diff --git a/.appveyor.yml b/.appveyor.yml index ebbce556e..210b3fa46 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,5 +1,3 @@ -os: Visual Studio 2015 - environment: matrix: - BUILD_ENV: msbuild @@ -14,6 +12,8 @@ for: 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" @@ -22,6 +22,8 @@ for: 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 diff --git a/.builds/alpine.yml b/.builds/alpine.yml deleted file mode 100644 index 9477671aa..000000000 --- a/.builds/alpine.yml +++ /dev/null @@ -1,25 +0,0 @@ -image: alpine/edge -packages: -- autoconf -- automake -- libtool -- eudev-dev -- libusb-dev -- linux-headers -sources: -- https://github.com/libusb/hidapi -tasks: -- setup: | - cd hidapi - ./bootstrap - ./configure -- build: | - cd hidapi - make - make DESTDIR=$PWD/root install - make clean -- build-manual: | - cd hidapi/linux - make -f Makefile-manual - cd ../libusb - make -f Makefile-manual diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml deleted file mode 100644 index 0f733100a..000000000 --- a/.builds/archlinux.yml +++ /dev/null @@ -1,24 +0,0 @@ -image: archlinux -packages: -- autoconf -- automake -- libtool -- libusb -- libudev0 -sources: -- https://github.com/libusb/hidapi -tasks: -- setup: | - cd hidapi - ./bootstrap - ./configure -- build: | - cd hidapi - make - make DESTDIR=$PWD/root install - make clean -- build-manual: | - cd hidapi/linux - make -f Makefile-manual - cd ../libusb - make -f Makefile-manual diff --git a/.builds/fedora-mingw.yml b/.builds/fedora-mingw.yml deleted file mode 100644 index 4effecf32..000000000 --- a/.builds/fedora-mingw.yml +++ /dev/null @@ -1,22 +0,0 @@ -image: fedora/latest -packages: -- autoconf -- automake -- libtool -- mingw64-gcc -- mingw64-gcc-c++ -sources: -- https://github.com/libusb/hidapi -tasks: -- setup: | - cd hidapi - ./bootstrap - mingw64-configure -- build: | - cd hidapi - make - make DESTDIR=$PWD/root install - make clean -- build-manual: | - cd hidapi/windows - make -f Makefile-manual OS=MINGW CC=x86_64-w64-mingw32-gcc diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 355dc4930..1679b03c3 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -6,18 +6,29 @@ packages: - libiconv - libtool - pkgconf +- cmake +- ninja sources: - https://github.com/libusb/hidapi tasks: -- setup: | +- configure: | cd hidapi + echo Configure Autotools build ./bootstrap ./configure -- build: | + 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 diff --git a/.builds/netbsd.yml b/.builds/netbsd.yml index a800e6087..413d91c02 100644 --- a/.builds/netbsd.yml +++ b/.builds/netbsd.yml @@ -7,7 +7,7 @@ packages: sources: - https://github.com/libusb/hidapi tasks: -- setup: | +- configure: | cd hidapi mkdir -p build install cmake -B build -S . -DCMAKE_INSTALL_PREFIX=install diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml new file mode 100644 index 000000000..780df7f66 --- /dev/null +++ b/.builds/openbsd.yml @@ -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 diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index c8bbc904c..4e01ac0c1 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -3,7 +3,8 @@ name: GitHub Builds on: [push, pull_request] env: - NIX_COMPILE_FLAGS: -Wall -Wextra -pedantic -Werror + NIX_COMPILE_FLAGS: -Wall -Wextra -pedantic -Werror + GNU_COMPILE_FLAGS: -Wall -Wextra -pedantic -Werror -Wformat-signedness MSVC_COMPILE_FLAGS: /W4 /WX jobs: @@ -12,7 +13,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install build tools run: brew install autoconf automake libtool - name: Configure Automake @@ -29,53 +30,91 @@ jobs: working-directory: mac run: make -f Makefile-manual + macos-cmake: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - 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_INSTALL_PREFIX=install/shared -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}" - cmake -B build/framework -S hidapisrc -DCMAKE_INSTALL_PREFIX=install/framework -DCMAKE_FRAMEWORK=ON -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}" + 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@v1 + 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" - allow_failure: true + 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@v2 + - uses: actions/checkout@v3 with: path: hidapisrc - name: Install dependencies run: | sudo apt update - sudo apt install libudev-dev libusb-1.0-0-dev + 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_INSTALL_PREFIX=install/shared -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}" - cmake -B build/static -S hidapisrc -DCMAKE_INSTALL_PREFIX=install/static -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}" + 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=${GNU_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=${GNU_COMPILE_FLAGS}" - name: Build CMake Shared working-directory: build/shared run: make install @@ -83,7 +122,7 @@ jobs: working-directory: build/static run: make install - name: Check artifacts - uses: andstor/file-existence-action@v1 + uses: andstor/file-existence-action@v2 with: files: "install/shared/lib/libhidapi-libusb.so, \ install/shared/lib/libhidapi-hidraw.so, \ @@ -93,89 +132,215 @@ jobs: install/static/lib/libhidapi-hidraw.a, \ install/static/include/hidapi/hidapi.h, \ install/static/include/hidapi/hidapi_libusb.h" - allow_failure: true + 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=${GNU_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=${GNU_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@v2 + - uses: actions/checkout@v3 with: path: hidapisrc + - name: Install dependencies + shell: cmd + run: | + choco install ninja + pip3 install meson + refreshenv - name: Configure CMake MSVC shell: cmd run: | - cmake -B build\msvc -S hidapisrc -DCMAKE_INSTALL_PREFIX=install\msvc -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%" + 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 . --target install - - name: Check artifacts MSVC - uses: andstor/file-existence-action@v1 + run: cmake --build . --config RelWithDebInfo --target install + - name: Check artifacts CMake 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" - allow_failure: true + fail: true + - name: Check CMake MSVC 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 --no-compress-output --output-on-failure - - name: Configure CMake NMake + - name: Configure CMake NMake MSVC 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_INSTALL_PREFIX=install\nmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%" - - name: Build CMake NMake + 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 MSVC 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@v1 + - name: Check artifacts CMake NMake MSVC + 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" - allow_failure: true + fail: true + - name: Check CMake NMake MSVC Export Package + 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 MSVC + working-directory: build\nmake + run: ctest --no-compress-output --output-on-failure + + - name: Configure CMake NMake ClangCL + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cmake -G"NMake Makefiles" -B build\clang_cl -S hidapisrc -D CMAKE_C_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_PP_DATA_DUMP=ON -DHIDAPI_ENABLE_ASAN=OFF -DCMAKE_INSTALL_PREFIX=install\clang_cl -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%" + - name: Build CMake NMake ClangCL + working-directory: build\clang_cl + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + nmake install + - name: Check artifacts CMake NMake ClangCL + uses: andstor/file-existence-action@v2 + with: + files: "install/clang_cl/lib/hidapi.lib, \ + install/clang_cl/bin/hidapi.dll, \ + install/clang_cl/include/hidapi/hidapi.h, \ + install/clang_cl/include/hidapi/hidapi_winapi.h" + fail: true + - name: Check CMake NMake ClangCL Export Package + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cmake ^ + -G"NMake Makefiles" ^ + -B build\clang_cl_test ^ + -S hidapisrc\hidtest ^ + -D CMAKE_C_COMPILER=clang-cl ^ + -Dhidapi_ROOT=install\clang_cl ^ + -DCMAKE_INSTALL_PREFIX=install\clang_cl_test ^ + "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%" + cd build\clang_cl_test + cmake --build . --target install + - name: Run CTest NMake ClangCL + shell: cmd + working-directory: build/clang_cl + run: ctest -C RelWithDebInfo --no-compress-output --output-on-failure - name: Configure CMake MinGW shell: cmd run: | - cmake -G"MinGW Makefiles" -B build\mingw -S hidapisrc -DCMAKE_INSTALL_PREFIX=install\mingw -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%NIX_COMPILE_FLAGS%" + 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=%GNU_COMPILE_FLAGS%" - name: Build CMake MinGW working-directory: build\mingw run: cmake --build . --target install - name: Check artifacts MinGW - uses: andstor/file-existence-action@v1 + 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" - allow_failure: true + 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=%GNU_COMPILE_FLAGS%" + cd build\mingw_test + cmake --build . --target install + - name: Run CTest MinGW + working-directory: build\mingw + run: ctest --no-compress-output --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@v2 + - uses: actions/checkout@v3 - uses: microsoft/setup-msbuild@v1.1 - - name: MSBuild x86 + - name: MSBuild x86 MSVC run: msbuild windows\hidapi.sln /p:Configuration=Release /p:Platform=Win32 - name: Check artifacts x86 - uses: andstor/file-existence-action@v1 + uses: andstor/file-existence-action@v2 with: files: "windows/Release/hidapi.dll, windows/Release/hidapi.lib, windows/Release/hidapi.pdb" - allow_failure: true - - name: MSBuild x64 + fail: true + - name: MSBuild x64 MSVC run: msbuild windows\hidapi.sln /p:Configuration=Release /p:Platform=x64 - name: Check artifacts x64 - uses: andstor/file-existence-action@v1 + uses: andstor/file-existence-action@v2 with: files: "windows/x64/Release/hidapi.dll, windows/x64/Release/hidapi.lib, windows/x64/Release/hidapi.pdb" - allow_failure: true + fail: true - name: Gather artifacts run: | md artifacts @@ -186,8 +351,230 @@ jobs: 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 + uses: actions/upload-artifact@v4 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=${GNU_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=${GNU_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=${GNU_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=${GNU_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 glibc lib32-glibc 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=${GNU_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=${GNU_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=${GNU_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=${GNU_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: ${GNU_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 diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 000000000..4566a430a --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,198 @@ +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@v4 + with: + name: coverity-logs-windows + path: build/cov-int + retention-days: 7 + + + coverity-macos: + runs-on: macos-13 + 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@v4 + 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@v4 + 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 update + 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@v4 + 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@v4 + with: + name: coverity-logs-windows-macos-linux + path: build/cov-int + retention-days: 7 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 000000000..a9d604d28 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -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@v4 + 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@v4 + 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 diff --git a/.gitignore b/.gitignore index 24c4c2e51..048900e28 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ ar-lib autom4te.cache/ config.* configure +configure~ compile depcomp install-sh @@ -26,3 +27,6 @@ libtool # Qt Creator CMakeLists.txt.user + +# doxgen output +doxygen/html/ diff --git a/AUTHORS.txt b/AUTHORS.txt index 7193d71e0..7c2a03584 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -11,7 +11,7 @@ Ludovic Rousseau : Correctness fixes libusb/hidapi Team: - Development/maintainance since June 4th 2019 + Development/maintenance since June 4th 2019 For a comprehensive list of contributions, see the commit list at github: https://github.com/libusb/hidapi/graphs/contributors diff --git a/BUILD.autotools.md b/BUILD.autotools.md index 24b20a5af..34cf56aaa 100644 --- a/BUILD.autotools.md +++ b/BUILD.autotools.md @@ -46,7 +46,9 @@ A simple command list, to build HIDAPI with Autotools as a _shared library_ and ```sh ./bootstrap # this prepares the configure script -./configure +mkdir build +cd build # in-source builds are not recommended and known to be broken in some cases (https://github.com/libusb/hidapi/issues/621) +../configure make # build the library make install # as root, or using sudo, this will install hidapi into your system ``` diff --git a/BUILD.cmake.md b/BUILD.cmake.md index 364c815e3..573f910de 100644 --- a/BUILD.cmake.md +++ b/BUILD.cmake.md @@ -16,7 +16,7 @@ most of this document may not be of interest for you; just check variables names 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, +On most \*nix systems, the preferred 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), @@ -88,6 +88,8 @@ Some of the [standard](https://cmake.org/cmake/help/latest/manual/cmake-variable 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;
Linux-specific variables @@ -157,7 +159,7 @@ endif() 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) +cmake_minimum_required(VERSION 3.4.3...3.25 FATAL_ERROR) add_subdirectory(hidapi) add_subdirectory(my_application) @@ -212,7 +214,7 @@ This is done to let the host project's developer decide what is important (what 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_include` - the interface library; `hidapi::include` 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; @@ -231,3 +233,48 @@ Advanced: 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 -B "/static" -DCMAKE_INSTALL_PREFIX= -DBUILD_SHARED_LIBS=FALSE +cmake --build "/static" +# Shared libraries +cmake -S -B "/shared" -DCMAKE_INSTALL_PREFIX= -DBUILD_SHARED_LIBS=TRUE +cmake --build "/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 "/static" +# Shared libraries +cmake --install "/shared" + +``` diff --git a/BUILD.md b/BUILD.md index e348e3caf..d7a3546f6 100644 --- a/BUILD.md +++ b/BUILD.md @@ -14,32 +14,38 @@ ## Intro -For various reasons you may need to build HIDAPI on your own. +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 [manual makefiles](#building-the-manual-way-on-unix-platforms); +- using `Meson` (requires CMake); -**Autotools** build system is historically first mature build system for -HIDAPI. Most common usage of it is in its separate README: [BUILD.autotools.md](BUILD.autotools.md).
+**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).
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 uses the power of CMake for its advantage. +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.
+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 system you choose to use, there are specific dependencies for each platform/backend. +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 +additional development packages. For `linux/hidraw` backend, you need a development package for `libudev`. For `libusb` backend, naturally, you need `libusb` development package. @@ -53,7 +59,7 @@ sudo apt install libusb-1.0-0-dev ### FreeBSD: -On FreeBSD you will need to install libiconv. This is done by running +On FreeBSD, you will need to install libiconv. This is done by running the following: ```sh pkg_add -r libiconv @@ -61,11 +67,11 @@ pkg_add -r libiconv ### Mac: -On Mac make sure you have XCode installed and its Command Line Tools. +Make sure you have XCode installed and its Command Line Tools. ### Windows: -On Windows you just need a compiler. You may use Visual Studio or Cygwin/MinGW, +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 @@ -89,7 +95,7 @@ depending on your platform and the backend you want to use: - 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 `/hid.c` and `hidapi/hidapi.h` is enough to build HIDAPI. -The only guarantee that `/hid.c` includes all nesessary sources to compile it as a single file. +The only guarantee that `/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. @@ -100,7 +106,7 @@ 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 to the directory +To build HIDAPI using the manual Makefiles, change the directory of your platform and run make. For example, on Linux run: ```sh cd linux/ @@ -112,7 +118,7 @@ make -f Makefile-manual 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 a general Autotools +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). diff --git a/CMakeLists.txt b/CMakeLists.txt index b279a3601..d7086813c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ -cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1.3...3.25 FATAL_ERROR) if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) add_subdirectory(src) - # compatinility with find_package() vs add_subdirectory + # compatibility with find_package() vs add_subdirectory set(hidapi_VERSION "${hidapi_VERSION}" PARENT_SCOPE) return() endif() @@ -42,6 +42,9 @@ elseif(NOT WIN32) option(HIDAPI_WITH_HIDRAW "Build HIDRAW-based implementation of HIDAPI" ON) option(HIDAPI_WITH_LIBUSB "Build LIBUSB-based implementation of HIDAPI" ON) endif() + if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + option(HIDAPI_WITH_NETBSD "Build NetBSD/UHID implementation of HIDAPI" ON) + endif() endif() option(BUILD_SHARED_LIBS "Build shared version of the libraries, otherwise build statically" ON) @@ -49,13 +52,57 @@ option(BUILD_SHARED_LIBS "Build shared version of the libraries, otherwise build set(HIDAPI_INSTALL_TARGETS ON) set(HIDAPI_PRINT_VERSION ON) -add_subdirectory(src) - -set(BUILD_HIDTEST_DEFAULT OFF) +set(IS_DEBUG_BUILD OFF) if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(BUILD_HIDTEST_DEFAULT ON) + 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() -option(HIDAPI_BUILD_HIDTEST "Build small console test application hidtest" ${BUILD_HIDTEST_DEFAULT}) + +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() diff --git a/HACKING.txt b/HACKING.txt index eae6cb09c..e06b533aa 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -4,8 +4,16 @@ Updating a Version: 1. Update VERSION file. 2. HID_API_VERSION_MAJOR/HID_API_VERSION_MINOR/HID_API_VERSION_PATCH in hidapi.h. +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. Build hidapi.dll/.lib for x86/x64. -3. Upload Windows binaries to Github release page. -4. Make sure to tag the release as: `hidapi-`, where as in VERSION file. +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-` +5. Push newly created tag: `git push origin hidapi-` +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. diff --git a/README.md b/README.md index 22886aae7..45e17360f 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,10 @@ | 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) | -| `Linux/BSD, last build (branch/PR)` | [![builds.sr.ht status](https://builds.sr.ht/~z3ntu/hidapi.svg)](https://builds.sr.ht/~z3ntu/hidapi) | +| `Linux/macOS/Windows (master)` | [![GitHub Builds](https://github.com/libusb/hidapi/actions/workflows/builds.yml/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. @@ -97,7 +98,7 @@ device spec. Writing data (`hid_write`) at random to your HID devices can break ```c #include // printf -#include // wprintf +#include // wchar_t #include @@ -117,22 +118,27 @@ int main(int argc, char* argv[]) // 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); - wprintf(L"Manufacturer String: %s\n", wstr); + printf("Manufacturer String: %ls\n", wstr); // Read the Product String res = hid_get_product_string(handle, wstr, MAX_STR); - wprintf(L"Product String: %s\n", wstr); + printf("Product String: %ls\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); + printf("Serial Number String: (%d) %ls\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); + printf("Indexed String 1: %ls\n", wstr); // Toggle LED (cmd 0x80). The first byte is the report number (0x0). buf[0] = 0x0; diff --git a/VERSION b/VERSION index ac454c6a1..7092c7c46 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.12.0 +0.15.0 \ No newline at end of file diff --git a/configure.ac b/configure.ac index 5d05e45bc..1b2051052 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,7 @@ case $host in backend="mac" os="darwin" threads="pthreads" - LIBS="${LIBS} -framework IOKit -framework CoreFoundation -framework AppKit" + LIBS="${LIBS} -framework IOKit -framework CoreFoundation" ;; *-freebsd*) AC_MSG_RESULT([ (FreeBSD back-end)]) @@ -123,6 +123,7 @@ case $host in os="windows" threads="windows" win_implementation="mingw" + LDFLAGS="${LDFLAGS} -static-libgcc" ;; *-msys*) AC_MSG_RESULT([ (Windows back-end, using MSYS2)]) @@ -130,6 +131,7 @@ case $host in os="windows" threads="windows" win_implementation="mingw" + LDFLAGS="${LDFLAGS} -static-libgcc" ;; *-cygwin*) AC_MSG_RESULT([ (Windows back-end, using Cygwin)]) diff --git a/dist/hidapi.podspec b/dist/hidapi.podspec index b2f061b7a..8588514ad 100644 --- a/dist/hidapi.podspec +++ b/dist/hidapi.podspec @@ -22,10 +22,10 @@ Pod::Spec.new do |spec| spec.source = { :git => "https://github.com/libusb/hidapi.git", :tag => "hidapi-#{spec.version}" } - spec.source_files = "mac/hid.c", "hidapi/hidapi.h" + spec.source_files = "mac/hid.c", "hidapi/hidapi.h", "mac/hidapi_darwin.h" - spec.public_header_files = "hidapi/hidapi.h" + spec.public_header_files = "hidapi/hidapi.h", "mac/hidapi_darwin.h" - spec.frameworks = "IOKit", "CoreFoundation", "AppKit" + spec.frameworks = "IOKit", "CoreFoundation" end diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile index b1ea0a223..4e01360e0 100644 --- a/doxygen/Doxyfile +++ b/doxygen/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.15 +# Doxyfile 1.9.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -12,6 +12,16 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -60,16 +70,28 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes -# performance problems for the file system. +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode @@ -81,26 +103,18 @@ ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all generated output in the proper direction. -# Possible values are: None, LTR, RTL and Context. -# The default value is: None. - -OUTPUT_TEXT_DIRECTION = None - # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -160,7 +174,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = ../ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -187,6 +201,16 @@ SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus @@ -207,6 +231,14 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. @@ -230,25 +262,19 @@ TAB_SIZE = 8 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all @@ -289,19 +315,22 @@ OPTIMIZE_OUTPUT_SLICE = NO # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is -# Fortran), use: inc=Fortran f=C. +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = @@ -319,10 +348,10 @@ MARKDOWN_SUPPORT = NO # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 0. +# Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. -TOC_INCLUDE_HEADINGS = 0 +TOC_INCLUDE_HEADINGS = 5 # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can @@ -435,6 +464,19 @@ TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -455,6 +497,12 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = NO +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -492,6 +540,13 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -503,14 +558,15 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO, these declarations will be -# included in the documentation. +# declarations. If set to NO, these declarations will be included in the +# documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO @@ -529,12 +585,20 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. -# The default value is: system dependent. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = YES @@ -552,6 +616,12 @@ HIDE_SCOPE_NAMES = NO HIDE_COMPOUND_REFERENCE= NO +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -709,7 +779,8 @@ FILE_VERSION_FILTER = # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE @@ -755,24 +826,43 @@ WARNINGS = YES WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = NO +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO @@ -783,13 +873,27 @@ WARN_AS_ERROR = NO # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = @@ -803,17 +907,29 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../hidapi +INPUT = ../hidapi \ + ./main_page.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. @@ -822,11 +938,15 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = @@ -865,25 +985,27 @@ EXCLUDE_PATTERNS = # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test +# ANamespace::AClass, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = HID_API_AS_STR_IMPL \ + HID_API_AS_STR \ + HID_API_TO_VERSION_STR # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = ../hidtest # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = *.c # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands @@ -913,6 +1035,11 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. @@ -952,7 +1079,16 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = main_page.md + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1040,6 +1176,46 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1051,17 +1227,11 @@ VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1140,7 +1310,12 @@ HTML_STYLESHEET = # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1155,9 +1330,22 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1167,7 +1355,7 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1196,9 +1384,9 @@ HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that -# are dynamically created via Javascript. If disabled, the navigation index will +# are dynamically created via JavaScript. If disabled, the navigation index will # consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have Javascript, +# page. Disable this option to support browsers that do not have JavaScript, # like the Qt help browser. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1228,10 +1416,11 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. @@ -1248,6 +1437,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1273,8 +1469,12 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1304,7 +1504,7 @@ CHM_FILE = HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated -# (YES) or that it should be included in the master .chm file (NO). +# (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1349,7 +1549,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1357,8 +1558,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1366,30 +1567,30 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1432,16 +1633,28 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # @@ -1466,6 +1679,24 @@ TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML @@ -1475,19 +1706,14 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. -FORMULA_TRANSPARENT = YES +FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# https://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side JavaScript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1497,11 +1723,29 @@ FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1514,22 +1758,29 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1557,7 +1808,7 @@ MATHJAX_CODEFILE = SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a web server instead of a web client using Javascript. There +# implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH # setting. When disabled, doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing @@ -1576,7 +1827,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1589,8 +1841,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -1661,10 +1914,11 @@ LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex # The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to -# generate index for LaTeX. +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. # Note: This tag is used in the generated output file (.tex). # See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. -# The default value is: \makeindex. +# The default value is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_MAKEINDEX_CMD = \makeindex @@ -1684,7 +1938,7 @@ COMPACT_LATEX = NO # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just @@ -1698,29 +1952,31 @@ PAPER_TYPE = a4wide EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = @@ -1753,9 +2009,11 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES, to get a -# higher quality PDF documentation. +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1763,8 +2021,7 @@ USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode # command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. +# if errors occur, instead of asking the user for help. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1777,16 +2034,6 @@ LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. @@ -1867,16 +2114,6 @@ RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_RTF is set to YES. - -RTF_SOURCE_CODE = NO - #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- @@ -1973,15 +2210,6 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -2068,7 +2296,8 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2156,34 +2385,10 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2216,35 +2421,50 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_COMMON_ATTR = "fontname=FreeSans.ttf,fontsize=10" + +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = FreeSans.ttf +DOT_EDGE_ATTR = "labelfontname=FreeSans.ttf,labelfontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a +# graph for each documented class showing the direct and indirect inheritance +# relations. In case HAVE_DOT is set as well dot will be used to draw the graph, +# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set +# to TEXT the direct and indirect inheritance relations will be shown as texts / +# links. +# Possible values are: NO, YES, TEXT and GRAPH. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES @@ -2258,7 +2478,8 @@ CLASS_GRAPH = YES COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# groups, showing the direct groups dependencies. See also the chapter Grouping +# in the manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2281,10 +2502,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2351,6 +2594,13 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: @@ -2404,10 +2654,10 @@ MSCFILE_DIRS = DIAFILE_DIRS = # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = @@ -2445,18 +2695,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2469,14 +2707,18 @@ DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES diff --git a/doxygen/main_page.md b/doxygen/main_page.md new file mode 100644 index 000000000..ff11e9adb --- /dev/null +++ b/doxygen/main_page.md @@ -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. diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index 959c9122a..62ca8a80e 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -7,7 +7,7 @@ libusb/hidapi Team - Copyright 2022, 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,13 +29,17 @@ #include +/* #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 - #define HID_API_EXPORT /**< API export macro */ - #define HID_API_CALL /**< API call macro */ + #endif #endif +#ifndef HID_API_EXPORT + #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*/ @@ -48,7 +52,7 @@ @ingroup API */ -#define HID_API_VERSION_MINOR 12 +#define HID_API_VERSION_MINOR 15 /** @brief Static/compile-time patch version of the library. @ingroup API @@ -66,7 +70,9 @@ 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 */ @@ -88,18 +94,58 @@ */ #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 + /** A structure to hold the version numbers. */ struct hid_api_version { - int major; - int minor; - int patch; + 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 */ + /** @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 */ @@ -126,15 +172,18 @@ extern "C" { /** 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 on the Mac implementation if and only if the device - is a USB HID device. */ + Valid only if the device is a USB HID device. + Set to -1 in all other cases. + */ int interface_number; /** 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; }; @@ -151,6 +200,7 @@ extern "C" { @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); @@ -162,7 +212,7 @@ extern "C" { @ingroup API - @returns + @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_exit(void); @@ -182,21 +232,25 @@ extern "C" { @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); @@ -206,17 +260,19 @@ extern "C" { If @p serial_number is NULL, the first device with the specified VID and PID is opened. - This function sets the return value of hid_error(). - @ingroup API @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); @@ -226,14 +282,16 @@ extern "C" { platform-specific path name can be used (eg: /dev/hidraw0 on Linux). - This function sets the return value of hid_error(). - @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); @@ -249,11 +307,9 @@ extern "C" { single report), followed by the report data (16 bytes). In this example, the length passed in would be 17. - hid_write() will send the data on the first OUT endpoint, if - one exists. If it does not, it will send the data through - the Control Endpoint (Endpoint 0). - - This function sets the return value of hid_error(). + hid_write() will send the data on the first interrupt OUT + endpoint, if one exists. If it does not the behaviour is as + @ref hid_send_output_report @ingroup API @param dev A device handle returned from hid_open(). @@ -264,6 +320,7 @@ extern "C" { @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); @@ -273,8 +330,6 @@ extern "C" { to the host through the INTERRUPT IN endpoint. The first byte will contain the Report number if the device uses numbered reports. - This function sets the return value of hid_error(). - @ingroup API @param dev A device handle returned from hid_open(). @param data A buffer to put the read data into. @@ -285,7 +340,9 @@ extern "C" { @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); @@ -293,11 +350,9 @@ extern "C" { /** @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. - This function sets the return value of hid_error(). - @ingroup API @param dev A device handle returned from hid_open(). @param data A buffer to put the read data into. @@ -307,7 +362,9 @@ extern "C" { @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); @@ -329,6 +386,7 @@ extern "C" { @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); @@ -347,8 +405,6 @@ extern "C" { report data (16 bytes). In this example, the length passed in would be 17. - This function sets the return value of hid_error(). - @ingroup API @param dev A device handle returned from hid_open(). @param data The data to send, including the report number as @@ -359,6 +415,7 @@ extern "C" { @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); @@ -370,8 +427,6 @@ extern "C" { still contain the Report ID, and the report data will start in data[1]. - This function sets the return value of hid_error(). - @ingroup API @param dev A device handle returned from hid_open(). @param data A buffer to put the read data into, including @@ -386,9 +441,44 @@ extern "C" { 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 Send a Output report to the device. + + Since version 0.15.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 15, 0) + + Output reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_output_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_output_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + This function sets the return value of hid_error(). + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + + @see @ref hid_write + */ + int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device* dev, const 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) @@ -400,7 +490,7 @@ extern "C" { start in data[1]. @ingroup API - @param device A device handle returned from hid_open(). + @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 @@ -413,13 +503,12 @@ extern "C" { 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. - This function sets the return value of hid_error(). - @ingroup API @param dev A device handle returned from hid_open(). */ @@ -434,6 +523,7 @@ extern "C" { @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); @@ -446,6 +536,7 @@ extern "C" { @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); @@ -458,9 +549,27 @@ extern "C" { @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 @@ -471,32 +580,58 @@ extern "C" { @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 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 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. - Whether a function sets the last error is noted in its - documentation. These functions will reset the last error - to NULL before their execution. + 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. - Strings returned from hid_error() must not be freed by the user! + 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. - This function is thread-safe, and error messages are thread-local. + 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() itself). + (e.g. for errors in hid_open() or hid_enumerate()). @returns - This function returns a string containing the last error - which occurred or NULL if none has occurred. + A string describing the last error (if any). */ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev); /** @brief Get a runtime version of the library. + This function is thread-safe. + @ingroup API @returns @@ -507,6 +642,8 @@ extern "C" { /** @brief Get a runtime version string of the library. + This function is thread-safe. + @ingroup API @returns @@ -519,4 +656,3 @@ extern "C" { #endif #endif - diff --git a/hidtest/CMakeLists.txt b/hidtest/CMakeLists.txt index 717ffec03..19c50e1fb 100644 --- a/hidtest/CMakeLists.txt +++ b/hidtest/CMakeLists.txt @@ -1,5 +1,21 @@ +cmake_minimum_required(VERSION 3.1.3...3.25 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) diff --git a/hidtest/test.c b/hidtest/test.c index 157ce6f90..4ac09a16e 100644 --- a/hidtest/test.c +++ b/hidtest/test.c @@ -1,12 +1,13 @@ /******************************************************* - Windows HID simplification + HIDAPI - Multi-Platform library for + communication with HID devices. Alan Ott Signal 11 Software - 8/22/2009 + libusb/hidapi Team - Copyright 2009 + Copyright 2022. This contents of this file may be used by anyone for any reason without any conditions and may be @@ -51,11 +52,106 @@ #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: %u (%s)\n", (unsigned)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: "); +#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 14, 0) + res = hid_get_report_descriptor(device, descriptor, sizeof(descriptor)); +#else + (void)res; +#endif + 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; + /* --- HIDAPI R&D: this is just to force the compiler to ensure + each of those functions are implemented (even as a stub) + by each backend. --- */ + (void)&hid_open; + (void)&hid_open_path; + (void)&hid_read_timeout; + (void)&hid_get_input_report; +#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 15, 0) + (void)&hid_send_output_report; +#endif + (void)&hid_get_feature_report; + (void)&hid_send_feature_report; +#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 14, 0) + (void)&hid_get_report_descriptor; +#endif + /* --- */ + int res; unsigned char buf[256]; #define MAX_STR 255 @@ -63,7 +159,7 @@ int main(int argc, char* argv[]) hid_device *handle; int i; - struct hid_device_info *devs, *cur_dev; + 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)) { @@ -83,18 +179,7 @@ int main(int argc, char* argv[]) #endif 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(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page); - printf("\n"); - cur_dev = cur_dev->next; - } + print_devices_with_descriptor(devs); hid_free_enumeration(devs); // Set up the command buffer. @@ -109,6 +194,7 @@ int main(int argc, char* argv[]) handle = hid_open(0x4d8, 0x3f, NULL); if (!handle) { printf("unable to open device\n"); + hid_exit(); return 1; } @@ -131,8 +217,16 @@ int main(int argc, char* argv[]) 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"); + 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; @@ -165,8 +259,7 @@ int main(int argc, char* argv[]) 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)); + printf("Unable to get a feature report: %ls\n", hid_error(handle)); } else { // Print out the returned buffer. @@ -183,8 +276,7 @@ int main(int argc, char* argv[]) buf[1] = 0x80; res = hid_write(handle, buf, 17); if (res < 0) { - printf("Unable to write()\n"); - printf("Error: %ls\n", hid_error(handle)); + printf("Unable to write(): %ls\n", hid_error(handle)); } @@ -192,31 +284,45 @@ int main(int argc, char* argv[]) buf[0] = 0x1; buf[1] = 0x81; hid_write(handle, buf, 17); - if (res < 0) - printf("Unable to write() (2)\n"); + 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) + if (res == 0) { printf("waiting...\n"); - if (res < 0) - printf("Unable to read()\n"); - #ifdef _WIN32 + } + 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 +#else usleep(500*1000); - #endif +#endif } - printf("Data read:\n "); - // Print out the returned buffer. - for (i = 0; i < res; i++) - printf("%02x ", (unsigned int) buf[i]); - printf("\n"); + 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); diff --git a/libusb/CMakeLists.txt b/libusb/CMakeLists.txt index e5d7d5180..4c458c569 100644 --- a/libusb/CMakeLists.txt +++ b/libusb/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR) list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_libusb.h") @@ -22,11 +22,53 @@ target_link_libraries(hidapi_libusb PRIVATE Threads::Threads) if(HIDAPI_NO_ICONV) target_compile_definitions(hidapi_libusb PRIVATE NO_ICONV) else() - if(NOT ANDROID AND NOT CMAKE_VERSION VERSION_LESS 3.11) - find_package(Iconv REQUIRED) + if(NOT ANDROID) include(CheckCSourceCompiles) - target_link_libraries(hidapi_libusb PRIVATE Iconv::Iconv) - set(CMAKE_REQUIRED_LIBRARIES "Iconv::Iconv") + + 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 + #include + int main() { + char *a, *b; + size_t i, j; + iconv_t ic; + ic = iconv_open(\"to\", \"from\"); + iconv(ic, &a, &i, &b, &j); + iconv_close(ic); + } + " + Iconv_EXPLICITLY_AT_ENV) + if(Iconv_EXPLICITLY_AT_ENV) + message(STATUS "Iconv Explicitly check '-liconv' - Available") + target_link_libraries(hidapi_libusb PRIVATE iconv) + else() + message(FATAL_ERROR "Iconv is not found, make sure to provide it in the build environment") + endif() + endif() + else() + # otherwise there is 2 options: + # 1) iconv is provided by Standard C library and the build will be just fine + # 2) The _user_ has to provide additional compilation options for this project/target + endif() + # check for error: "conflicting types for 'iconv'" check_c_source_compiles("#include extern size_t iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); @@ -35,11 +77,9 @@ else() 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() - # otherwise there is 3 options: - # 1) On Android Iconv is disabled on the code level anyway, so no issue; - # 2) iconv is provided by Standard C library and the build will be just fine; - # 4) The _user_ has to provide additiona compilation options for this project/target. endif() set_target_properties(hidapi_libusb diff --git a/libusb/hid.c b/libusb/hid.c index 3103f037d..a48ea9bfa 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -37,7 +37,6 @@ #include #include #include -#include #include /* GNU / LibUSB */ @@ -51,66 +50,10 @@ #include "hidapi_libusb.h" -#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__ - -/* Barrier implementation because Android/Bionic don't have pthread_barrier. - This implementation came from Brent Priddy and was posted on - StackOverflow. It is used with his permission. */ -typedef int pthread_barrierattr_t; -typedef struct pthread_barrier { - pthread_mutex_t mutex; - pthread_cond_t cond; - int count; - int trip_count; -} pthread_barrier_t; - -static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) -{ - if(count == 0) { - errno = EINVAL; - return -1; - } - - if(pthread_mutex_init(&barrier->mutex, 0) < 0) { - return -1; - } - if(pthread_cond_init(&barrier->cond, 0) < 0) { - pthread_mutex_destroy(&barrier->mutex); - return -1; - } - barrier->trip_count = count; - barrier->count = 0; - - return 0; -} - -static int pthread_barrier_destroy(pthread_barrier_t *barrier) -{ - pthread_cond_destroy(&barrier->cond); - pthread_mutex_destroy(&barrier->mutex); - return 0; -} - -static int pthread_barrier_wait(pthread_barrier_t *barrier) -{ - pthread_mutex_lock(&barrier->mutex); - ++(barrier->count); - if(barrier->count >= barrier->trip_count) - { - barrier->count = 0; - pthread_cond_broadcast(&barrier->cond); - pthread_mutex_unlock(&barrier->mutex); - return 1; - } - else - { - pthread_cond_wait(&barrier->cond, &(barrier->mutex)); - pthread_mutex_unlock(&barrier->mutex); - return 0; - } -} - +#ifndef HIDAPI_THREAD_MODEL_INCLUDE +#define HIDAPI_THREAD_MODEL_INCLUDE "hidapi_thread_pthread.h" #endif +#include HIDAPI_THREAD_MODEL_INCLUDE #ifdef __cplusplus extern "C" { @@ -146,27 +89,29 @@ struct hid_device_ { /* Handle to the actual device. */ libusb_device_handle *device_handle; + /* USB Configuration Number of the device */ + int config_number; + /* The interface number of the HID */ + int interface; + + uint16_t report_descriptor_size; + /* Endpoint information */ int input_endpoint; int output_endpoint; int input_ep_max_packet_size; - /* The interface number of the HID */ - int interface; - /* Indexes of Strings */ int manufacturer_index; int product_index; int serial_index; + struct hid_device_info* device_info; /* Whether blocking reads are used */ int blocking; /* boolean */ /* Read thread objects */ - pthread_t thread; - pthread_mutex_t mutex; /* Protects input_reports */ - pthread_cond_t condition; - pthread_barrier_t barrier; /* Ensures correct startup sequence */ + hidapi_thread_state thread_state; int shutdown_thread; int transfer_loop_finished; struct libusb_transfer *transfer; @@ -196,9 +141,7 @@ static hid_device *new_hid_device(void) hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); dev->blocking = 1; - pthread_mutex_init(&dev->mutex, NULL); - pthread_cond_init(&dev->condition, NULL); - pthread_barrier_init(&dev->barrier, NULL, 2); + hidapi_thread_state_init(&dev->thread_state); return dev; } @@ -206,9 +149,9 @@ static hid_device *new_hid_device(void) static void free_hid_device(hid_device *dev) { /* Clean up the thread objects */ - pthread_barrier_destroy(&dev->barrier); - pthread_cond_destroy(&dev->condition); - pthread_mutex_destroy(&dev->mutex); + hidapi_thread_state_destroy(&dev->thread_state); + + hid_free_enumeration(dev->device_info); /* Free the device itself */ free(dev); @@ -222,7 +165,6 @@ static void register_error(hid_device *dev, const char *op) } #endif -#ifdef INVASIVE_GET_USAGE /* Get bytes from a HID Report Descriptor. Only call with a num_bytes of 0, 1, 2, or 4. */ static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) @@ -308,8 +250,16 @@ static int get_usage(uint8_t *report_descriptor, size_t size, //printf("Usage Page: %x\n", (uint32_t)*usage_page); } if (key_cmd == 0x8) { - *usage = get_bytes(report_descriptor, size, data_len, i); - usage_found = 1; + if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */ + *usage_page = get_bytes(report_descriptor, size, 2, i + 2); + usage_page_found = 1; + *usage = get_bytes(report_descriptor, size, 2, i); + usage_found = 1; + } + else { + *usage = get_bytes(report_descriptor, size, data_len, i); + usage_found = 1; + } //printf("Usage: %x\n", (uint32_t)*usage); } @@ -322,7 +272,6 @@ static int get_usage(uint8_t *report_descriptor, size_t size, return -1; /* failure */ } -#endif /* INVASIVE_GET_USAGE */ #if defined(__FreeBSD__) && __FreeBSD__ < 10 /* The libusb version included in FreeBSD < 10 doesn't have this function. In @@ -484,9 +433,14 @@ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) return str; } -static char *make_path(libusb_device *dev, int interface_number, int config_number) +/** + Max length of the result: "000-000.000.000.000.000.000.000:000.000" (39 chars). + 64 is used for simplicity/alignment. +*/ +static void get_path(char (*result)[64], libusb_device *dev, int config_number, int interface_number) { - char str[64]; /* max length "000-000.000.000.000.000.000.000:000.000" */ + char *str = *result; + /* Note that USB3 port count limit is 7; use 8 here for alignment */ uint8_t port_numbers[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int num_ports = libusb_get_port_numbers(dev, port_numbers, 8); @@ -499,7 +453,7 @@ static char *make_path(libusb_device *dev, int interface_number, int config_numb n += snprintf(&str[n], sizeof(":000.000"), ":%u.%u", (uint8_t)config_number, (uint8_t)interface_number); str[n] = '\0'; } else { - /* USB3.0 specs limit number of ports to 7 and buffer size here is 8 */ + /* Likely impossible, but check: USB3.0 specs limit number of ports to 7 and buffer size here is 8 */ if (num_ports == LIBUSB_ERROR_OVERFLOW) { LOG("make_path() failed. buffer overflow error\n"); } else { @@ -507,15 +461,21 @@ static char *make_path(libusb_device *dev, int interface_number, int config_numb } str[0] = '\0'; } +} + +static char *make_path(libusb_device *dev, int config_number, int interface_number) +{ + char str[64]; + get_path(&str, dev, config_number, interface_number); return strdup(str); } -HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version() +HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) { return &api_version; } -HID_API_EXPORT const char* HID_API_CALL hid_version_str() +HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) { return HID_API_VERSION_STR; } @@ -548,11 +508,287 @@ int HID_API_EXPORT hid_exit(void) return 0; } +static int hid_get_report_descriptor_libusb(libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size, unsigned char *buf, size_t buf_size) +{ + unsigned char tmp[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + + if (expected_report_descriptor_size > HID_API_MAX_REPORT_DESCRIPTOR_SIZE) + expected_report_descriptor_size = HID_API_MAX_REPORT_DESCRIPTOR_SIZE; + + /* Get the HID Report Descriptor. + See USB HID Specification, section 7.1.1 + */ + int res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8), interface_num, tmp, expected_report_descriptor_size, 5000); + if (res < 0) { + LOG("libusb_control_transfer() for getting the HID Report descriptor failed with %d: %s\n", res, libusb_error_name(res)); + return -1; + } + + if (res > (int)buf_size) + res = (int)buf_size; + + memcpy(buf, tmp, (size_t)res); + return res; +} + +/** + * Requires an opened device with *claimed interface*. + */ +static void fill_device_info_usage(struct hid_device_info *cur_dev, libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size) +{ + unsigned char hid_report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + unsigned short page = 0, usage = 0; + + int res = hid_get_report_descriptor_libusb(handle, interface_num, expected_report_descriptor_size, hid_report_descriptor, sizeof(hid_report_descriptor)); + if (res >= 0) { + /* Parse the usage and usage page + out of the report descriptor. */ + get_usage(hid_report_descriptor, res, &page, &usage); + } + + cur_dev->usage_page = page; + cur_dev->usage = usage; +} + +#ifdef INVASIVE_GET_USAGE +static void invasive_fill_device_info_usage(struct hid_device_info *cur_dev, libusb_device_handle *handle, int interface_num, uint16_t report_descriptor_size) +{ + int res = 0; + +#ifdef DETACH_KERNEL_DRIVER + int detached = 0; + /* Usage Page and Usage */ + res = libusb_kernel_driver_active(handle, interface_num); + if (res == 1) { + res = libusb_detach_kernel_driver(handle, interface_num); + if (res < 0) + LOG("Couldn't detach kernel driver, even though a kernel driver was attached.\n"); + else + detached = 1; + } +#endif + + res = libusb_claim_interface(handle, interface_num); + if (res >= 0) { + fill_device_info_usage(cur_dev, handle, interface_num, report_descriptor_size); + + /* Release the interface */ + res = libusb_release_interface(handle, interface_num); + if (res < 0) + LOG("Can't release the interface.\n"); + } + else + LOG("Can't claim interface: (%d) %s\n", res, libusb_error_name(res)); + +#ifdef DETACH_KERNEL_DRIVER + /* Re-attach kernel driver if necessary. */ + if (detached) { + res = libusb_attach_kernel_driver(handle, interface_num); + if (res < 0) + LOG("Couldn't re-attach kernel driver.\n"); + } +#endif +} +#endif /* INVASIVE_GET_USAGE */ + +/** + * Create and fill up most of hid_device_info fields. + * usage_page/usage is not filled up. + */ +static struct hid_device_info * create_device_info_for_device(libusb_device *device, libusb_device_handle *handle, struct libusb_device_descriptor *desc, int config_number, int interface_num) +{ + struct hid_device_info *cur_dev = calloc(1, sizeof(struct hid_device_info)); + if (cur_dev == NULL) { + return NULL; + } + + /* VID/PID */ + cur_dev->vendor_id = desc->idVendor; + cur_dev->product_id = desc->idProduct; + + cur_dev->release_number = desc->bcdDevice; + + cur_dev->interface_number = interface_num; + + cur_dev->bus_type = HID_API_BUS_USB; + + cur_dev->path = make_path(device, config_number, interface_num); + + if (!handle) { + return cur_dev; + } + + if (desc->iSerialNumber > 0) + cur_dev->serial_number = get_usb_string(handle, desc->iSerialNumber); + + /* Manufacturer and Product strings */ + if (desc->iManufacturer > 0) + cur_dev->manufacturer_string = get_usb_string(handle, desc->iManufacturer); + if (desc->iProduct > 0) + cur_dev->product_string = get_usb_string(handle, desc->iProduct); + + return cur_dev; +} + +static uint16_t get_report_descriptor_size_from_interface_descriptors(const struct libusb_interface_descriptor *intf_desc) +{ + int i = 0; + int found_hid_report_descriptor = 0; + uint16_t result = HID_API_MAX_REPORT_DESCRIPTOR_SIZE; + const unsigned char *extra = intf_desc->extra; + int extra_length = intf_desc->extra_length; + + /* + "extra" contains a HID descriptor + See section 6.2.1 of HID 1.1 specification. + */ + + while (extra_length >= 2) { /* Descriptor header: bLength/bDescriptorType */ + if (extra[1] == LIBUSB_DT_HID) { /* bDescriptorType */ + if (extra_length < 6) { + LOG("Broken HID descriptor: not enough data\n"); + break; + } + unsigned char bNumDescriptors = extra[5]; + if (extra_length < (6 + 3 * bNumDescriptors)) { + LOG("Broken HID descriptor: not enough data for Report metadata\n"); + break; + } + for (i = 0; i < bNumDescriptors; i++) { + if (extra[6 + 3 * i] == LIBUSB_DT_REPORT) { + result = (uint16_t)extra[6 + 3 * i + 2] << 8 | extra[6 + 3 * i + 1]; + found_hid_report_descriptor = 1; + break; + } + } + + if (!found_hid_report_descriptor) { + /* We expect to find exactly 1 HID descriptor (LIBUSB_DT_HID) + which should contain exactly one HID Report Descriptor metadata (LIBUSB_DT_REPORT). */ + LOG("Broken HID descriptor: missing Report descriptor\n"); + } + break; + } + + if (extra[0] == 0) { /* bLength */ + LOG("Broken HID Interface descriptors: zero-sized descriptor\n"); + break; + } + + /* Iterate over to the next Descriptor */ + extra_length -= extra[0]; + extra += extra[0]; + } + + return result; +} + +static int is_xbox360(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) +{ + static const int xb360_iface_subclass = 93; + static const int xb360_iface_protocol = 1; /* Wired */ + static const int xb360w_iface_protocol = 129; /* Wireless */ + static const int supported_vendors[] = { + 0x0079, /* GPD Win 2 */ + 0x044f, /* Thrustmaster */ + 0x045e, /* Microsoft */ + 0x046d, /* Logitech */ + 0x056e, /* Elecom */ + 0x06a3, /* Saitek */ + 0x0738, /* Mad Catz */ + 0x07ff, /* Mad Catz */ + 0x0e6f, /* PDP */ + 0x0f0d, /* Hori */ + 0x1038, /* SteelSeries */ + 0x11c9, /* Nacon */ + 0x12ab, /* Unknown */ + 0x1430, /* RedOctane */ + 0x146b, /* BigBen */ + 0x1532, /* Razer Sabertooth */ + 0x15e4, /* Numark */ + 0x162e, /* Joytech */ + 0x1689, /* Razer Onza */ + 0x1949, /* Lab126, Inc. */ + 0x1bad, /* Harmonix */ + 0x20d6, /* PowerA */ + 0x24c6, /* PowerA */ + 0x2c22, /* Qanba */ + 0x2dc8, /* 8BitDo */ + 0x9886, /* ASTRO Gaming */ + }; + + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && + intf_desc->bInterfaceSubClass == xb360_iface_subclass && + (intf_desc->bInterfaceProtocol == xb360_iface_protocol || + intf_desc->bInterfaceProtocol == xb360w_iface_protocol)) { + size_t i; + for (i = 0; i < sizeof(supported_vendors)/sizeof(supported_vendors[0]); ++i) { + if (vendor_id == supported_vendors[i]) { + return 1; + } + } + } + return 0; +} + +static int is_xboxone(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) +{ + static const int xb1_iface_subclass = 71; + static const int xb1_iface_protocol = 208; + static const int supported_vendors[] = { + 0x044f, /* Thrustmaster */ + 0x045e, /* Microsoft */ + 0x0738, /* Mad Catz */ + 0x0e6f, /* PDP */ + 0x0f0d, /* Hori */ + 0x10f5, /* Turtle Beach */ + 0x1532, /* Razer Wildcat */ + 0x20d6, /* PowerA */ + 0x24c6, /* PowerA */ + 0x2dc8, /* 8BitDo */ + 0x2e24, /* Hyperkin */ + 0x3537, /* GameSir */ + }; + + if (intf_desc->bInterfaceNumber == 0 && + intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && + intf_desc->bInterfaceSubClass == xb1_iface_subclass && + intf_desc->bInterfaceProtocol == xb1_iface_protocol) { + size_t i; + for (i = 0; i < sizeof(supported_vendors)/sizeof(supported_vendors[0]); ++i) { + if (vendor_id == supported_vendors[i]) { + return 1; + } + } + } + return 0; +} + +static int should_enumerate_interface(unsigned short vendor_id, const struct libusb_interface_descriptor *intf_desc) +{ +#if 0 + printf("Checking interface 0x%x %d/%d/%d/%d\n", vendor_id, intf_desc->bInterfaceNumber, intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol); +#endif + + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) + return 1; + + /* Also enumerate Xbox 360 controllers */ + if (is_xbox360(vendor_id, intf_desc)) + return 1; + + /* Also enumerate Xbox One controllers */ + if (is_xboxone(vendor_id, intf_desc)) + return 1; + + return 0; +} + struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { libusb_device **devs; libusb_device *dev; - libusb_device_handle *handle; + libusb_device_handle *handle = NULL; ssize_t num_devs; int i = 0; @@ -571,6 +807,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, int j, k; int res = libusb_get_device_descriptor(dev, &desc); + if (res < 0) + continue; + unsigned short dev_vid = desc.idVendor; unsigned short dev_pid = desc.idProduct; @@ -588,28 +827,13 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, for (k = 0; k < intf->num_altsetting; k++) { const struct libusb_interface_descriptor *intf_desc; intf_desc = &intf->altsetting[k]; - if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { - int interface_num = intf_desc->bInterfaceNumber; + if (should_enumerate_interface(dev_vid, intf_desc)) { struct hid_device_info *tmp; - /* VID/PID match. Create the record. */ - tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Fill out the record */ - cur_dev->next = NULL; - cur_dev->path = make_path(dev, interface_num, conf_desc->bConfigurationValue); - res = libusb_open(dev, &handle); - if (res >= 0) { #ifdef __ANDROID__ + if (handle) { /* There is (a potential) libusb Android backend, in which device descriptor is not accurate up until the device is opened. https://github.com/libusb/libusb/pull/874#discussion_r632801373 @@ -618,95 +842,50 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, having it here won't do any harm, since reading the device descriptor is as cheap as copy 18 bytes of data. */ libusb_get_device_descriptor(dev, &desc); + } #endif - /* Serial Number */ - if (desc.iSerialNumber > 0) - cur_dev->serial_number = - get_usb_string(handle, desc.iSerialNumber); - - /* Manufacturer and Product strings */ - if (desc.iManufacturer > 0) - cur_dev->manufacturer_string = - get_usb_string(handle, desc.iManufacturer); - if (desc.iProduct > 0) - cur_dev->product_string = - get_usb_string(handle, desc.iProduct); - + tmp = create_device_info_for_device(dev, handle, &desc, conf_desc->bConfigurationValue, intf_desc->bInterfaceNumber); + if (tmp) { #ifdef INVASIVE_GET_USAGE -{ - /* - This section is removed because it is too - invasive on the system. Getting a Usage Page - and Usage requires parsing the HID Report - descriptor. Getting a HID Report descriptor - involves claiming the interface. Claiming the - interface involves detaching the kernel driver. - Detaching the kernel driver is hard on the system - because it will unclaim interfaces (if another - app has them claimed) and the re-attachment of - the driver will sometimes change /dev entry names. - It is for these reasons that this section is - #if 0. For composite devices, use the interface - field in the hid_device_info struct to distinguish - between interfaces. */ - unsigned char data[256]; -#ifdef DETACH_KERNEL_DRIVER - int detached = 0; - /* Usage Page and Usage */ - res = libusb_kernel_driver_active(handle, interface_num); - if (res == 1) { - res = libusb_detach_kernel_driver(handle, interface_num); - if (res < 0) - LOG("Couldn't detach kernel driver, even though a kernel driver was attached.\n"); - else - detached = 1; + /* TODO: have a runtime check for this section. */ + + /* + This section is removed because it is too + invasive on the system. Getting a Usage Page + and Usage requires parsing the HID Report + descriptor. Getting a HID Report descriptor + involves claiming the interface. Claiming the + interface involves detaching the kernel driver. + Detaching the kernel driver is hard on the system + because it will unclaim interfaces (if another + app has them claimed) and the re-attachment of + the driver will sometimes change /dev entry names. + It is for these reasons that this section is + optional. For composite devices, use the interface + field in the hid_device_info struct to distinguish + between interfaces. */ + if (handle) { + uint16_t report_descriptor_size = get_report_descriptor_size_from_interface_descriptors(intf_desc); + + invasive_fill_device_info_usage(tmp, handle, intf_desc->bInterfaceNumber, report_descriptor_size); } -#endif - res = libusb_claim_interface(handle, interface_num); - if (res >= 0) { - /* Get the HID Report Descriptor. */ - res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); - if (res >= 0) { - unsigned short page=0, usage=0; - /* Parse the usage and usage page - out of the report descriptor. */ - get_usage(data, res, &page, &usage); - cur_dev->usage_page = page; - cur_dev->usage = usage; - } - else - LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); - - /* Release the interface */ - res = libusb_release_interface(handle, interface_num); - if (res < 0) - LOG("Can't release the interface.\n"); +#endif /* INVASIVE_GET_USAGE */ + + if (cur_dev) { + cur_dev->next = tmp; } - else - LOG("Can't claim interface %d\n", res); -#ifdef DETACH_KERNEL_DRIVER - /* Re-attach kernel driver if necessary. */ - if (detached) { - res = libusb_attach_kernel_driver(handle, interface_num); - if (res < 0) - LOG("Couldn't re-attach kernel driver.\n"); + else { + root = tmp; } -#endif -} -#endif /* INVASIVE_GET_USAGE */ + cur_dev = tmp; + } + if (res >= 0) { libusb_close(handle); + handle = NULL; } - /* VID/PID */ - cur_dev->vendor_id = dev_vid; - cur_dev->product_id = dev_pid; - - /* Release Number */ - cur_dev->release_number = desc.bcdDevice; - - /* Interface Number */ - cur_dev->interface_number = interface_num; + break; } } /* altsettings */ } /* interfaces */ @@ -769,7 +948,7 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const return handle; } -static void read_callback(struct libusb_transfer *transfer) +static void LIBUSB_CALL read_callback(struct libusb_transfer *transfer) { hid_device *dev = transfer->user_data; int res; @@ -782,13 +961,13 @@ static void read_callback(struct libusb_transfer *transfer) rpt->len = transfer->actual_length; rpt->next = NULL; - pthread_mutex_lock(&dev->mutex); + hidapi_thread_mutex_lock(&dev->thread_state); /* Attach the new report object to the end of the list. */ if (dev->input_reports == NULL) { /* The list is empty. Put it at the root. */ dev->input_reports = rpt; - pthread_cond_signal(&dev->condition); + hidapi_thread_cond_signal(&dev->thread_state); } else { /* Find the end of the list and attach. */ @@ -807,7 +986,7 @@ static void read_callback(struct libusb_transfer *transfer) return_data(dev, NULL, 0); } } - pthread_mutex_unlock(&dev->mutex); + hidapi_thread_mutex_unlock(&dev->thread_state); } else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { dev->shutdown_thread = 1; @@ -830,7 +1009,7 @@ static void read_callback(struct libusb_transfer *transfer) /* Re-submit the transfer object. */ res = libusb_submit_transfer(transfer); if (res != 0) { - LOG("Unable to submit URB. libusb error code: %d\n", res); + LOG("Unable to submit URB: (%d) %s\n", res, libusb_error_name(res)); dev->shutdown_thread = 1; dev->transfer_loop_finished = 1; } @@ -839,6 +1018,7 @@ static void read_callback(struct libusb_transfer *transfer) static void *read_thread(void *param) { + int res; hid_device *dev = param; uint8_t *buf; const size_t length = dev->input_ep_max_packet_size; @@ -850,25 +1030,29 @@ static void *read_thread(void *param) dev->device_handle, dev->input_endpoint, buf, - length, + (int)length, read_callback, dev, 5000/*timeout*/); /* Make the first submission. Further submissions are made from inside read_callback() */ - libusb_submit_transfer(dev->transfer); + res = libusb_submit_transfer(dev->transfer); + if(res < 0) { + LOG("libusb_submit_transfer failed: %d %s. Stopping read_thread from running\n", res, libusb_error_name(res)); + dev->shutdown_thread = 1; + dev->transfer_loop_finished = 1; + } /* Notify the main thread that the read thread is up and running. */ - pthread_barrier_wait(&dev->barrier); + hidapi_thread_barrier_wait(&dev->thread_state); /* Handle all the events. */ while (!dev->shutdown_thread) { - int res; res = libusb_handle_events(usb_context); if (res < 0) { /* There was an error. */ - LOG("read_thread(): libusb reports error # %d\n", res); + LOG("read_thread(): (%d) %s\n", res, libusb_error_name(res)); /* Break out of this loop only on fatal error.*/ if (res != LIBUSB_ERROR_BUSY && @@ -893,23 +1077,86 @@ static void *read_thread(void *param) make sure that a thread which is about to go to sleep waiting on the condition actually will go to sleep before the condition is signaled. */ - pthread_mutex_lock(&dev->mutex); - pthread_cond_broadcast(&dev->condition); - pthread_mutex_unlock(&dev->mutex); + hidapi_thread_mutex_lock(&dev->thread_state); + hidapi_thread_cond_broadcast(&dev->thread_state); + hidapi_thread_mutex_unlock(&dev->thread_state); /* The dev->transfer->buffer and dev->transfer objects are cleaned up in hid_close(). They are not cleaned up here because this thread could end either due to a disconnect or due to a user call to hid_close(). In both cases the objects can be safely - cleaned up after the call to pthread_join() (in hid_close()), but + cleaned up after the call to hidapi_thread_join() (in hid_close()), but since hid_close() calls libusb_cancel_transfer(), on these objects, they can not be cleaned up here. */ return NULL; } +static void init_xbox360(libusb_device_handle *device_handle, unsigned short idVendor, unsigned short idProduct, const struct libusb_config_descriptor *conf_desc) +{ + (void)conf_desc; + + if ((idVendor == 0x05ac && idProduct == 0x055b) /* Gamesir-G3w */ || + idVendor == 0x0f0d /* Hori Xbox controllers */) { + unsigned char data[20]; + + /* The HORIPAD FPS for Nintendo Switch requires this to enable input reports. + This VID/PID is also shared with other HORI controllers, but they all seem + to be fine with this as well. + */ + memset(data, 0, sizeof(data)); + libusb_control_transfer(device_handle, 0xC1, 0x01, 0x100, 0x0, data, sizeof(data), 100); + } +} + +static void init_xboxone(libusb_device_handle *device_handle, unsigned short idVendor, unsigned short idProduct, const struct libusb_config_descriptor *conf_desc) +{ + static const int vendor_microsoft = 0x045e; + static const int xb1_iface_subclass = 71; + static const int xb1_iface_protocol = 208; + int j, k, res; + + (void)idProduct; + + for (j = 0; j < conf_desc->bNumInterfaces; j++) { + const struct libusb_interface *intf = &conf_desc->interface[j]; + for (k = 0; k < intf->num_altsetting; k++) { + const struct libusb_interface_descriptor *intf_desc = &intf->altsetting[k]; + if (intf_desc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && + intf_desc->bInterfaceSubClass == xb1_iface_subclass && + intf_desc->bInterfaceProtocol == xb1_iface_protocol) { + int bSetAlternateSetting = 0; + + /* Newer Microsoft Xbox One controllers have a high speed alternate setting */ + if (idVendor == vendor_microsoft && + intf_desc->bInterfaceNumber == 0 && intf_desc->bAlternateSetting == 1) { + bSetAlternateSetting = 1; + } else if (intf_desc->bInterfaceNumber != 0 && intf_desc->bAlternateSetting == 0) { + bSetAlternateSetting = 1; + } + + if (bSetAlternateSetting) { + res = libusb_claim_interface(device_handle, intf_desc->bInterfaceNumber); + if (res < 0) { + LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); + continue; + } + + LOG("Setting alternate setting for VID/PID 0x%x/0x%x interface %d to %d\n", idVendor, idProduct, intf_desc->bInterfaceNumber, intf_desc->bAlternateSetting); + + res = libusb_set_interface_alt_setting(device_handle, intf_desc->bInterfaceNumber, intf_desc->bAlternateSetting); + if (res < 0) { + LOG("xbox init: can't set alt setting %d: %d\n", intf_desc->bInterfaceNumber, res); + } -static int hidapi_initialize_device(hid_device *dev, const struct libusb_interface_descriptor *intf_desc) + libusb_release_interface(device_handle, intf_desc->bInterfaceNumber); + } + } + } + } +} + +static int hidapi_initialize_device(hid_device *dev, const struct libusb_interface_descriptor *intf_desc, const struct libusb_config_descriptor *conf_desc) { int i =0; int res = 0; @@ -923,7 +1170,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); if (res < 0) { - LOG("Unable to detach Kernel Driver\n"); + LOG("Unable to detach Kernel Driver: (%d) %s\n", res, libusb_error_name(res)); return 0; } else { @@ -934,18 +1181,39 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa #endif res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); if (res < 0) { - LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); + LOG("can't claim interface %d: (%d) %s\n", intf_desc->bInterfaceNumber, res, libusb_error_name(res)); + +#ifdef DETACH_KERNEL_DRIVER + if (dev->is_driver_detached) { + res = libusb_attach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); + if (res < 0) + LOG("Failed to reattach the driver to kernel: (%d) %s\n", res, libusb_error_name(res)); + } +#endif return 0; } + /* Initialize XBox 360 controllers */ + if (is_xbox360(desc.idVendor, intf_desc)) { + init_xbox360(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc); + } + + /* Initialize XBox One controllers */ + if (is_xboxone(desc.idVendor, intf_desc)) { + init_xboxone(dev->device_handle, desc.idVendor, desc.idProduct, conf_desc); + } + /* Store off the string descriptor indexes */ dev->manufacturer_index = desc.iManufacturer; dev->product_index = desc.iProduct; dev->serial_index = desc.iSerialNumber; - /* Store off the interface number */ + /* Store off the USB information */ + dev->config_number = conf_desc->bConfigurationValue; dev->interface = intf_desc->bInterfaceNumber; + dev->report_descriptor_size = get_report_descriptor_size_from_interface_descriptors(intf_desc); + dev->input_endpoint = 0; dev->input_ep_max_packet_size = 0; dev->output_endpoint = 0; @@ -982,10 +1250,10 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa } } - pthread_create(&dev->thread, NULL, read_thread, dev); + hidapi_thread_create(&dev->thread_state, read_thread, dev); /* Wait here for the read thread to be initialized. */ - pthread_barrier_wait(&dev->barrier); + hidapi_thread_barrier_wait(&dev->thread_state); return 1; } @@ -1007,17 +1275,27 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) libusb_get_device_list(usb_context, &devs); while ((usb_dev = devs[d++]) != NULL && !good_open) { + struct libusb_device_descriptor desc; struct libusb_config_descriptor *conf_desc = NULL; int j,k; - if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) + res = libusb_get_device_descriptor(usb_dev, &desc); + if (res < 0) continue; + + res = libusb_get_active_config_descriptor(usb_dev, &conf_desc); + if (res < 0) + libusb_get_config_descriptor(usb_dev, 0, &conf_desc); + if (!conf_desc) + continue; + for (j = 0; j < conf_desc->bNumInterfaces && !good_open; j++) { const struct libusb_interface *intf = &conf_desc->interface[j]; for (k = 0; k < intf->num_altsetting && !good_open; k++) { const struct libusb_interface_descriptor *intf_desc = &intf->altsetting[k]; - if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { - char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber, conf_desc->bConfigurationValue); + if (should_enumerate_interface(desc.idVendor, intf_desc)) { + char dev_path[64]; + get_path(&dev_path, usb_dev, conf_desc->bConfigurationValue, intf_desc->bInterfaceNumber); if (!strcmp(dev_path, path)) { /* Matched Paths. Open this device */ @@ -1025,14 +1303,12 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) res = libusb_open(usb_dev, &dev->device_handle); if (res < 0) { LOG("can't open device\n"); - free(dev_path); break; } - good_open = hidapi_initialize_device(dev, intf_desc); + good_open = hidapi_initialize_device(dev, intf_desc, conf_desc); if (!good_open) libusb_close(dev->device_handle); } - free(dev_path); } } } @@ -1107,7 +1383,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_libusb_wrap_sys_device(intptr_t sys goto err; } - if (!hidapi_initialize_device(dev, selected_intf_desc)) + if (!hidapi_initialize_device(dev, selected_intf_desc, conf_desc)) goto err; return dev; @@ -1133,6 +1409,11 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t int report_number; int skipped_report_id = 0; + if (dev->output_endpoint <= 0) { + /* No interrupt out endpoint. Use the Control Endpoint */ + return hid_send_output_report(dev, data, length); + } + if (!data || (length ==0)) { return -1; } @@ -1145,42 +1426,21 @@ int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t skipped_report_id = 1; } + /* Use the interrupt out endpoint */ + int actual_length; + res = libusb_interrupt_transfer(dev->device_handle, + dev->output_endpoint, + (unsigned char*)data, + (int)length, + &actual_length, 1000); - if (dev->output_endpoint <= 0) { - /* No interrupt out endpoint. Use the Control Endpoint */ - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, - 0x09/*HID Set_Report*/, - (2/*HID output*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - if (skipped_report_id) - length++; - - return length; - } - else { - /* Use the interrupt out endpoint */ - int actual_length; - res = libusb_interrupt_transfer(dev->device_handle, - dev->output_endpoint, - (unsigned char*)data, - length, - &actual_length, 1000); - - if (res < 0) - return -1; + if (res < 0) + return -1; - if (skipped_report_id) - actual_length++; + if (skipped_report_id) + actual_length++; - return actual_length; - } + return actual_length; } /* Helper function, to simplify hid_read(). @@ -1196,13 +1456,13 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length) dev->input_reports = rpt->next; free(rpt->data); free(rpt); - return len; + return (int)len; } static void cleanup_mutex(void *param) { hid_device *dev = param; - pthread_mutex_unlock(&dev->mutex); + hidapi_thread_mutex_unlock(&dev->thread_state); } @@ -1218,8 +1478,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t /* error: variable ‘bytes_read’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered] */ int bytes_read; /* = -1; */ - pthread_mutex_lock(&dev->mutex); - pthread_cleanup_push(&cleanup_mutex, dev); + hidapi_thread_mutex_lock(&dev->thread_state); + hidapi_thread_cleanup_push(cleanup_mutex, dev); bytes_read = -1; @@ -1240,7 +1500,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t if (milliseconds == -1) { /* Blocking */ while (!dev->input_reports && !dev->shutdown_thread) { - pthread_cond_wait(&dev->condition, &dev->mutex); + hidapi_thread_cond_wait(&dev->thread_state); } if (dev->input_reports) { bytes_read = return_data(dev, data, length); @@ -1249,17 +1509,12 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t else if (milliseconds > 0) { /* Non-blocking, but called with timeout. */ int res; - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += milliseconds / 1000; - ts.tv_nsec += (milliseconds % 1000) * 1000000; - if (ts.tv_nsec >= 1000000000L) { - ts.tv_sec++; - ts.tv_nsec -= 1000000000L; - } + hidapi_timespec ts; + hidapi_thread_gettime(&ts); + hidapi_thread_addtime(&ts, milliseconds); while (!dev->input_reports && !dev->shutdown_thread) { - res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); + res = hidapi_thread_cond_timedwait(&dev->thread_state, &ts); if (res == 0) { if (dev->input_reports) { bytes_read = return_data(dev, data, length); @@ -1270,7 +1525,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t or the read thread was shutdown. Run the loop again (ie: don't break). */ } - else if (res == ETIMEDOUT) { + else if (res == HIDAPI_THREAD_TIMED_OUT) { /* Timed out. */ bytes_read = 0; break; @@ -1288,8 +1543,8 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t } ret: - pthread_mutex_unlock(&dev->mutex); - pthread_cleanup_pop(0); + hidapi_thread_mutex_unlock(&dev->thread_state); + hidapi_thread_cleanup_pop(0); return bytes_read; } @@ -1334,7 +1589,7 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char if (skipped_report_id) length++; - return length; + return (int)length; } int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) @@ -1367,6 +1622,36 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return res; } +int HID_API_EXPORT hid_send_output_report(hid_device *dev, const unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + res = libusb_control_transfer(dev->device_handle, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID set_report*/, + (2/*HID output*/ << 8) | report_number, + dev->interface, + (unsigned char *)data, length, + 1000/*timeout millis*/); + + if (res < 0) + return -1; + + /* Account for the report ID */ + if (skipped_report_id) + length++; + + return length; +} + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { int res = -1; @@ -1407,7 +1692,7 @@ void HID_API_EXPORT hid_close(hid_device *dev) libusb_cancel_transfer(dev->transfer); /* Wait for read_thread() to end. */ - pthread_join(dev->thread, NULL); + hidapi_thread_join(&dev->thread_state); /* Clean up the Transfer objects allocated in read_thread(). */ free(dev->transfer->buffer); @@ -1430,11 +1715,11 @@ void HID_API_EXPORT hid_close(hid_device *dev) libusb_close(dev->device_handle); /* Clear out the queue of received reports. */ - pthread_mutex_lock(&dev->mutex); + hidapi_thread_mutex_lock(&dev->thread_state); while (dev->input_reports) { return_data(dev, NULL, 0); } - pthread_mutex_unlock(&dev->mutex); + hidapi_thread_mutex_unlock(&dev->thread_state); free_hid_device(dev); } @@ -1455,6 +1740,23 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); } +HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { + if (!dev->device_info) { + struct libusb_device_descriptor desc; + libusb_device *usb_device = libusb_get_device(dev->device_handle); + libusb_get_device_descriptor(usb_device, &desc); + + dev->device_info = create_device_info_for_device(usb_device, dev->device_handle, &desc, dev->config_number, dev->interface); + // device error already set by create_device_info_for_device, if any + + if (dev->device_info) { + fill_device_info_usage(dev->device_info, dev->device_handle, dev->interface, dev->report_descriptor_size); + } + } + + return dev->device_info; +} + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { wchar_t *str; @@ -1471,6 +1773,12 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index } +int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) +{ + return hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, buf, buf_size); +} + + HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { (void)dev; @@ -1635,7 +1943,7 @@ uint16_t get_usb_code_for_current_locale(void) return 0x0; /* Make a copy of the current locale string. */ - strncpy(search_string, locale, sizeof(search_string)); + strncpy(search_string, locale, sizeof(search_string)-1); search_string[sizeof(search_string)-1] = '\0'; /* Chop off the encoding part, and make it lower case. */ diff --git a/libusb/hidapi_thread_pthread.h b/libusb/hidapi_thread_pthread.h new file mode 100644 index 000000000..0abe733e5 --- /dev/null +++ b/libusb/hidapi_thread_pthread.h @@ -0,0 +1,174 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + libusb/hidapi Team + + Sam Lantinga + + Copyright 2023, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + https://github.com/libusb/hidapi . +********************************************************/ + +#include + +#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__ + +/* Barrier implementation because Android/Bionic don't have pthread_barrier. + This implementation came from Brent Priddy and was posted on + StackOverflow. It is used with his permission. */ +typedef int pthread_barrierattr_t; +typedef struct pthread_barrier { + pthread_mutex_t mutex; + pthread_cond_t cond; + int count; + int trip_count; +} pthread_barrier_t; + +static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) +{ + if(count == 0) { + errno = EINVAL; + return -1; + } + + if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + return -1; + } + if(pthread_cond_init(&barrier->cond, 0) < 0) { + pthread_mutex_destroy(&barrier->mutex); + return -1; + } + barrier->trip_count = count; + barrier->count = 0; + + return 0; +} + +static int pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + pthread_cond_destroy(&barrier->cond); + pthread_mutex_destroy(&barrier->mutex); + return 0; +} + +static int pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_mutex_lock(&barrier->mutex); + ++(barrier->count); + if(barrier->count >= barrier->trip_count) { + barrier->count = 0; + pthread_cond_broadcast(&barrier->cond); + pthread_mutex_unlock(&barrier->mutex); + return 1; + } + else { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + pthread_mutex_unlock(&barrier->mutex); + return 0; + } +} + +#endif + +#define HIDAPI_THREAD_TIMED_OUT ETIMEDOUT + +typedef struct timespec hidapi_timespec; + +typedef struct +{ + pthread_t thread; + pthread_mutex_t mutex; /* Protects input_reports */ + pthread_cond_t condition; + pthread_barrier_t barrier; /* Ensures correct startup sequence */ + +} hidapi_thread_state; + +static void hidapi_thread_state_init(hidapi_thread_state *state) +{ + pthread_mutex_init(&state->mutex, NULL); + pthread_cond_init(&state->condition, NULL); + pthread_barrier_init(&state->barrier, NULL, 2); +} + +static void hidapi_thread_state_destroy(hidapi_thread_state *state) +{ + pthread_barrier_destroy(&state->barrier); + pthread_cond_destroy(&state->condition); + pthread_mutex_destroy(&state->mutex); +} + +#define hidapi_thread_cleanup_push pthread_cleanup_push +#define hidapi_thread_cleanup_pop pthread_cleanup_pop + +static void hidapi_thread_mutex_lock(hidapi_thread_state *state) +{ + pthread_mutex_lock(&state->mutex); +} + +static void hidapi_thread_mutex_unlock(hidapi_thread_state *state) +{ + pthread_mutex_unlock(&state->mutex); +} + +static void hidapi_thread_cond_wait(hidapi_thread_state *state) +{ + pthread_cond_wait(&state->condition, &state->mutex); +} + +static int hidapi_thread_cond_timedwait(hidapi_thread_state *state, hidapi_timespec *ts) +{ + return pthread_cond_timedwait(&state->condition, &state->mutex, ts); +} + +static void hidapi_thread_cond_signal(hidapi_thread_state *state) +{ + pthread_cond_signal(&state->condition); +} + +static void hidapi_thread_cond_broadcast(hidapi_thread_state *state) +{ + pthread_cond_broadcast(&state->condition); +} + +static void hidapi_thread_barrier_wait(hidapi_thread_state *state) +{ + pthread_barrier_wait(&state->barrier); +} + +static void hidapi_thread_create(hidapi_thread_state *state, void *(*func)(void*), void *func_arg) +{ + pthread_create(&state->thread, NULL, func, func_arg); +} + +static void hidapi_thread_join(hidapi_thread_state *state) +{ + pthread_join(state->thread, NULL); +} + +static void hidapi_thread_gettime(hidapi_timespec *ts) +{ + clock_gettime(CLOCK_REALTIME, ts); +} + +static void hidapi_thread_addtime(hidapi_timespec *ts, int milliseconds) +{ + ts->tv_sec += milliseconds / 1000; + ts->tv_nsec += (milliseconds % 1000) * 1000000; + if (ts->tv_nsec >= 1000000000L) { + ts->tv_sec++; + ts->tv_nsec -= 1000000000L; + } +} diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 0970ac3f1..9c627087f 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.6.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR) add_library(hidapi_hidraw ${HIDAPI_PUBLIC_HEADERS} diff --git a/linux/hid.c b/linux/hid.c index 1d7911700..228fdeeca 100644 --- a/linux/hid.c +++ b/linux/hid.c @@ -61,34 +61,21 @@ #endif -// HIDIOCGINPUT is not defined in Linux kernel headers < 5.11. -// This definition is from hidraw.h in Linux >= 5.11. +// HIDIOCGINPUT and HIDIOCSOUTPUT are not defined in Linux kernel headers < 5.11. +// These definitions are from hidraw.h in Linux >= 5.11. // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f43d3870cafa2a0f3854c1819c8385733db8f9ae #ifndef HIDIOCGINPUT #define HIDIOCGINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0A, len) #endif - -/* USB HID device property names */ -const char *device_string_names[] = { - "manufacturer", - "product", - "serial", -}; - -/* Symbolic names for the properties above */ -enum device_string_id { - DEVICE_STRING_MANUFACTURER, - DEVICE_STRING_PRODUCT, - DEVICE_STRING_SERIAL, - - DEVICE_STRING_COUNT, -}; +#ifndef HIDIOCSOUTPUT +#define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len) +#endif struct hid_device_ { int device_handle; int blocking; - int uses_numbered_reports; wchar_t *last_error_str; + struct hid_device_info* device_info; }; static struct hid_api_version api_version = { @@ -97,17 +84,20 @@ static struct hid_api_version api_version = { .patch = HID_API_VERSION_PATCH }; -/* Global error message that is not specific to a device, e.g. for - hid_open(). It is thread-local like errno. */ -__thread wchar_t *last_global_error_str = NULL; +static wchar_t *last_global_error_str = NULL; + static hid_device *new_hid_device(void) { hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + if (dev == NULL) { + return NULL; + } + dev->device_handle = -1; dev->blocking = 1; - dev->uses_numbered_reports = 0; dev->last_error_str = NULL; + dev->device_info = NULL; return dev; } @@ -124,6 +114,10 @@ static wchar_t *utf8_to_wchar_t(const char *utf8) return wcsdup(L""); } ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t)); + if (ret == NULL) { + /* as much as we can do at this point */ + return NULL; + } mbstowcs(ret, utf8, wlen+1); ret[wlen] = 0x0000; } @@ -132,6 +126,25 @@ static wchar_t *utf8_to_wchar_t(const char *utf8) } +/* Makes a copy of the given error message (and decoded according to the + * currently locale) into the wide string pointer pointed by error_str. + * The last stored error string is freed. + * Use register_error_str(NULL) to free the error message completely. */ +static void register_error_str(wchar_t **error_str, const char *msg) +{ + free(*error_str); + *error_str = utf8_to_wchar_t(msg); +} + +/* Semilar to register_error_str, but allows passing a format string with va_list args into this function. */ +static void register_error_str_vformat(wchar_t **error_str, const char *format, va_list args) +{ + char msg[256]; + vsnprintf(msg, sizeof(msg), format, args); + + register_error_str(error_str, msg); +} + /* Set the last global error to be reported by hid_error(NULL). * The given error message will be copied (and decoded according to the * currently locale, so do not pass in string constants). @@ -139,51 +152,35 @@ static wchar_t *utf8_to_wchar_t(const char *utf8) * Use register_global_error(NULL) to indicate "no error". */ static void register_global_error(const char *msg) { - if (last_global_error_str) - free(last_global_error_str); - - last_global_error_str = utf8_to_wchar_t(msg); + register_error_str(&last_global_error_str, msg); } -/* See register_global_error, but you can pass a format string into this function. */ +/* Similar to register_global_error, but allows passing a format string into this function. */ static void register_global_error_format(const char *format, ...) { va_list args; va_start(args, format); - - char msg[100]; - vsnprintf(msg, sizeof(msg), format, args); - + register_error_str_vformat(&last_global_error_str, format, args); va_end(args); - - register_global_error(msg); } -/* Set the last error for a device to be reported by hid_error(device). +/* Set the last error for a device to be reported by hid_error(dev). * The given error message will be copied (and decoded according to the * currently locale, so do not pass in string constants). - * The last stored global error message is freed. - * Use register_device_error(device, NULL) to indicate "no error". */ + * The last stored device error message is freed. + * Use register_device_error(dev, NULL) to indicate "no error". */ static void register_device_error(hid_device *dev, const char *msg) { - if (dev->last_error_str) - free(dev->last_error_str); - - dev->last_error_str = utf8_to_wchar_t(msg); + register_error_str(&dev->last_error_str, msg); } -/* See register_device_error, but you can pass a format string into this function. */ +/* Similar to register_device_error, but you can pass a format string into this function. */ static void register_device_error_format(hid_device *dev, const char *format, ...) { va_list args; va_start(args, format); - - char msg[100]; - vsnprintf(msg, sizeof(msg), format, args); - + register_error_str_vformat(&dev->last_error_str, format, args); va_end(args); - - register_device_error(dev, msg); } /* Get an attribute value from a udev_device and return it as a whar_t @@ -198,7 +195,7 @@ static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) * Returns 1 if successful, 0 if an invalid key * Sets data_len and key_size when successful */ -static int get_hid_item_size(__u8 *report_descriptor, unsigned int pos, __u32 size, int *data_len, int *key_size) +static int get_hid_item_size(const __u8 *report_descriptor, __u32 size, unsigned int pos, int *data_len, int *key_size) { int key = report_descriptor[pos]; int size_code; @@ -250,39 +247,11 @@ static int get_hid_item_size(__u8 *report_descriptor, unsigned int pos, __u32 si return 0; } -/* uses_numbered_reports() returns 1 if report_descriptor describes a device - which contains numbered reports. */ -static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { - unsigned int i = 0; - int data_len, key_size; - - while (i < size) { - int key = report_descriptor[i]; - - /* Check for the Report ID key */ - if (key == 0x85/*Report ID*/) { - /* This device has a Report ID, which means it uses - numbered reports. */ - return 1; - } - - /* Determine data_len and key_size */ - if (!get_hid_item_size(report_descriptor, i, size, &data_len, &key_size)) - return 0; /* malformed report */ - - /* Skip over this key and its associated data */ - i += data_len + key_size; - } - - /* Didn't find a Report ID key. Device doesn't use numbered reports. */ - return 0; -} - /* * Get bytes from a HID Report Descriptor. * Only call with a num_bytes of 0, 1, 2, or 4. */ -static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_t cur) +static __u32 get_hid_report_bytes(const __u8 *rpt, size_t len, size_t num_bytes, size_t cur) { /* Return if there aren't enough bytes. */ if (cur + num_bytes >= len) @@ -305,6 +274,60 @@ static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_ return 0; } +/* + * Iterates until the end of a Collection. + * Assumes that *pos is exactly at the beginning of a Collection. + * Skips all nested Collection, i.e. iterates until the end of current level Collection. + * + * The return value is non-0 when an end of current Collection is found, + * 0 when error is occured (broken Descriptor, end of a Collection is found before its begin, + * or no Collection is found at all). + */ +static int hid_iterate_over_collection(const __u8 *report_descriptor, __u32 size, unsigned int *pos, int *data_len, int *key_size) +{ + int collection_level = 0; + + while (*pos < size) { + int key = report_descriptor[*pos]; + int key_cmd = key & 0xfc; + + /* Determine data_len and key_size */ + if (!get_hid_item_size(report_descriptor, size, *pos, data_len, key_size)) + return 0; /* malformed report */ + + switch (key_cmd) { + case 0xa0: /* Collection 6.2.2.4 (Main) */ + collection_level++; + break; + case 0xc0: /* End Collection 6.2.2.4 (Main) */ + collection_level--; + break; + } + + if (collection_level < 0) { + /* Broken descriptor or someone is using this function wrong, + * i.e. should be called exactly at the collection start */ + return 0; + } + + if (collection_level == 0) { + /* Found it! + * Also possible when called not at the collection start, but should not happen if used correctly */ + return 1; + } + + *pos += *data_len + *key_size; + } + + return 0; /* Did not find the end of a Collection */ +} + +struct hid_usage_iterator { + unsigned int pos; + int usage_page_found; + unsigned short usage_page; +}; + /* * Retrieves the device's Usage Page and Usage from the report descriptor. * The algorithm returns the current Usage Page/Usage pair whenever a new @@ -322,77 +345,78 @@ static __u32 get_hid_report_bytes(__u8 *rpt, size_t len, size_t num_bytes, size_ * 1 when finished processing descriptor. * -1 on a malformed report. */ -static int get_next_hid_usage(__u8 *report_descriptor, __u32 size, unsigned int *pos, unsigned short *usage_page, unsigned short *usage) +static int get_next_hid_usage(const __u8 *report_descriptor, __u32 size, struct hid_usage_iterator *ctx, unsigned short *usage_page, unsigned short *usage) { int data_len, key_size; - int initial = *pos == 0; /* Used to handle case where no top-level application collection is defined */ - int usage_pair_ready = 0; + int initial = ctx->pos == 0; /* Used to handle case where no top-level application collection is defined */ - /* Usage is a Local Item, it must be set before each Main Item (Collection) before a pair is returned */ int usage_found = 0; - while (*pos < size) { - int key = report_descriptor[*pos]; + while (ctx->pos < size) { + int key = report_descriptor[ctx->pos]; int key_cmd = key & 0xfc; /* Determine data_len and key_size */ - if (!get_hid_item_size(report_descriptor, *pos, size, &data_len, &key_size)) + if (!get_hid_item_size(report_descriptor, size, ctx->pos, &data_len, &key_size)) return -1; /* malformed report */ switch (key_cmd) { case 0x4: /* Usage Page 6.2.2.7 (Global) */ - *usage_page = get_hid_report_bytes(report_descriptor, size, data_len, *pos); + ctx->usage_page = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); + ctx->usage_page_found = 1; break; case 0x8: /* Usage 6.2.2.8 (Local) */ - *usage = get_hid_report_bytes(report_descriptor, size, data_len, *pos); - usage_found = 1; + if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */ + ctx->usage_page = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos + 2); + ctx->usage_page_found = 1; + *usage = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos); + usage_found = 1; + } + else { + *usage = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); + usage_found = 1; + } break; case 0xa0: /* Collection 6.2.2.4 (Main) */ - /* A Usage Item (Local) must be found for the pair to be valid */ - if (usage_found) - usage_pair_ready = 1; + if (!hid_iterate_over_collection(report_descriptor, size, &ctx->pos, &data_len, &key_size)) { + return -1; + } - /* Usage is a Local Item, unset it */ - usage_found = 0; - break; + /* A pair is valid - to be reported when Collection is found */ + if (usage_found && ctx->usage_page_found) { + *usage_page = ctx->usage_page; + return 0; + } - case 0x80: /* Input 6.2.2.4 (Main) */ - case 0x90: /* Output 6.2.2.4 (Main) */ - case 0xb0: /* Feature 6.2.2.4 (Main) */ - case 0xc0: /* End Collection 6.2.2.4 (Main) */ - /* Usage is a Local Item, unset it */ - usage_found = 0; break; } /* Skip over this key and its associated data */ - *pos += data_len + key_size; - - /* Return usage pair */ - if (usage_pair_ready) - return 0; + ctx->pos += data_len + key_size; } /* If no top-level application collection is found and usage page/usage pair is found, pair is valid https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */ - if (initial && usage_found) - return 0; /* success */ + if (initial && usage_found && ctx->usage_page_found) { + *usage_page = ctx->usage_page; + return 0; /* success */ + } return 1; /* finished processing */ } /* * Retrieves the hidraw report descriptor from a file. - * When using this form, /device/report_descriptor, elevated priviledges are not required. + * When using this form, /device/report_descriptor, elevated privileges are not required. */ static int get_hid_report_descriptor(const char *rpt_path, struct hidraw_report_descriptor *rpt_desc) { int rpt_handle; ssize_t res; - rpt_handle = open(rpt_path, O_RDONLY); + rpt_handle = open(rpt_path, O_RDONLY | O_CLOEXEC); if (rpt_handle < 0) { register_global_error_format("open failed (%s): %s", rpt_path, strerror(errno)); return -1; @@ -415,6 +439,7 @@ static int get_hid_report_descriptor(const char *rpt_path, struct hidraw_report_ return (int) res; } +/* return size of the descriptor, or -1 on failure */ static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct hidraw_report_descriptor *rpt_desc) { int res = -1; @@ -429,16 +454,133 @@ static int get_hid_report_descriptor_from_sysfs(const char *sysfs_path, struct h return res; } +/* return non-zero if successfully parsed */ +static int parse_hid_vid_pid_from_uevent(const char *uevent, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) +{ + char tmp[1024]; + size_t uevent_len = strlen(uevent); + if (uevent_len > sizeof(tmp) - 1) + uevent_len = sizeof(tmp) - 1; + memcpy(tmp, uevent, uevent_len); + tmp[uevent_len] = '\0'; + + char *saveptr = NULL; + char *line; + char *key; + char *value; + + line = strtok_r(tmp, "\n", &saveptr); + while (line != NULL) { + /* line: "KEY=value" */ + key = line; + value = strchr(line, '='); + if (!value) { + goto next_line; + } + *value = '\0'; + value++; + + if (strcmp(key, "HID_ID") == 0) { + /** + * type vendor product + * HID_ID=0003:000005AC:00008242 + **/ + int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); + if (ret == 3) { + return 1; + } + } + +next_line: + line = strtok_r(NULL, "\n", &saveptr); + } + + register_global_error("Couldn't find/parse HID_ID"); + return 0; +} + +/* return non-zero if successfully parsed */ +static int parse_hid_vid_pid_from_uevent_path(const char *uevent_path, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) +{ + int handle; + ssize_t res; + + handle = open(uevent_path, O_RDONLY | O_CLOEXEC); + if (handle < 0) { + register_global_error_format("open failed (%s): %s", uevent_path, strerror(errno)); + return 0; + } + + char buf[1024]; + res = read(handle, buf, sizeof(buf) - 1); /* -1 for '\0' at the end */ + close(handle); + + if (res < 0) { + register_global_error_format("read failed (%s): %s", uevent_path, strerror(errno)); + return 0; + } + + buf[res] = '\0'; + return parse_hid_vid_pid_from_uevent(buf, bus_type, vendor_id, product_id); +} + +/* return non-zero if successfully read/parsed */ +static int parse_hid_vid_pid_from_sysfs(const char *sysfs_path, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id) +{ + int res = 0; + /* Construct /device/uevent */ + size_t uevent_path_len = strlen(sysfs_path) + 14 + 1; + char* uevent_path = (char*) calloc(1, uevent_path_len); + snprintf(uevent_path, uevent_path_len, "%s/device/uevent", sysfs_path); + + res = parse_hid_vid_pid_from_uevent_path(uevent_path, bus_type, vendor_id, product_id); + free(uevent_path); + + return res; +} + +static int get_hid_report_descriptor_from_hidraw(hid_device *dev, struct hidraw_report_descriptor *rpt_desc) +{ + int desc_size = 0; + + /* Get Report Descriptor Size */ + int res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); + if (res < 0) { + register_device_error_format(dev, "ioctl(GRDESCSIZE): %s", strerror(errno)); + return res; + } + + /* Get Report Descriptor */ + memset(rpt_desc, 0x0, sizeof(*rpt_desc)); + rpt_desc->size = desc_size; + res = ioctl(dev->device_handle, HIDIOCGRDESC, rpt_desc); + if (res < 0) { + register_device_error_format(dev, "ioctl(GRDESC): %s", strerror(errno)); + } + + return res; +} + /* * The caller is responsible for free()ing the (newly-allocated) character * strings pointed to by serial_number_utf8 and product_name_utf8 after use. */ -static int -parse_uevent_info(const char *uevent, unsigned *bus_type, +static int parse_uevent_info(const char *uevent, unsigned *bus_type, unsigned short *vendor_id, unsigned short *product_id, char **serial_number_utf8, char **product_name_utf8) { - char *tmp = strdup(uevent); + char tmp[1024]; + + if (!uevent) { + return 0; + } + + size_t uevent_len = strlen(uevent); + if (uevent_len > sizeof(tmp) - 1) + uevent_len = sizeof(tmp) - 1; + memcpy(tmp, uevent, uevent_len); + tmp[uevent_len] = '\0'; + char *saveptr = NULL; char *line; char *key; @@ -482,109 +624,205 @@ parse_uevent_info(const char *uevent, unsigned *bus_type, line = strtok_r(NULL, "\n", &saveptr); } - free(tmp); return (found_id && found_name && found_serial); } -static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen) +static struct hid_device_info * create_device_info_for_device(struct udev_device *raw_dev) { - struct udev *udev; - struct udev_device *udev_dev, *parent, *hid_dev; - struct stat s; - int ret = -1; + struct hid_device_info *root = NULL; + struct hid_device_info *cur_dev = NULL; + + const char *sysfs_path; + const char *dev_path; + const char *str; + struct udev_device *hid_dev; /* The device's HID udev node. */ + struct udev_device *usb_dev; /* The device's USB udev node. */ + struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ + unsigned short dev_vid; + unsigned short dev_pid; char *serial_number_utf8 = NULL; char *product_name_utf8 = NULL; + unsigned bus_type; + int result; + struct hidraw_report_descriptor report_desc; - /* Create the udev object */ - udev = udev_new(); - if (!udev) { - register_global_error("Couldn't create udev context"); - return -1; + sysfs_path = udev_device_get_syspath(raw_dev); + dev_path = udev_device_get_devnode(raw_dev); + + hid_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "hid", + NULL); + + if (!hid_dev) { + /* Unable to find parent hid device. */ + goto end; } - /* Get the dev_t (major/minor numbers) from the file handle. */ - ret = fstat(dev->device_handle, &s); - if (-1 == ret) - return ret; - /* Open a udev device from the dev_t. 'c' means character device. */ - udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); - if (udev_dev) { - hid_dev = udev_device_get_parent_with_subsystem_devtype( - udev_dev, - "hid", - NULL); - if (hid_dev) { - unsigned short dev_vid; - unsigned short dev_pid; - unsigned bus_type; - size_t retm; - - ret = parse_uevent_info( - udev_device_get_sysattr_value(hid_dev, "uevent"), - &bus_type, - &dev_vid, - &dev_pid, - &serial_number_utf8, - &product_name_utf8); - - /* Standard USB device */ - if (bus_type == BUS_USB) { - /* This is a USB device. Find its parent USB Device node. */ - parent = udev_device_get_parent_with_subsystem_devtype( - udev_dev, - "usb", - "usb_device"); - if (parent) { - const char *str; - const char *key_str = NULL; - - if (key >= 0 && key < DEVICE_STRING_COUNT) { - key_str = device_string_names[key]; - } else { - ret = -1; - goto end; - } - - str = udev_device_get_sysattr_value(parent, key_str); - if (str) { - /* Convert the string from UTF-8 to wchar_t */ - retm = mbstowcs(string, str, maxlen); - ret = (retm == (size_t)-1)? -1: 0; - } - - /* USB information parsed */ - goto end; - } - else { - /* Correctly handled below */ - } + result = parse_uevent_info( + udev_device_get_sysattr_value(hid_dev, "uevent"), + &bus_type, + &dev_vid, + &dev_pid, + &serial_number_utf8, + &product_name_utf8); + + if (!result) { + /* parse_uevent_info() failed for at least one field. */ + goto end; + } + + /* Filter out unhandled devices right away */ + switch (bus_type) { + case BUS_BLUETOOTH: + case BUS_I2C: + case BUS_USB: + case BUS_SPI: + break; + + default: + goto end; + } + + /* Create the record. */ + root = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + if (!root) + goto end; + + cur_dev = root; + + /* Fill out the record */ + cur_dev->next = NULL; + cur_dev->path = dev_path? strdup(dev_path): NULL; + + /* VID/PID */ + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + + /* Serial Number */ + cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); + + /* Release Number */ + cur_dev->release_number = 0x0; + + /* Interface Number */ + cur_dev->interface_number = -1; + + switch (bus_type) { + case BUS_USB: + /* The device pointed to by raw_dev contains information about + the hidraw device. In order to get information about the + USB device, get the parent device with the + subsystem/devtype pair of "usb"/"usb_device". This will + be several levels up the tree, but the function will find + it. */ + usb_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "usb", + "usb_device"); + + /* uhid USB devices + * Since this is a virtual hid interface, no USB information will + * be available. */ + if (!usb_dev) { + /* Manufacturer and Product strings */ + cur_dev->manufacturer_string = wcsdup(L""); + cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); + break; } - /* USB information not available (uhid) or another type of HID bus */ - switch (bus_type) { - case BUS_BLUETOOTH: - case BUS_I2C: - case BUS_USB: - switch (key) { - case DEVICE_STRING_MANUFACTURER: - wcsncpy(string, L"", maxlen); - ret = 0; - break; - case DEVICE_STRING_PRODUCT: - retm = mbstowcs(string, product_name_utf8, maxlen); - ret = (retm == (size_t)-1)? -1: 0; - break; - case DEVICE_STRING_SERIAL: - retm = mbstowcs(string, serial_number_utf8, maxlen); - ret = (retm == (size_t)-1)? -1: 0; - break; - case DEVICE_STRING_COUNT: - default: - ret = -1; - break; - } + cur_dev->manufacturer_string = copy_udev_string(usb_dev, "manufacturer"); + cur_dev->product_string = copy_udev_string(usb_dev, "product"); + + cur_dev->bus_type = HID_API_BUS_USB; + + str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); + cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; + + /* Get a handle to the interface's udev node. */ + intf_dev = udev_device_get_parent_with_subsystem_devtype( + raw_dev, + "usb", + "usb_interface"); + if (intf_dev) { + str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); + cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; } + + break; + + case BUS_BLUETOOTH: + cur_dev->manufacturer_string = wcsdup(L""); + cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); + + cur_dev->bus_type = HID_API_BUS_BLUETOOTH; + + break; + case BUS_I2C: + cur_dev->manufacturer_string = wcsdup(L""); + cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); + + cur_dev->bus_type = HID_API_BUS_I2C; + + break; + + case BUS_SPI: + cur_dev->manufacturer_string = wcsdup(L""); + cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); + + cur_dev->bus_type = HID_API_BUS_SPI; + + break; + + default: + /* Unknown device type - this should never happen, as we + * check for USB and Bluetooth devices above */ + break; + } + + /* Usage Page and Usage */ + result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc); + if (result >= 0) { + unsigned short page = 0, usage = 0; + struct hid_usage_iterator usage_iterator; + memset(&usage_iterator, 0, sizeof(usage_iterator)); + + /* + * Parse the first usage and usage page + * out of the report descriptor. + */ + if (!get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage)) { + cur_dev->usage_page = page; + cur_dev->usage = usage; + } + + /* + * Parse any additional usage and usage pages + * out of the report descriptor. + */ + while (!get_next_hid_usage(report_desc.value, report_desc.size, &usage_iterator, &page, &usage)) { + /* Create new record for additional usage pairs */ + struct hid_device_info *tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + struct hid_device_info *prev_dev = cur_dev; + + if (!tmp) + continue; + cur_dev->next = tmp; + cur_dev = tmp; + + /* Update fields */ + cur_dev->path = dev_path? strdup(dev_path): NULL; + cur_dev->vendor_id = dev_vid; + cur_dev->product_id = dev_pid; + cur_dev->serial_number = prev_dev->serial_number? wcsdup(prev_dev->serial_number): NULL; + cur_dev->release_number = prev_dev->release_number; + cur_dev->interface_number = prev_dev->interface_number; + cur_dev->manufacturer_string = prev_dev->manufacturer_string? wcsdup(prev_dev->manufacturer_string): NULL; + cur_dev->product_string = prev_dev->product_string? wcsdup(prev_dev->product_string): NULL; + cur_dev->usage_page = page; + cur_dev->usage = usage; + cur_dev->bus_type = prev_dev->bus_type; } } @@ -592,20 +830,55 @@ static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t free(serial_number_utf8); free(product_name_utf8); + return root; +} + +static struct hid_device_info * create_device_info_for_hid_device(hid_device *dev) { + struct udev *udev; + struct udev_device *udev_dev; + struct stat s; + int ret = -1; + struct hid_device_info *root = NULL; + + register_device_error(dev, NULL); + + /* Get the dev_t (major/minor numbers) from the file handle. */ + ret = fstat(dev->device_handle, &s); + if (-1 == ret) { + register_device_error(dev, "Failed to stat device handle"); + return NULL; + } + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + register_device_error(dev, "Couldn't create udev context"); + return NULL; + } + + /* Open a udev device from the dev_t. 'c' means character device. */ + udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); + if (udev_dev) { + root = create_device_info_for_device(udev_dev); + } + + if (!root) { + /* TODO: have a better error reporting via create_device_info_for_device */ + register_device_error(dev, "Couldn't create hid_device_info"); + } + udev_device_unref(udev_dev); - /* parent and hid_dev don't need to be (and can't be) unref'd. - I'm not sure why, but they'll throw double-free() errors. */ udev_unref(udev); - return ret; + return root; } -HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version() +HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) { return &api_version; } -HID_API_EXPORT const char* HID_API_CALL hid_version_str() +HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) { return HID_API_VERSION_STR; } @@ -614,6 +887,9 @@ int HID_API_EXPORT hid_init(void) { const char *locale; + /* indicate no error */ + register_global_error(NULL); + /* Set the locale if it's not set. */ locale = setlocale(LC_CTYPE, NULL); if (!locale) @@ -630,7 +906,6 @@ int HID_API_EXPORT hid_exit(void) return 0; } - struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct udev *udev; @@ -639,9 +914,9 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; - struct hid_device_info *prev_dev = NULL; /* previous device */ hid_init(); + /* register_global_error: global error is reset by hid_init */ /* Create the udev object */ udev = udev_new(); @@ -659,202 +934,62 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, create a udev_device record for it */ udev_list_entry_foreach(dev_list_entry, devices) { const char *sysfs_path; - const char *dev_path; - const char *str; + unsigned short dev_vid = 0; + unsigned short dev_pid = 0; + unsigned bus_type = 0; struct udev_device *raw_dev; /* The device's hidraw udev node. */ - struct udev_device *hid_dev; /* The device's HID udev node. */ - struct udev_device *usb_dev; /* The device's USB udev node. */ - struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ - unsigned short dev_vid; - unsigned short dev_pid; - char *serial_number_utf8 = NULL; - char *product_name_utf8 = NULL; - unsigned bus_type; - int result; - struct hidraw_report_descriptor report_desc; + struct hid_device_info * tmp; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ sysfs_path = udev_list_entry_get_name(dev_list_entry); - raw_dev = udev_device_new_from_syspath(udev, sysfs_path); - dev_path = udev_device_get_devnode(raw_dev); - - hid_dev = udev_device_get_parent_with_subsystem_devtype( - raw_dev, - "hid", - NULL); + if (!sysfs_path) + continue; - if (!hid_dev) { - /* Unable to find parent hid device. */ - goto next; - } + if (vendor_id != 0 || product_id != 0) { + if (!parse_hid_vid_pid_from_sysfs(sysfs_path, &bus_type, &dev_vid, &dev_pid)) + continue; - result = parse_uevent_info( - udev_device_get_sysattr_value(hid_dev, "uevent"), - &bus_type, - &dev_vid, - &dev_pid, - &serial_number_utf8, - &product_name_utf8); - - if (!result) { - /* parse_uevent_info() failed for at least one field. */ - goto next; + if (vendor_id != 0 && vendor_id != dev_vid) + continue; + if (product_id != 0 && product_id != dev_pid) + continue; } - /* Filter out unhandled devices right away */ - switch (bus_type) { - case BUS_BLUETOOTH: - case BUS_I2C: - case BUS_USB: - break; - - default: - goto next; - } - - /* Check the VID/PID against the arguments */ - if ((vendor_id == 0x0 || vendor_id == dev_vid) && - (product_id == 0x0 || product_id == dev_pid)) { - struct hid_device_info *tmp; + raw_dev = udev_device_new_from_syspath(udev, sysfs_path); + if (!raw_dev) + continue; - /* VID/PID match. Create the record. */ - tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); + tmp = create_device_info_for_device(raw_dev); + if (tmp) { if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } - prev_dev = cur_dev; cur_dev = tmp; - /* Fill out the record */ - cur_dev->next = NULL; - cur_dev->path = dev_path? strdup(dev_path): NULL; - - /* VID/PID */ - cur_dev->vendor_id = dev_vid; - cur_dev->product_id = dev_pid; - - /* Serial Number */ - cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); - - /* Release Number */ - cur_dev->release_number = 0x0; - - /* Interface Number */ - cur_dev->interface_number = -1; - - switch (bus_type) { - case BUS_USB: - /* The device pointed to by raw_dev contains information about - the hidraw device. In order to get information about the - USB device, get the parent device with the - subsystem/devtype pair of "usb"/"usb_device". This will - be several levels up the tree, but the function will find - it. */ - usb_dev = udev_device_get_parent_with_subsystem_devtype( - raw_dev, - "usb", - "usb_device"); - - /* uhid USB devices - Since this is a virtual hid interface, no USB information will - be available. */ - if (!usb_dev) { - /* Manufacturer and Product strings */ - cur_dev->manufacturer_string = wcsdup(L""); - cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); - break; - } - - /* Manufacturer and Product strings */ - cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]); - cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]); - - /* Release Number */ - str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); - cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; - - /* Get a handle to the interface's udev node. */ - intf_dev = udev_device_get_parent_with_subsystem_devtype( - raw_dev, - "usb", - "usb_interface"); - if (intf_dev) { - str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); - cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; - } - - break; - - case BUS_BLUETOOTH: - case BUS_I2C: - /* Manufacturer and Product strings */ - cur_dev->manufacturer_string = wcsdup(L""); - cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); - - break; - - default: - /* Unknown device type - this should never happen, as we - * check for USB and Bluetooth devices above */ - break; - } - - /* Usage Page and Usage */ - result = get_hid_report_descriptor_from_sysfs(sysfs_path, &report_desc); - if (result >= 0) { - unsigned short page = 0, usage = 0; - unsigned int pos = 0; - /* - * Parse the first usage and usage page - * out of the report descriptor. - */ - if (!get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage)) { - cur_dev->usage_page = page; - cur_dev->usage = usage; - } - - /* - * Parse any additional usage and usage pages - * out of the report descriptor. - */ - while (!get_next_hid_usage(report_desc.value, report_desc.size, &pos, &page, &usage)) { - /* Create new record for additional usage pairs */ - tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); - cur_dev->next = tmp; - prev_dev = cur_dev; - cur_dev = tmp; - - /* Update fields */ - cur_dev->path = strdup(dev_path); - cur_dev->vendor_id = dev_vid; - cur_dev->product_id = dev_pid; - cur_dev->serial_number = prev_dev->serial_number? wcsdup(prev_dev->serial_number): NULL; - cur_dev->release_number = prev_dev->release_number; - cur_dev->interface_number = prev_dev->interface_number; - cur_dev->manufacturer_string = prev_dev->manufacturer_string? wcsdup(prev_dev->manufacturer_string): NULL; - cur_dev->product_string = prev_dev->product_string? wcsdup(prev_dev->product_string): NULL; - cur_dev->usage_page = page; - cur_dev->usage = usage; - } + /* move the pointer to the tail of returned list */ + while (cur_dev->next != NULL) { + cur_dev = cur_dev->next; } } - next: - free(serial_number_utf8); - free(product_name_utf8); udev_device_unref(raw_dev); - /* hid_dev, usb_dev and intf_dev don't need to be (and can't be) - unref()d. It will cause a double-free() error. I'm not - sure why. */ } /* Free the enumerator and udev objects. */ udev_enumerate_unref(enumerate); udev_unref(udev); + if (root == NULL) { + if (vendor_id == 0 && product_id == 0) { + register_global_error("No HID devices found in the system."); + } else { + register_global_error("No HID devices with requested VID/PID found in the system."); + } + } + return root; } @@ -874,14 +1009,17 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { - /* Set global error to none */ - register_global_error(NULL); - struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; + /* register_global_error: global error is reset by hid_enumerate/hid_init */ devs = hid_enumerate(vendor_id, product_id); + if (devs == NULL) { + /* register_global_error: global error is already set by hid_enumerate */ + return NULL; + } + cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && @@ -904,7 +1042,7 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const /* Open the device */ handle = hid_open_path(path_to_open); } else { - register_global_error("No such device"); + register_global_error("Device with requested VID/PID/(SerialNumber) not found"); } hid_free_enumeration(devs); @@ -914,52 +1052,36 @@ hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const hid_device * HID_API_EXPORT hid_open_path(const char *path) { - /* Set global error to none */ - register_global_error(NULL); - hid_device *dev = NULL; hid_init(); + /* register_global_error: global error is reset by hid_init */ dev = new_hid_device(); + if (!dev) { + register_global_error("Couldn't allocate memory"); + return NULL; + } - /* OPEN HERE */ - dev->device_handle = open(path, O_RDWR); + dev->device_handle = open(path, O_RDWR | O_CLOEXEC); - /* If we have a good handle, return it. */ if (dev->device_handle >= 0) { - /* Set device error to none */ - register_device_error(dev, NULL); - - /* Get the report descriptor */ int res, desc_size = 0; - struct hidraw_report_descriptor rpt_desc; - - memset(&rpt_desc, 0x0, sizeof(rpt_desc)); - /* Get Report Descriptor Size */ + /* Make sure this is a HIDRAW device - responds to HIDIOCGRDESCSIZE */ res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); - if (res < 0) - register_device_error_format(dev, "ioctl (GRDESCSIZE): %s", strerror(errno)); - - /* Get Report Descriptor */ - rpt_desc.size = desc_size; - res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc); if (res < 0) { - register_device_error_format(dev, "ioctl (GRDESC): %s", strerror(errno)); - } else { - /* Determine if this device uses numbered reports. */ - dev->uses_numbered_reports = - uses_numbered_reports(rpt_desc.value, - rpt_desc.size); + hid_close(dev); + register_global_error_format("ioctl(GRDESCSIZE) error for '%s', not a HIDRAW device?: %s", path, strerror(errno)); + return NULL; } return dev; } else { - /* Unable to open any devices. */ - register_global_error(strerror(errno)); + /* Unable to open a device. */ free(dev); + register_global_error_format("Failed to open a device with path '%s': %s", path, strerror(errno)); return NULL; } } @@ -1016,9 +1138,11 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t else { /* Check for errors on the file descriptor. This will indicate a device disconnection. */ - if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) + if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) { // We cannot use strerror() here as no -1 was returned from poll(). + register_device_error(dev, "hid_read_timeout: unexpected poll error (device disconnected)"); return -1; + } } } @@ -1053,6 +1177,8 @@ int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char { int res; + register_device_error(dev, NULL); + res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); if (res < 0) register_device_error_format(dev, "ioctl (SFEATURE): %s", strerror(errno)); @@ -1064,6 +1190,8 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, { int res; + register_device_error(dev, NULL); + res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); if (res < 0) register_device_error_format(dev, "ioctl (GFEATURE): %s", strerror(errno)); @@ -1071,10 +1199,25 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return res; } +int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device *dev, const unsigned char *data, size_t length) +{ + int res; + + register_device_error(dev, NULL); + + res = ioctl(dev->device_handle, HIDIOCSOUTPUT(length), data); + if (res < 0) + register_device_error_format(dev, "ioctl (SOUTPUT): %s", strerror(errno)); + + return res; +} + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { int res; + register_device_error(dev, NULL); + res = ioctl(dev->device_handle, HIDIOCGINPUT(length), data); if (res < 0) register_device_error_format(dev, "ioctl (GINPUT): %s", strerror(errno)); @@ -1087,42 +1230,131 @@ void HID_API_EXPORT hid_close(hid_device *dev) if (!dev) return; - int ret = close(dev->device_handle); - - register_global_error((ret == -1)? strerror(errno): NULL); + close(dev->device_handle); /* Free the device error message */ register_device_error(dev, NULL); + hid_free_enumeration(dev->device_info); + free(dev); } int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { - return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + struct hid_device_info *info = hid_get_device_info(dev); + if (!info) { + // hid_get_device_info will have set an error already + return -1; + } + + if (info->manufacturer_string) { + wcsncpy(string, info->manufacturer_string, maxlen); + string[maxlen - 1] = L'\0'; + } + else { + string[0] = L'\0'; + } + + return 0; } int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { - return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + struct hid_device_info *info = hid_get_device_info(dev); + if (!info) { + // hid_get_device_info will have set an error already + return -1; + } + + if (info->product_string) { + wcsncpy(string, info->product_string, maxlen); + string[maxlen - 1] = L'\0'; + } + else { + string[0] = L'\0'; + } + + return 0; } int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { - return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + struct hid_device_info *info = hid_get_device_info(dev); + if (!info) { + // hid_get_device_info will have set an error already + return -1; + } + + if (info->serial_number) { + wcsncpy(string, info->serial_number, maxlen); + string[maxlen - 1] = L'\0'; + } + else { + string[0] = L'\0'; + } + + return 0; +} + + +HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { + if (!dev->device_info) { + // Lazy initialize device_info + dev->device_info = create_device_info_for_hid_device(dev); + } + + // create_device_info_for_hid_device will set an error if needed + return dev->device_info; } int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { - (void)dev; (void)string_index; (void)string; (void)maxlen; + + register_device_error(dev, "hid_get_indexed_string: not supported by hidraw"); + return -1; } +int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) +{ + struct hidraw_report_descriptor rpt_desc; + int res = get_hid_report_descriptor_from_hidraw(dev, &rpt_desc); + if (res < 0) { + /* error already registered */ + return res; + } + + if (rpt_desc.size < buf_size) { + buf_size = (size_t) rpt_desc.size; + } + + memcpy(buf, rpt_desc.value, buf_size); + + return (int) buf_size; +} + + /* Passing in NULL means asking for the last global error message. */ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { diff --git a/mac/CMakeLists.txt b/mac/CMakeLists.txt index a83664aae..0a1c1d95b 100644 --- a/mac/CMakeLists.txt +++ b/mac/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.4.3 FATAL_ERROR) +cmake_minimum_required(VERSION 3.4.3...3.25 FATAL_ERROR) list(APPEND HIDAPI_PUBLIC_HEADERS "hidapi_darwin.h") @@ -12,7 +12,7 @@ find_package(Threads REQUIRED) target_link_libraries(hidapi_darwin PUBLIC hidapi_include PRIVATE Threads::Threads - PRIVATE "-framework IOKit" "-framework CoreFoundation" "-framework AppKit" + PRIVATE "-framework IOKit" "-framework CoreFoundation" ) set_target_properties(hidapi_darwin diff --git a/mac/Makefile-manual b/mac/Makefile-manual index 27084922e..667c863c5 100644 --- a/mac/Makefile-manual +++ b/mac/Makefile-manual @@ -12,7 +12,7 @@ CC=gcc COBJS=hid.o ../hidtest/test.o OBJS=$(COBJS) CFLAGS+=-I../hidapi -I. -Wall -g -c -LIBS=-framework IOKit -framework CoreFoundation -framework AppKit +LIBS=-framework IOKit -framework CoreFoundation hidtest: $(OBJS) diff --git a/mac/hid.c b/mac/hid.c index d78ac9bee..e2b365c4f 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,9 +38,6 @@ #include "hidapi_darwin.h" -/* As defined in AppKit.h, but we don't need the entire AppKit for a single constant. */ -extern const double NSAppKitVersionNumber; - /* Barrier implementation because Mac OSX doesn't have pthread_barrier. It also doesn't have clock_gettime(). So much for POSIX and SUSv2. This implementation came from Brent Priddy and was posted on @@ -55,15 +54,15 @@ static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrie { (void) attr; - if(count == 0) { + if (count == 0) { errno = EINVAL; return -1; } - if(pthread_mutex_init(&barrier->mutex, 0) < 0) { + if (pthread_mutex_init(&barrier->mutex, 0) < 0) { return -1; } - if(pthread_cond_init(&barrier->cond, 0) < 0) { + if (pthread_cond_init(&barrier->cond, 0) < 0) { pthread_mutex_destroy(&barrier->mutex); return -1; } @@ -84,16 +83,18 @@ static int pthread_barrier_wait(pthread_barrier_t *barrier) { pthread_mutex_lock(&barrier->mutex); ++(barrier->count); - if(barrier->count >= barrier->trip_count) - { + if (barrier->count >= barrier->trip_count) { barrier->count = 0; - pthread_cond_broadcast(&barrier->cond); pthread_mutex_unlock(&barrier->mutex); + pthread_cond_broadcast(&barrier->cond); return 1; } - else - { - pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + else { + do { + pthread_cond_wait(&barrier->cond, &(barrier->mutex)); + } + while (barrier->count != 0); + pthread_mutex_unlock(&barrier->mutex); return 0; } @@ -118,13 +119,13 @@ static struct hid_api_version api_version = { static IOHIDManagerRef hid_mgr = 0x0; static int is_macos_10_10_or_greater = 0; static IOOptionBits device_open_options = 0; +static wchar_t *last_global_error_str = NULL; /* --- */ struct hid_device_ { IOHIDDeviceRef device_handle; IOOptionBits open_options; int blocking; - int uses_numbered_reports; int disconnected; CFStringRef run_loop_mode; CFRunLoopRef run_loop; @@ -132,6 +133,7 @@ struct hid_device_ { uint8_t *input_report_buf; CFIndex max_input_report_len; struct input_report *input_reports; + struct hid_device_info* device_info; pthread_t thread; pthread_mutex_t mutex; /* Protects input_reports */ @@ -139,22 +141,28 @@ struct hid_device_ { pthread_barrier_t barrier; /* Ensures correct startup sequence */ pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ int shutdown_thread; + wchar_t *last_error_str; }; static hid_device *new_hid_device(void) { hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + if (dev == NULL) { + return NULL; + } + dev->device_handle = NULL; dev->open_options = device_open_options; dev->blocking = 1; - dev->uses_numbered_reports = 0; dev->disconnected = 0; dev->run_loop_mode = NULL; dev->run_loop = NULL; dev->source = NULL; dev->input_report_buf = NULL; dev->input_reports = NULL; + dev->device_info = NULL; dev->shutdown_thread = 0; + dev->last_error_str = NULL; /* Thread objects */ pthread_mutex_init(&dev->mutex, NULL); @@ -187,6 +195,7 @@ static void free_hid_device(hid_device *dev) if (dev->source) CFRelease(dev->source); free(dev->input_report_buf); + hid_free_enumeration(dev->device_info); /* Clean up the thread objects */ pthread_barrier_destroy(&dev->shutdown_barrier); @@ -198,6 +207,88 @@ static void free_hid_device(hid_device *dev) free(dev); } + +/* The caller must free the returned string with free(). */ +static wchar_t *utf8_to_wchar_t(const char *utf8) +{ + wchar_t *ret = NULL; + + if (utf8) { + size_t wlen = mbstowcs(NULL, utf8, 0); + if ((size_t) -1 == wlen) { + return wcsdup(L""); + } + ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t)); + if (ret == NULL) { + /* as much as we can do at this point */ + return NULL; + } + mbstowcs(ret, utf8, wlen+1); + ret[wlen] = 0x0000; + } + + return ret; +} + + +/* Makes a copy of the given error message (and decoded according to the + * currently locale) into the wide string pointer pointed by error_str. + * The last stored error string is freed. + * Use register_error_str(NULL) to free the error message completely. */ +static void register_error_str(wchar_t **error_str, const char *msg) +{ + free(*error_str); + *error_str = utf8_to_wchar_t(msg); +} + +/* Similar to register_error_str, but allows passing a format string with va_list args into this function. */ +static void register_error_str_vformat(wchar_t **error_str, const char *format, va_list args) +{ + char msg[1024]; + vsnprintf(msg, sizeof(msg), format, args); + + register_error_str(error_str, msg); +} + +/* Set the last global error to be reported by hid_error(NULL). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored global error message is freed. + * Use register_global_error(NULL) to indicate "no error". */ +static void register_global_error(const char *msg) +{ + register_error_str(&last_global_error_str, msg); +} + +/* Similar to register_global_error, but allows passing a format string into this function. */ +static void register_global_error_format(const char *format, ...) +{ + va_list args; + va_start(args, format); + register_error_str_vformat(&last_global_error_str, format, args); + va_end(args); +} + +/* Set the last error for a device to be reported by hid_error(dev). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored device error message is freed. + * Use register_device_error(dev, NULL) to indicate "no error". */ +static void register_device_error(hid_device *dev, const char *msg) +{ + register_error_str(&dev->last_error_str, msg); +} + +/* Similar to register_device_error, but you can pass a format string into this function. */ +static void register_device_error_format(hid_device *dev, const char *format, ...) +{ + va_list args; + va_start(args, format); + register_error_str_vformat(&dev->last_error_str, format, args); + va_end(args); +} + + static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key) { CFTypeRef ref = IOHIDDeviceGetProperty(device, key); @@ -211,7 +302,7 @@ static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key) static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) { CFTypeRef ref; - int32_t value; + int32_t value = 0; ref = IOHIDDeviceGetProperty(device, key); if (ref) { @@ -223,6 +314,36 @@ static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) return 0; } +static bool try_get_int_property(IOHIDDeviceRef device, CFStringRef key, int32_t *out_val) +{ + bool result = false; + CFTypeRef ref; + + ref = IOHIDDeviceGetProperty(device, key); + if (ref) { + if (CFGetTypeID(ref) == CFNumberGetTypeID()) { + result = CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, out_val); + } + } + return result; +} + +static bool try_get_ioregistry_int_property(io_service_t service, CFStringRef property, int32_t *out_val) +{ + bool result = false; + CFTypeRef ref = IORegistryEntryCreateCFProperty(service, property, kCFAllocatorDefault, 0); + + if (ref) { + if (CFGetTypeID(ref) == CFNumberGetTypeID()) { + result = CFNumberGetValue(ref, kCFNumberSInt32Type, out_val); + } + + CFRelease(ref); + } + + return result; +} + static CFArrayRef get_usage_pairs(IOHIDDeviceRef device) { return get_array_property(device, CFSTR(kIOHIDDeviceUsagePairsKey)); @@ -254,7 +375,7 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t buf[0] = 0; - if (str) { + if (str && CFGetTypeID(str) == CFStringGetTypeID()) { CFIndex str_len = CFStringGetLength(str); CFRange range; CFIndex used_buf_len; @@ -322,15 +443,16 @@ static int init_hid_manager(void) return 0; } + register_global_error("Failed to create IOHIDManager"); return -1; } -HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version() +HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) { return &api_version; } -HID_API_EXPORT const char* HID_API_CALL hid_version_str() +HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) { return HID_API_VERSION_STR; } @@ -340,8 +462,10 @@ HID_API_EXPORT const char* HID_API_CALL hid_version_str() for failure. */ int HID_API_EXPORT hid_init(void) { + register_global_error(NULL); + if (!hid_mgr) { - is_macos_10_10_or_greater = (NSAppKitVersionNumber >= 1343); /* NSAppKitVersionNumber10_10 */ + is_macos_10_10_or_greater = (kCFCoreFoundationVersionNumber >= 1151.16); /* kCFCoreFoundationVersionNumber10_10 */ hid_darwin_set_open_exclusive(1); /* Backward compatibility */ return init_hid_manager(); } @@ -359,6 +483,9 @@ int HID_API_EXPORT hid_exit(void) hid_mgr = NULL; } + /* Free global error message */ + register_global_error(NULL); + return 0; } @@ -369,15 +496,56 @@ static void process_pending_events(void) { } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); } +static int read_usb_interface_from_hid_service_parent(io_service_t hid_service) +{ + int32_t result = -1; + bool success = false; + io_registry_entry_t current = IO_OBJECT_NULL; + kern_return_t res; + int parent_number = 0; + + res = IORegistryEntryGetParentEntry(hid_service, kIOServicePlane, ¤t); + while (KERN_SUCCESS == res + /* Only search up to 3 parent entries. + * With the default driver - the parent-of-interest supposed to be the first one, + * but lets assume some custom drivers or so, with deeper tree. */ + && parent_number < 3) { + io_registry_entry_t parent = IO_OBJECT_NULL; + int32_t interface_number = -1; + parent_number++; + + success = try_get_ioregistry_int_property(current, CFSTR(kUSBInterfaceNumber), &interface_number); + if (success) { + result = interface_number; + break; + } + + res = IORegistryEntryGetParentEntry(current, kIOServicePlane, &parent); + if (parent) { + IOObjectRelease(current); + current = parent; + } + + } + + if (current) { + IOObjectRelease(current); + current = IO_OBJECT_NULL; + } + + return result; +} + static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, int32_t usage_page, int32_t usage) { unsigned short dev_vid; unsigned short dev_pid; int BUF_LEN = 256; wchar_t buf[BUF_LEN]; + CFTypeRef transport_prop; struct hid_device_info *cur_dev; - io_object_t iokit_dev; + io_service_t hid_service; kern_return_t res; uint64_t entry_id = 0; @@ -401,9 +569,9 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, /* Fill in the path (as a unique ID of the service entry) */ cur_dev->path = NULL; - iokit_dev = IOHIDDeviceGetService(dev); - if (iokit_dev != MACH_PORT_NULL) { - res = IORegistryEntryGetRegistryEntryID(iokit_dev, &entry_id); + hid_service = IOHIDDeviceGetService(dev); + if (hid_service != MACH_PORT_NULL) { + res = IORegistryEntryGetRegistryEntryID(hid_service, &entry_id); } else { res = KERN_INVALID_ARGUMENT; @@ -412,10 +580,11 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, if (res == KERN_SUCCESS) { /* max value of entry_id(uint64_t) is 18446744073709551615 which is 20 characters long, so for (max) "path" string 'DevSrvsID:18446744073709551615' we would need - 9+1+20+1=31 bytes byffer, but allocate 32 for simple alignment */ - cur_dev->path = calloc(1, 32); + 9+1+20+1=31 bytes buffer, but allocate 32 for simple alignment */ + const size_t path_len = 32; + cur_dev->path = calloc(1, path_len); if (cur_dev->path != NULL) { - sprintf(cur_dev->path, "DevSrvsID:%llu", entry_id); + snprintf(cur_dev->path, path_len, "DevSrvsID:%llu", entry_id); } } @@ -441,16 +610,40 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, /* Release Number */ cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); - /* Interface Number */ - /* We can only retrieve the interface number for USB HID devices. - * IOKit always seems to return 0 when querying a standard USB device - * for its interface. */ - int is_usb_hid = get_int_property(dev, CFSTR(kUSBInterfaceClass)) == kUSBHIDClass; - if (is_usb_hid) { - /* Get the interface number */ - cur_dev->interface_number = get_int_property(dev, CFSTR(kUSBInterfaceNumber)); - } else { - cur_dev->interface_number = -1; + /* Interface Number. + * We can only retrieve the interface number for USB HID devices. + * See below */ + cur_dev->interface_number = -1; + + /* Bus Type */ + transport_prop = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDTransportKey)); + + if (transport_prop != NULL && CFGetTypeID(transport_prop) == CFStringGetTypeID()) { + if (CFStringCompare((CFStringRef)transport_prop, CFSTR(kIOHIDTransportUSBValue), 0) == kCFCompareEqualTo) { + int32_t interface_number = -1; + cur_dev->bus_type = HID_API_BUS_USB; + + /* A IOHIDDeviceRef used to have this simple property, + * until macOS 13.3 - we will try to use it. */ + if (try_get_int_property(dev, CFSTR(kUSBInterfaceNumber), &interface_number)) { + cur_dev->interface_number = interface_number; + } else { + /* Otherwise fallback to io_service_t property. + * (of one of the parent services). */ + cur_dev->interface_number = read_usb_interface_from_hid_service_parent(hid_service); + + /* If the above doesn't work - + * no (known) fallback exists at this point. */ + } + + /* Match "Bluetooth", "BluetoothLowEnergy" and "Bluetooth Low Energy" strings */ + } else if (CFStringHasPrefix((CFStringRef)transport_prop, CFSTR(kIOHIDTransportBluetoothValue))) { + cur_dev->bus_type = HID_API_BUS_BLUETOOTH; + } else if (CFStringCompare((CFStringRef)transport_prop, CFSTR(kIOHIDTransportI2CValue), 0) == kCFCompareEqualTo) { + cur_dev->bus_type = HID_API_BUS_I2C; + } else if (CFStringCompare((CFStringRef)transport_prop, CFSTR(kIOHIDTransportSPIValue), 0) == kCFCompareEqualTo) { + cur_dev->bus_type = HID_API_BUS_SPI; + } } return cur_dev; @@ -511,8 +704,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, int i; /* Set up the HID Manager if it hasn't been done */ - if (hid_init() < 0) + if (hid_init() < 0) { return NULL; + } + /* register_global_error: global error is set/reset by hid_init */ /* give the IOHIDManager a chance to update itself */ process_pending_events(); @@ -540,14 +735,17 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, } CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); - if (device_set == NULL) { - return NULL; - } - /* Convert the list into a C array so we can iterate easily. */ - num_devices = CFSetGetCount(device_set); - IOHIDDeviceRef *device_array = (IOHIDDeviceRef*) calloc(num_devices, sizeof(IOHIDDeviceRef)); - CFSetGetValues(device_set, (const void **) device_array); + IOHIDDeviceRef *device_array = NULL; + + if (device_set != NULL) { + /* Convert the list into a C array so we can iterate easily. */ + num_devices = CFSetGetCount(device_set); + device_array = (IOHIDDeviceRef*) calloc(num_devices, sizeof(IOHIDDeviceRef)); + CFSetGetValues(device_set, (const void **) device_array); + } else { + num_devices = 0; + } /* Iterate over each device, making an entry for it. */ for (i = 0; i < num_devices; i++) { @@ -570,14 +768,23 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, } cur_dev = tmp; - /* move the pointer to the tail of returnd list */ + /* move the pointer to the tail of returned list */ while (cur_dev->next != NULL) { cur_dev = cur_dev->next; } } free(device_array); - CFRelease(device_set); + if (device_set != NULL) + CFRelease(device_set); + + if (root == NULL) { + if (vendor_id == 0 && product_id == 0) { + register_global_error("No HID devices found in the system."); + } else { + register_global_error("No HID devices with requested VID/PID found in the system."); + } + } return root; } @@ -600,11 +807,18 @@ void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { /* This function is identical to the Linux version. Platform independent. */ + struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device * handle = NULL; + /* register_global_error: global error is reset by hid_enumerate/hid_init */ devs = hid_enumerate(vendor_id, product_id); + if (devs == NULL) { + /* register_global_error: global error is already set by hid_enumerate */ + return NULL; + } + cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && @@ -624,8 +838,9 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr } if (path_to_open) { - /* Open the device */ handle = hid_open_path(path_to_open); + } else { + register_global_error("Device with requested VID/PID/(SerialNumber) not found"); } hid_free_enumeration(devs); @@ -740,7 +955,7 @@ static void *read_thread(void *param) while (!dev->shutdown_thread && !dev->disconnected) { code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); /* Return if the device has been disconnected */ - if (code == kCFRunLoopRunFinished) { + if (code == kCFRunLoopRunFinished || code == kCFRunLoopRunStopped) { dev->disconnected = 1; break; } @@ -806,17 +1021,25 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) hid_device *dev = NULL; io_registry_entry_t entry = MACH_PORT_NULL; IOReturn ret = kIOReturnInvalid; + char str[32]; /* Set up the HID Manager if it hasn't been done */ - if (hid_init() < 0) - goto return_error; + if (hid_init() < 0) { + return NULL; + } + /* register_global_error: global error is set/reset by hid_init */ dev = new_hid_device(); + if (!dev) { + register_global_error("Couldn't allocate memory"); + return NULL; + } /* Get the IORegistry entry for the given path */ entry = hid_open_service_registry_from_path(path); if (entry == MACH_PORT_NULL) { /* Path wasn't valid (maybe device was removed?) */ + register_global_error("hid_open_path: device mach entry not found with the given path"); goto return_error; } @@ -824,42 +1047,41 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry); if (dev->device_handle == NULL) { /* Error creating the HID device */ + register_global_error("hid_open_path: failed to create IOHIDDevice from the mach entry"); goto return_error; } /* Open the IOHIDDevice */ ret = IOHIDDeviceOpen(dev->device_handle, dev->open_options); - if (ret == kIOReturnSuccess) { - char str[32]; + if (ret != kIOReturnSuccess) { + register_global_error_format("hid_open_path: failed to open IOHIDDevice from mach entry: (0x%08X) %s", ret, mach_error_string(ret)); + goto return_error; + } - /* Create the buffers for receiving data */ - dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); - dev->input_report_buf = (uint8_t*) calloc(dev->max_input_report_len, sizeof(uint8_t)); + /* Create the buffers for receiving data */ + dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle); + dev->input_report_buf = (uint8_t*) calloc(dev->max_input_report_len, sizeof(uint8_t)); - /* Create the Run Loop Mode for this device. - printing the reference seems to work. */ - sprintf(str, "HIDAPI_%p", (void*) dev->device_handle); - dev->run_loop_mode = - CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); + /* Create the Run Loop Mode for this device. + printing the reference seems to work. */ + snprintf(str, sizeof(str), "HIDAPI_%p", (void*) dev->device_handle); + dev->run_loop_mode = + CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); - /* Attach the device to a Run Loop */ - IOHIDDeviceRegisterInputReportCallback( - dev->device_handle, dev->input_report_buf, dev->max_input_report_len, - &hid_report_callback, dev); - IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); + /* Attach the device to a Run Loop */ + IOHIDDeviceRegisterInputReportCallback( + dev->device_handle, dev->input_report_buf, dev->max_input_report_len, + &hid_report_callback, dev); + IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); - /* Start the read thread */ - pthread_create(&dev->thread, NULL, read_thread, dev); + /* Start the read thread */ + pthread_create(&dev->thread, NULL, read_thread, dev); - /* Wait here for the read thread to be initialized. */ - pthread_barrier_wait(&dev->barrier); + /* Wait here for the read thread to be initialized. */ + pthread_barrier_wait(&dev->barrier); - IOObjectRelease(entry); - return dev; - } - else { - goto return_error; - } + IOObjectRelease(entry); + return dev; return_error: if (dev->device_handle != NULL) @@ -879,7 +1101,10 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char IOReturn res; unsigned char report_id; + register_device_error(dev, NULL); + if (!data || (length == 0)) { + register_device_error(dev, strerror(EINVAL)); return -1; } @@ -894,6 +1119,7 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char /* Avoid crash if the device has been unplugged. */ if (dev->disconnected) { + register_device_error(dev, "Device is disconnected"); return -1; } @@ -902,11 +1128,12 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char report_id, data_to_send, length_to_send); - if (res == kIOReturnSuccess) { - return (int) length; + if (res != kIOReturnSuccess) { + register_device_error_format(dev, "IOHIDDeviceSetReport failed: (0x%08X) %s", res, mach_error_string(res)); + return -1; } - return -1; + return (int) length; } static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data, size_t length) @@ -916,6 +1143,8 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data IOReturn res = kIOReturnSuccess; const unsigned char report_id = data[0]; + register_device_error(dev, NULL); + if (report_id == 0x0) { /* Not using numbered Reports. Don't send the report number. */ @@ -925,6 +1154,7 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data /* Avoid crash if the device has been unplugged. */ if (dev->disconnected) { + register_device_error(dev, "Device is disconnected"); return -1; } @@ -933,14 +1163,16 @@ static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data report_id, report, &report_length); - if (res == kIOReturnSuccess) { - if (report_id == 0x0) { /* 0 report number still present at the beginning */ - report_length++; - } - return (int) report_length; + if (res != kIOReturnSuccess) { + register_device_error_format(dev, "IOHIDDeviceGetReport failed: (0x%08X) %s", res, mach_error_string(res)); + return -1; } - return -1; + if (report_id == 0x0) { /* 0 report number still present at the beginning */ + report_length++; + } + + return (int) report_length; } int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) @@ -955,14 +1187,16 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length) return buffer (data), and delete the liked list item. */ struct input_report *rpt = dev->input_reports; size_t len = (length < rpt->len)? length: rpt->len; - memcpy(data, rpt->data, len); + if (data != NULL) { + memcpy(data, rpt->data, len); + } dev->input_reports = rpt->next; free(rpt->data); free(rpt); return (int) len; } -static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) +static int cond_wait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) { while (!dev->input_reports) { int res = pthread_cond_wait(cond, mutex); @@ -975,14 +1209,15 @@ static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_ to sleep. See the pthread_cond_timedwait() man page for details. */ - if (dev->shutdown_thread || dev->disconnected) + if (dev->shutdown_thread || dev->disconnected) { return -1; + } } return 0; } -static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) +static int cond_timedwait(hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { while (!dev->input_reports) { int res = pthread_cond_timedwait(cond, mutex, abstime); @@ -995,8 +1230,9 @@ static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_m to sleep. See the pthread_cond_timedwait() man page for details. */ - if (dev->shutdown_thread || dev->disconnected) + if (dev->shutdown_thread || dev->disconnected) { return -1; + } } return 0; @@ -1020,6 +1256,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t /* Return if the device has been disconnected. */ if (dev->disconnected) { bytes_read = -1; + register_device_error(dev, "hid_read_timeout: device disconnected"); goto ret; } @@ -1028,6 +1265,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t has been an error. An error code of -1 should be returned. */ bytes_read = -1; + register_device_error(dev, "hid_read_timeout: thread shutdown"); goto ret; } @@ -1041,6 +1279,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t bytes_read = return_data(dev, data, length); else { /* There was an error, or a device disconnection. */ + register_device_error(dev, "hid_read_timeout: error waiting for more data"); bytes_read = -1; } } @@ -1059,12 +1298,14 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t } res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); - if (res == 0) + if (res == 0) { bytes_read = return_data(dev, data, length); - else if (res == ETIMEDOUT) + } else if (res == ETIMEDOUT) { bytes_read = 0; - else + } else { + register_device_error(dev, "hid_read_timeout: error waiting for more data"); bytes_read = -1; + } } else { /* Purely non-blocking */ @@ -1100,8 +1341,13 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, return get_report(dev, kIOHIDReportTypeFeature, data, length); } +int HID_API_EXPORT hid_send_output_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, kIOHIDReportTypeOutput, data, length); +} + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) -{ +{ return get_report(dev, kIOHIDReportTypeInput, data, length); } @@ -1161,17 +1407,72 @@ void HID_API_EXPORT hid_close(hid_device *dev) int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { - return get_manufacturer_string(dev->device_handle, string, maxlen); + if (!string || !maxlen) + { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + struct hid_device_info *info = hid_get_device_info(dev); + if (!info) + { + // hid_get_device_info will have set an error already + return -1; + } + + wcsncpy(string, info->manufacturer_string, maxlen); + string[maxlen - 1] = L'\0'; + + return 0; } int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { - return get_product_string(dev->device_handle, string, maxlen); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + struct hid_device_info *info = hid_get_device_info(dev); + if (!info) { + // hid_get_device_info will have set an error already + return -1; + } + + wcsncpy(string, info->product_string, maxlen); + string[maxlen - 1] = L'\0'; + + return 0; } int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { - return get_serial_number(dev->device_handle, string, maxlen); + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + struct hid_device_info *info = hid_get_device_info(dev); + if (!info) { + // hid_get_device_info will have set an error already + return -1; + } + + wcsncpy(string, info->serial_number, maxlen); + string[maxlen - 1] = L'\0'; + + return 0; +} + +HID_API_EXPORT struct hid_device_info *HID_API_CALL hid_get_device_info(hid_device *dev) { + if (!dev->device_info) { + dev->device_info = create_device_info(dev->device_handle); + if (!dev->device_info) { + register_device_error(dev, "Failed to create hid_device_info"); + } + } + + return dev->device_info; } int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) @@ -1181,9 +1482,8 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index (void) string; (void) maxlen; - /* TODO: */ - - return 0; + register_device_error(dev, "hid_get_indexed_string: not available on this platform"); + return -1; } int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *location_id) @@ -1193,6 +1493,7 @@ int HID_API_EXPORT_CALL hid_darwin_get_location_id(hid_device *dev, uint32_t *lo *location_id = (uint32_t) res; return 0; } else { + register_device_error(dev, "Failed to get IOHIDLocationID property"); return -1; } } @@ -1215,10 +1516,42 @@ int HID_API_EXPORT_CALL hid_darwin_is_device_open_exclusive(hid_device *dev) return (dev->open_options == kIOHIDOptionsTypeSeizeDevice) ? 1 : 0; } +int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) +{ + CFTypeRef ref = IOHIDDeviceGetProperty(dev->device_handle, CFSTR(kIOHIDReportDescriptorKey)); + if (ref != NULL && CFGetTypeID(ref) == CFDataGetTypeID()) { + CFDataRef report_descriptor = (CFDataRef) ref; + const UInt8 *descriptor_buf = CFDataGetBytePtr(report_descriptor); + CFIndex descriptor_buf_len = CFDataGetLength(report_descriptor); + size_t copy_len = (size_t) descriptor_buf_len; + + if (descriptor_buf == NULL || descriptor_buf_len < 0) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + if (buf_size < copy_len) { + copy_len = buf_size; + } + + memcpy(buf, descriptor_buf, copy_len); + return copy_len; + } + else { + register_device_error(dev, "Failed to get kIOHIDReportDescriptorKey property"); + return -1; + } +} + HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { - (void) dev; - /* TODO: */ + if (dev) { + if (dev->last_error_str == NULL) + return L"Success"; + return dev->last_error_str; + } - return L"hid_error is not implemented yet"; + if (last_global_error_str == NULL) + return L"Success"; + return last_global_error_str; } diff --git a/meson.build b/meson.build new file mode 100644 index 000000000..d7867cb4e --- /dev/null +++ b/meson.build @@ -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 diff --git a/netbsd/CMakeLists.txt b/netbsd/CMakeLists.txt new file mode 100644 index 000000000..3b3e4d049 --- /dev/null +++ b/netbsd/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.6.3...3.25 FATAL_ERROR) + +add_library(hidapi_netbsd + ${HIDAPI_PUBLIC_HEADERS} + hid.c +) +target_link_libraries(hidapi_netbsd PUBLIC hidapi_include) + +find_package(Threads REQUIRED) + +target_link_libraries(hidapi_netbsd PRIVATE Threads::Threads) + +set_target_properties(hidapi_netbsd + PROPERTIES + EXPORT_NAME "netbsd" + OUTPUT_NAME "hidapi-netbsd" + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER "${HIDAPI_PUBLIC_HEADERS}" +) + +# compatibility with find_package() +add_library(hidapi::netbsd ALIAS hidapi_netbsd) +# compatibility with raw library link +add_library(hidapi-netbsd ALIAS hidapi_netbsd) + +if(HIDAPI_INSTALL_TARGETS) + install(TARGETS hidapi_netbsd 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-netbsd.pc.in") diff --git a/netbsd/README.md b/netbsd/README.md new file mode 100644 index 000000000..f1b12a0ae --- /dev/null +++ b/netbsd/README.md @@ -0,0 +1,29 @@ +Implementation Notes +-------------------- +NetBSD maps every `uhidev` device to one or more `uhid` +devices. Each `uhid` device only supports one report ID. +The parent device `uhidev` creates one `uhid` device per +report ID found in the hardware's report descriptor. + +In the event there are no report ID(s) found within the +report descriptor, only one `uhid` device with a report ID +of `0` is created. + +In order to remain compatible with existing `hidapi` APIs, +all the `uhid` devices created by the parent `uhidev` device +must be opened under the same `hid_device` instance to ensure +that we can route reports to their appropriate `uhid` device. + +Internally the `uhid` driver will insert the report ID as +needed so we must also omit the report ID in any situation +where the `hidapi` API expects it to be included in the +report data stream. + +Given the design of `uhid`, it must be augmented with extra +platform specific APIs to ensure that the exact relationship +between `uhidev` devices and `uhid` devices can be determined. + +The NetBSD implementation does this via the `drvctl` kernel +driver. At present there is no known way to do this on OpenBSD +for a `uhid` implementation to be at the same level as the +NetBSD one. diff --git a/netbsd/hid.c b/netbsd/hid.c new file mode 100644 index 000000000..9aed28f38 --- /dev/null +++ b/netbsd/hid.c @@ -0,0 +1,1178 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + James Buren + libusb/hidapi Team + + Copyright 2023, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + https://github.com/libusb/hidapi . +********************************************************/ + +/* C */ +#include +#include +#include +#include +#include +#include + +/* Unix */ +#include +#include +#include +#include + +/* NetBSD */ +#include +#include +#include + +#include "hidapi.h" + +#define HIDAPI_MAX_CHILD_DEVICES 256 + +struct hid_device_ { + int device_handle; + int blocking; + wchar_t *last_error_str; + struct hid_device_info *device_info; + size_t poll_handles_length; + struct pollfd poll_handles[256]; + int report_handles[256]; + char path[USB_MAX_DEVNAMELEN]; +}; + +struct hid_enumerate_data { + struct hid_device_info *root; + struct hid_device_info *end; + int drvctl; + uint16_t vendor_id; + uint16_t product_id; +}; + +typedef void (*enumerate_devices_callback) (const struct usb_device_info *, void *); + +static wchar_t *last_global_error_str = NULL; + +/* The caller must free the returned string with free(). */ +static wchar_t *utf8_to_wchar_t(const char *utf8) +{ + wchar_t *ret = NULL; + + if (utf8) { + size_t wlen = mbstowcs(NULL, utf8, 0); + if ((size_t) -1 == wlen) { + return wcsdup(L""); + } + ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t)); + if (ret == NULL) { + /* as much as we can do at this point */ + return NULL; + } + mbstowcs(ret, utf8, wlen+1); + ret[wlen] = 0x0000; + } + + return ret; +} + +/* Makes a copy of the given error message (and decoded according to the + * currently locale) into the wide string pointer pointed by error_str. + * The last stored error string is freed. + * Use register_error_str(NULL) to free the error message completely. */ +static void register_error_str(wchar_t **error_str, const char *msg) +{ + free(*error_str); + *error_str = utf8_to_wchar_t(msg); +} + +/* Semilar to register_error_str, but allows passing a format string with va_list args into this function. */ +static void register_error_str_vformat(wchar_t **error_str, const char *format, va_list args) +{ + char msg[256]; + vsnprintf(msg, sizeof(msg), format, args); + + register_error_str(error_str, msg); +} + +/* Set the last global error to be reported by hid_error(NULL). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored global error message is freed. + * Use register_global_error(NULL) to indicate "no error". */ +static void register_global_error(const char *msg) +{ + register_error_str(&last_global_error_str, msg); +} + +/* Similar to register_global_error, but allows passing a format string into this function. */ +static void register_global_error_format(const char *format, ...) +{ + va_list args; + va_start(args, format); + register_error_str_vformat(&last_global_error_str, format, args); + va_end(args); +} + +/* Set the last error for a device to be reported by hid_error(dev). + * The given error message will be copied (and decoded according to the + * currently locale, so do not pass in string constants). + * The last stored device error message is freed. + * Use register_device_error(dev, NULL) to indicate "no error". */ +static void register_device_error(hid_device *dev, const char *msg) +{ + register_error_str(&dev->last_error_str, msg); +} + +/* Similar to register_device_error, but you can pass a format string into this function. */ +static void register_device_error_format(hid_device *dev, const char *format, ...) +{ + va_list args; + va_start(args, format); + register_error_str_vformat(&dev->last_error_str, format, args); + va_end(args); +} + + +/* + * Gets the size of the HID item at the given position + * Returns 1 if successful, 0 if an invalid key + * Sets data_len and key_size when successful + */ +static int get_hid_item_size(const uint8_t *report_descriptor, uint32_t size, unsigned int pos, int *data_len, int *key_size) +{ + int key = report_descriptor[pos]; + int size_code; + + /* + * This is a Long Item. The next byte contains the + * length of the data section (value) for this key. + * See the HID specification, version 1.11, section + * 6.2.2.3, titled "Long Items." + */ + if ((key & 0xf0) == 0xf0) { + if (pos + 1 < size) + { + *data_len = report_descriptor[pos + 1]; + *key_size = 3; + return 1; + } + *data_len = 0; /* malformed report */ + *key_size = 0; + } + + /* + * This is a Short Item. The bottom two bits of the + * key contain the size code for the data section + * (value) for this key. Refer to the HID + * specification, version 1.11, section 6.2.2.2, + * titled "Short Items." + */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + *data_len = size_code; + *key_size = 1; + return 1; + case 3: + *data_len = 4; + *key_size = 1; + return 1; + default: + /* Can't ever happen since size_code is & 0x3 */ + *data_len = 0; + *key_size = 0; + break; + }; + + /* malformed report */ + return 0; +} + +/* + * Get bytes from a HID Report Descriptor. + * Only call with a num_bytes of 0, 1, 2, or 4. + */ +static uint32_t get_hid_report_bytes(const uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) +{ + /* Return if there aren't enough bytes. */ + if (cur + num_bytes >= len) + return 0; + + if (num_bytes == 0) + return 0; + else if (num_bytes == 1) + return rpt[cur + 1]; + else if (num_bytes == 2) + return (rpt[cur + 2] * 256 + rpt[cur + 1]); + else if (num_bytes == 4) + return ( + rpt[cur + 4] * 0x01000000 + + rpt[cur + 3] * 0x00010000 + + rpt[cur + 2] * 0x00000100 + + rpt[cur + 1] * 0x00000001 + ); + else + return 0; +} + +/* + * Iterates until the end of a Collection. + * Assumes that *pos is exactly at the beginning of a Collection. + * Skips all nested Collection, i.e. iterates until the end of current level Collection. + * + * The return value is non-0 when an end of current Collection is found, + * 0 when error is occured (broken Descriptor, end of a Collection is found before its begin, + * or no Collection is found at all). + */ +static int hid_iterate_over_collection(const uint8_t *report_descriptor, uint32_t size, unsigned int *pos, int *data_len, int *key_size) +{ + int collection_level = 0; + + while (*pos < size) { + int key = report_descriptor[*pos]; + int key_cmd = key & 0xfc; + + /* Determine data_len and key_size */ + if (!get_hid_item_size(report_descriptor, size, *pos, data_len, key_size)) + return 0; /* malformed report */ + + switch (key_cmd) { + case 0xa0: /* Collection 6.2.2.4 (Main) */ + collection_level++; + break; + case 0xc0: /* End Collection 6.2.2.4 (Main) */ + collection_level--; + break; + } + + if (collection_level < 0) { + /* Broken descriptor or someone is using this function wrong, + * i.e. should be called exactly at the collection start */ + return 0; + } + + if (collection_level == 0) { + /* Found it! + * Also possible when called not at the collection start, but should not happen if used correctly */ + return 1; + } + + *pos += *data_len + *key_size; + } + + return 0; /* Did not find the end of a Collection */ +} + +struct hid_usage_iterator { + unsigned int pos; + int usage_page_found; + unsigned short usage_page; +}; + +/* + * Retrieves the device's Usage Page and Usage from the report descriptor. + * The algorithm returns the current Usage Page/Usage pair whenever a new + * Collection is found and a Usage Local Item is currently in scope. + * Usage Local Items are consumed by each Main Item (See. 6.2.2.8). + * The algorithm should give similar results as Apple's: + * https://developer.apple.com/documentation/iokit/kiohiddeviceusagepairskey?language=objc + * Physical Collections are also matched (macOS does the same). + * + * This function can be called repeatedly until it returns non-0 + * Usage is found. pos is the starting point (initially 0) and will be updated + * to the next search position. + * + * The return value is 0 when a pair is found. + * 1 when finished processing descriptor. + * -1 on a malformed report. + */ +static int get_next_hid_usage(const uint8_t *report_descriptor, uint32_t size, struct hid_usage_iterator *ctx, unsigned short *usage_page, unsigned short *usage) +{ + int data_len, key_size; + int initial = ctx->pos == 0; /* Used to handle case where no top-level application collection is defined */ + + int usage_found = 0; + + while (ctx->pos < size) { + int key = report_descriptor[ctx->pos]; + int key_cmd = key & 0xfc; + + /* Determine data_len and key_size */ + if (!get_hid_item_size(report_descriptor, size, ctx->pos, &data_len, &key_size)) + return -1; /* malformed report */ + + switch (key_cmd) { + case 0x4: /* Usage Page 6.2.2.7 (Global) */ + ctx->usage_page = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); + ctx->usage_page_found = 1; + break; + + case 0x8: /* Usage 6.2.2.8 (Local) */ + if (data_len == 4) { /* Usages 5.5 / Usage Page 6.2.2.7 */ + ctx->usage_page = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos + 2); + ctx->usage_page_found = 1; + *usage = get_hid_report_bytes(report_descriptor, size, 2, ctx->pos); + usage_found = 1; + } + else { + *usage = get_hid_report_bytes(report_descriptor, size, data_len, ctx->pos); + usage_found = 1; + } + break; + + case 0xa0: /* Collection 6.2.2.4 (Main) */ + if (!hid_iterate_over_collection(report_descriptor, size, &ctx->pos, &data_len, &key_size)) { + return -1; + } + + /* A pair is valid - to be reported when Collection is found */ + if (usage_found && ctx->usage_page_found) { + *usage_page = ctx->usage_page; + return 0; + } + + break; + } + + /* Skip over this key and its associated data */ + ctx->pos += data_len + key_size; + } + + /* If no top-level application collection is found and usage page/usage pair is found, pair is valid + https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections */ + if (initial && usage_found && ctx->usage_page_found) { + *usage_page = ctx->usage_page; + return 0; /* success */ + } + + return 1; /* finished processing */ +} + +static struct hid_device_info *create_device_info(const struct usb_device_info *udi, const char *path, const struct usb_ctl_report_desc *ucrd) +{ + struct hid_device_info *root; + struct hid_device_info *end; + + root = (struct hid_device_info *) calloc(1, sizeof(struct hid_device_info)); + if (!root) + return NULL; + + end = root; + + /* Path */ + end->path = (path) ? strdup(path) : NULL; + + /* Vendor Id */ + end->vendor_id = udi->udi_vendorNo; + + /* Product Id */ + end->product_id = udi->udi_productNo; + + /* Serial Number */ + end->serial_number = utf8_to_wchar_t(udi->udi_serial); + + /* Release Number */ + end->release_number = udi->udi_releaseNo; + + /* Manufacturer String */ + end->manufacturer_string = utf8_to_wchar_t(udi->udi_vendor); + + /* Product String */ + end->product_string = utf8_to_wchar_t(udi->udi_product); + + /* Usage Page */ + end->usage_page = 0; + + /* Usage */ + end->usage = 0; + + /* Interface Number */ + end->interface_number = -1; + + /* Next Device Info */ + end->next = NULL; + + /* Bus Type */ + end->bus_type = HID_API_BUS_USB; + + if (ucrd) { + uint16_t page; + uint16_t usage; + struct hid_usage_iterator usage_iterator; + + page = usage = 0; + memset(&usage_iterator, 0, sizeof(usage_iterator)); + + /* + * Parse the first usage and usage page + * out of the report descriptor. + */ + if (get_next_hid_usage(ucrd->ucrd_data, ucrd->ucrd_size, &usage_iterator, &page, &usage) == 0) { + end->usage_page = page; + end->usage = usage; + } + + /* + * Parse any additional usage and usage pages + * out of the report descriptor. + */ + while (get_next_hid_usage(ucrd->ucrd_data, ucrd->ucrd_size, &usage_iterator, &page, &usage) == 0) { + /* Create new record for additional usage pairs */ + struct hid_device_info *node = (struct hid_device_info *) calloc(1, sizeof(struct hid_device_info)); + + if (!node) + continue; + + /* Update fields */ + node->path = (end->path) ? strdup(end->path) : NULL; + node->vendor_id = end->vendor_id; + node->product_id = end->product_id; + node->serial_number = (end->serial_number) ? wcsdup(end->serial_number) : NULL; + node->release_number = end->release_number; + node->manufacturer_string = (end->manufacturer_string) ? wcsdup(end->manufacturer_string) : NULL; + node->product_string = (end->product_string) ? wcsdup(end->product_string) : NULL; + node->usage_page = page; + node->usage = usage; + node->interface_number = end->interface_number; + node->next = NULL; + node->bus_type = end->bus_type; + + /* Insert node */ + end->next = node; + end = node; + } + } + + return root; +} + +static int is_usb_controller(const char *s) +{ + return (!strncmp(s, "usb", 3) && isdigit((int) s[3])); +} + +static int is_uhid_parent_device(const char *s) +{ + return (!strncmp(s, "uhidev", 6) && isdigit((int) s[6])); +} + +static int is_uhid_device(const char *s) +{ + return (!strncmp(s, "uhid", 4) && isdigit((int) s[4])); +} + +static void walk_device_tree(int drvctl, const char *dev, int depth, char arr[static HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN], size_t *len, int (*cmp) (const char *)) +{ + int res; + char childname[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + struct devlistargs dla; + + if (depth && (!dev || !*dev)) + return; + + if (cmp(dev) && *len < HIDAPI_MAX_CHILD_DEVICES) + strlcpy(arr[(*len)++], dev, sizeof(*arr)); + + strlcpy(dla.l_devname, dev, sizeof(dla.l_devname)); + dla.l_childname = childname; + dla.l_children = HIDAPI_MAX_CHILD_DEVICES; + + res = ioctl(drvctl, DRVLISTDEV, &dla); + if (res == -1) + return; + + /* + * DO NOT CHANGE THIS. This is a fail-safe check + * for the unlikely event that a parent device has + * more than HIDAPI_MAX_CHILD_DEVICES child devices + * to prevent iterating over uninitialized data. + */ + if (dla.l_children > HIDAPI_MAX_CHILD_DEVICES) + return; + + for (size_t i = 0; i < dla.l_children; i++) + walk_device_tree(drvctl, dla.l_childname[i], depth + 1, arr, len, cmp); +} + +static void enumerate_usb_devices(int bus, uint8_t addr, enumerate_devices_callback func, void *data) +{ + int res; + struct usb_device_info udi; + + udi.udi_addr = addr; + + res = ioctl(bus, USB_DEVICEINFO, &udi); + if (res == -1) + return; + + for (int port = 0; port < udi.udi_nports; port++) { + addr = udi.udi_ports[port]; + if (addr >= USB_MAX_DEVICES) + continue; + + enumerate_usb_devices(bus, addr, func, data); + } + + func(&udi, data); +} + +static void hid_enumerate_callback(const struct usb_device_info *udi, void *data) +{ + struct hid_enumerate_data *hed; + + hed = (struct hid_enumerate_data *) data; + + if (hed->vendor_id != 0 && hed->vendor_id != udi->udi_vendorNo) + return; + + if (hed->product_id != 0 && hed->product_id != udi->udi_productNo) + return; + + for (size_t i = 0; i < USB_MAX_DEVNAMES; i++) { + const char *parent_dev; + char arr[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + size_t len; + const char *child_dev; + char devpath[USB_MAX_DEVNAMELEN]; + int uhid; + struct usb_ctl_report_desc ucrd; + int use_ucrd; + struct hid_device_info *node; + + parent_dev = udi->udi_devnames[i]; + if (!is_uhid_parent_device(parent_dev)) + continue; + + len = 0; + walk_device_tree(hed->drvctl, parent_dev, 0, arr, &len, is_uhid_device); + + if (len == 0) + continue; + + child_dev = arr[0]; + strlcpy(devpath, "/dev/", sizeof(devpath)); + strlcat(devpath, child_dev, sizeof(devpath)); + + uhid = open(devpath, O_RDONLY | O_CLOEXEC); + if (uhid >= 0) { + use_ucrd = (ioctl(uhid, USB_GET_REPORT_DESC, &ucrd) != -1); + close(uhid); + } else { + use_ucrd = 0; + } + + node = create_device_info(udi, parent_dev, (use_ucrd) ? &ucrd : NULL); + if (!node) + continue; + + if (!hed->root) { + hed->root = node; + hed->end = node; + } else { + hed->end->next = node; + hed->end = node; + } + + while (hed->end->next) + hed->end = hed->end->next; + } +} + +static int set_report(hid_device *dev, const uint8_t *data, size_t length, int report) +{ + int res; + int device_handle; + struct usb_ctl_report ucr; + + if (length < 1) { + register_device_error(dev, "report must be greater than 1 byte"); + return -1; + } + + device_handle = dev->report_handles[*data]; + if (device_handle < 0) { + register_device_error_format(dev, "unsupported report id: %hhu", *data); + return -1; + } + + length--; + data++; + + if (length > sizeof(ucr.ucr_data)) { + register_device_error_format(dev, "report must be less than or equal to %zu bytes", sizeof(ucr.ucr_data)); + return -1; + } + + ucr.ucr_report = report; + memcpy(ucr.ucr_data, data, length); + + res = ioctl(device_handle, USB_SET_REPORT, &ucr); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_SET_REPORT): %s", strerror(errno)); + return -1; + } + + return (int) (length + 1); +} + +static int get_report(hid_device *dev, uint8_t *data, size_t length, int report) +{ + int res; + int device_handle; + struct usb_ctl_report ucr; + + if (length < 1) { + register_device_error(dev, "report must be greater than 1 byte"); + return -1; + } + + device_handle = dev->report_handles[*data]; + if (device_handle < 0) { + register_device_error_format(dev, "unsupported report id: %hhu", *data); + return -1; + } + + length--; + data++; + + if (length > sizeof(ucr.ucr_data)) { + length = sizeof(ucr.ucr_data); + } + + ucr.ucr_report = report; + + res = ioctl(device_handle, USB_GET_REPORT, &ucr); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_REPORT): %s", strerror(errno)); + return -1; + } + + memcpy(data, ucr.ucr_data, length); + + return (int) (length + 1); +} + +int HID_API_EXPORT HID_API_CALL hid_init(void) +{ + /* indicate no error */ + register_global_error(NULL); + + return 0; +} + +int HID_API_EXPORT HID_API_CALL hid_exit(void) +{ + /* Free global error message */ + register_global_error(NULL); + + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) +{ + int res; + int drvctl; + char arr[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + size_t len; + struct hid_enumerate_data hed; + + res = hid_init(); + if (res == -1) + return NULL; + + drvctl = open(DRVCTLDEV, O_RDONLY | O_CLOEXEC); + if (drvctl == -1) { + register_global_error_format("failed to open drvctl: %s", strerror(errno)); + return NULL; + } + + len = 0; + walk_device_tree(drvctl, "", 0, arr, &len, is_usb_controller); + + hed.root = NULL; + hed.end = NULL; + hed.drvctl = drvctl; + hed.vendor_id = vendor_id; + hed.product_id = product_id; + + for (size_t i = 0; i < len; i++) { + char devpath[USB_MAX_DEVNAMELEN]; + int bus; + + strlcpy(devpath, "/dev/", sizeof(devpath)); + strlcat(devpath, arr[i], sizeof(devpath)); + + bus = open(devpath, O_RDONLY | O_CLOEXEC); + if (bus == -1) + continue; + + enumerate_usb_devices(bus, 0, hid_enumerate_callback, &hed); + + close(bus); + } + + close(drvctl); + + return hed.root; +} + +void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs) +{ + while (devs) { + struct hid_device_info *next = devs->next; + free(devs->path); + free(devs->serial_number); + free(devs->manufacturer_string); + free(devs->product_string); + free(devs); + devs = next; + } +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) +{ + struct hid_device_info *devs; + struct hid_device_info *dev; + char path[USB_MAX_DEVNAMELEN]; + + devs = hid_enumerate(vendor_id, product_id); + if (!devs) + return NULL; + + *path = '\0'; + + for (dev = devs; dev; dev = dev->next) { + if (dev->vendor_id != vendor_id) + continue; + + if (dev->product_id != product_id) + continue; + + if (serial_number && wcscmp(dev->serial_number, serial_number)) + continue; + + strlcpy(path, dev->path, sizeof(path)); + + break; + } + + hid_free_enumeration(devs); + + if (*path == '\0') { + register_global_error("Device with requested VID/PID/(SerialNumber) not found"); + return NULL; + } + + return hid_open_path(path); +} + +HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) +{ + int res; + hid_device *dev; + int drvctl; + char arr[HIDAPI_MAX_CHILD_DEVICES][USB_MAX_DEVNAMELEN]; + size_t len; + + res = hid_init(); + if (res == -1) + goto err_0; + + dev = (hid_device *) calloc(1, sizeof(hid_device)); + if (!dev) { + register_global_error("could not allocate hid_device"); + goto err_0; + } + + drvctl = open(DRVCTLDEV, O_RDONLY | O_CLOEXEC); + if (drvctl == -1) { + register_global_error_format("failed to open drvctl: %s", strerror(errno)); + goto err_1; + } + + if (!is_uhid_parent_device(path)) { + register_global_error("not a uhidev device"); + goto err_2; + } + + len = 0; + walk_device_tree(drvctl, path, 0, arr, &len, is_uhid_device); + + dev->poll_handles_length = 0; + memset(dev->poll_handles, 0x00, sizeof(dev->poll_handles)); + memset(dev->report_handles, 0xff, sizeof(dev->report_handles)); + + for (size_t i = 0; i < len; i++) { + const char *child_dev; + char devpath[USB_MAX_DEVNAMELEN]; + int uhid; + int rep_id; + struct pollfd *ph; + + child_dev = arr[i]; + strlcpy(devpath, "/dev/", sizeof(devpath)); + strlcat(devpath, child_dev, sizeof(devpath)); + + uhid = open(devpath, O_RDWR | O_CLOEXEC); + if (uhid == -1) { + register_global_error_format("failed to open %s: %s", child_dev, strerror(errno)); + goto err_3; + } + + res = ioctl(uhid, USB_GET_REPORT_ID, &rep_id); + if (res == -1) { + close(uhid); + register_global_error_format("failed to get report id %s: %s", child_dev, strerror(errno)); + goto err_3; + } + + ph = &dev->poll_handles[dev->poll_handles_length++]; + ph->fd = uhid; + ph->events = POLLIN; + ph->revents = 0; + dev->report_handles[rep_id] = uhid; + dev->device_handle = uhid; + } + + dev->blocking = 1; + dev->last_error_str = NULL; + dev->device_info = NULL; + strlcpy(dev->path, path, sizeof(dev->path)); + + register_global_error(NULL); + return dev; + +err_3: + for (size_t i = 0; i < dev->poll_handles_length; i++) + close(dev->poll_handles[i].fd); +err_2: + close(drvctl); +err_1: + free(dev); +err_0: + return NULL; +} + +int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, data, length, UHID_OUTPUT_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) +{ + int res; + size_t i; + struct pollfd *ph; + ssize_t n; + + res = poll(dev->poll_handles, dev->poll_handles_length, milliseconds); + if (res == -1) { + register_device_error_format(dev, "error while polling: %s", strerror(errno)); + return -1; + } + + if (res == 0) + return 0; + + for (i = 0; i < dev->poll_handles_length; i++) { + ph = &dev->poll_handles[i]; + + if (ph->revents & (POLLERR | POLLHUP | POLLNVAL)) { + register_device_error(dev, "device IO error while polling"); + return -1; + } + + if (ph->revents & POLLIN) + break; + } + + if (i == dev->poll_handles_length) + return 0; + + n = read(ph->fd, data, length); + if (n == -1) { + if (errno == EAGAIN || errno == EINPROGRESS) + n = 0; + else + register_device_error_format(dev, "error while reading: %s", strerror(errno)); + } + + return n; +} + +int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length) +{ + return hid_read_timeout(dev, data, length, (dev->blocking) ? -1 : 0); +} + +int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock) +{ + dev->blocking = !nonblock; + return 0; +} + +int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, data, length, UHID_FEATURE_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) +{ + return get_report(dev, data, length, UHID_FEATURE_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device *dev, const unsigned char *data, size_t length) +{ + return set_report(dev, data, length, UHID_OUTPUT_REPORT); +} + +int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) +{ + return get_report(dev, data, length, UHID_INPUT_REPORT); +} + +void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) +{ + if (!dev) + return; + + /* Free the device error message */ + register_device_error(dev, NULL); + + hid_free_enumeration(dev->device_info); + + for (size_t i = 0; i < dev->poll_handles_length; i++) + close(dev->poll_handles[i].fd); + + free(dev); +} + +int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + struct hid_device_info *hdi; + + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + hdi = hid_get_device_info(dev); + if (!dev) + return -1; + + if (hdi->manufacturer_string) { + wcsncpy(string, hdi->manufacturer_string, maxlen); + string[maxlen - 1] = L'\0'; + } else { + string[0] = L'\0'; + } + + return 0; +} + +int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + struct hid_device_info *hdi; + + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + hdi = hid_get_device_info(dev); + if (!dev) + return -1; + + if (hdi->product_string) { + wcsncpy(string, hdi->product_string, maxlen); + string[maxlen - 1] = L'\0'; + } else { + string[0] = L'\0'; + } + + return 0; +} + +int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) +{ + struct hid_device_info *hdi; + + if (!string || !maxlen) { + register_device_error(dev, "Zero buffer/length"); + return -1; + } + + hdi = hid_get_device_info(dev); + if (!dev) + return -1; + + if (hdi->serial_number) { + wcsncpy(string, hdi->serial_number, maxlen); + string[maxlen - 1] = L'\0'; + } else { + string[0] = L'\0'; + } + + return 0; +} + +struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev) +{ + int res; + struct usb_device_info udi; + struct usb_ctl_report_desc ucrd; + int use_ucrd; + struct hid_device_info *hdi; + + if (dev->device_info) + return dev->device_info; + + res = ioctl(dev->device_handle, USB_GET_DEVICEINFO, &udi); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_DEVICEINFO): %s", strerror(errno)); + return NULL; + } + + use_ucrd = (ioctl(dev->device_handle, USB_GET_REPORT_DESC, &ucrd) != -1); + + hdi = create_device_info(&udi, dev->path, (use_ucrd) ? &ucrd : NULL); + if (!hdi) { + register_device_error(dev, "failed to create device info"); + return NULL; + } + + dev->device_info = hdi; + + return hdi; +} + +int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) +{ + int res; + struct usb_string_desc usd; + usb_string_descriptor_t *str; + iconv_t ic; + const char *src; + size_t srcleft; + char *dst; + size_t dstleft; + size_t ic_res; + + /* First let us get the supported language IDs. */ + usd.usd_string_index = 0; + usd.usd_language_id = 0; + + res = ioctl(dev->device_handle, USB_GET_STRING_DESC, &usd); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_STRING_DESC): %s", strerror(errno)); + return -1; + } + + str = &usd.usd_desc; + + if (str->bLength < 4) { + register_device_error(dev, "failed to get supported language IDs"); + return -1; + } + + /* Now we can get the requested string. */ + usd.usd_string_index = string_index; + usd.usd_language_id = UGETW(str->bString[0]); + + res = ioctl(dev->device_handle, USB_GET_STRING_DESC, &usd); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_STRING_DESC): %s", strerror(errno)); + return -1; + } + + /* Now we need to convert it, using iconv. */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + ic = iconv_open("utf-32le", "utf-16le"); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + ic = iconv_open("utf-32be", "utf-16le"); +#endif + if (ic == (iconv_t) -1) { + register_device_error_format(dev, "iconv_open failed: %s", strerror(errno)); + return -1; + } + + src = (const char *) str->bString; + srcleft = str->bLength - 2; + dst = (char *) string; + dstleft = sizeof(wchar_t[maxlen]); + + ic_res = iconv(ic, &src, &srcleft, &dst, &dstleft); + iconv_close(ic); + if (ic_res == (size_t) -1) { + register_device_error_format(dev, "iconv failed: %s", strerror(errno)); + return -1; + } + + /* Write the terminating NULL. */ + string[maxlen - 1] = L'\0'; + if (dstleft >= sizeof(wchar_t)) + *((wchar_t *) dst) = L'\0'; + + return 0; +} + +int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) +{ + int res; + struct usb_ctl_report_desc ucrd; + + res = ioctl(dev->device_handle, USB_GET_REPORT_DESC, &ucrd); + if (res == -1) { + register_device_error_format(dev, "ioctl (USB_GET_REPORT_DESC): %s", strerror(errno)); + return -1; + } + + if ((size_t) ucrd.ucrd_size < buf_size) + buf_size = (size_t) ucrd.ucrd_size; + + memcpy(buf, ucrd.ucrd_data, buf_size); + + return (int) buf_size; +} + +HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev) +{ + if (dev) { + if (dev->last_error_str == NULL) + return L"Success"; + return dev->last_error_str; + } + + if (last_global_error_str == NULL) + return L"Success"; + return last_global_error_str; +} + +HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) +{ + static const struct hid_api_version api_version = { + .major = HID_API_VERSION_MAJOR, + .minor = HID_API_VERSION_MINOR, + .patch = HID_API_VERSION_PATCH + }; + + return &api_version; +} + +HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) +{ + return HID_API_VERSION_STR; +} diff --git a/pc/hidapi-netbsd.pc.in b/pc/hidapi-netbsd.pc.in new file mode 100644 index 000000000..fcb5ca215 --- /dev/null +++ b/pc/hidapi-netbsd.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: hidapi-netbsd +Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the netbsd implementation. +URL: https://github.com/libusb/hidapi +Version: @VERSION@ +Libs: -L${libdir} -lhidapi-netbsd +Cflags: -I${includedir}/hidapi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 504b20548..e663c3fd6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ endif() set(VERSION "${CMAKE_MATCH_1}") string(STRIP "${CMAKE_MATCH_2}" VERSION_SUFFIX) -# compatinility with find_package() vs add_subdirectory +# compatibility with find_package() vs add_subdirectory set(hidapi_VERSION "${VERSION}" PARENT_SCOPE) # @@ -26,6 +26,9 @@ 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() @@ -65,24 +68,34 @@ function(hidapi_configure_pc PC_IN_FILE) 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/") + if(HIDAPI_INSTALL_TARGETS) + install(FILES "${PC_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") + endif() endfunction() # The library +if(HIDAPI_INSTALL_TARGETS) + include(GNUInstallDirs) +endif() + add_library(hidapi_include INTERFACE) target_include_directories(hidapi_include INTERFACE "$" - "$" ) +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 + "$" + ) +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) - include(GNUInstallDirs) install(TARGETS hidapi_include EXPORT hidapi) endif() @@ -128,6 +141,18 @@ else() set(HIDAPI_NEED_EXPORT_LIBUDEV TRUE) endif() endif() + elseif(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + if(NOT DEFINED HIDAPI_WITH_NETBSD) + set(HIDAPI_WITH_NETBSD ON) + endif() + if(HIDAPI_WITH_NETBSD) + add_subdirectory("${PROJECT_ROOT}/netbsd" netbsd) + list(APPEND EXPORT_COMPONENTS netbsd) + set(EXPORT_ALIAS netbsd) + if(NOT BUILD_SHARED_LIBS) + set(HIDAPI_NEED_EXPORT_THREADS TRUE) + endif() + endif() else() set(HIDAPI_WITH_LIBUSB ON) endif() @@ -148,9 +173,6 @@ else() if(NOT TARGET usb-1.0) set(HIDAPI_NEED_EXPORT_LIBUSB TRUE) endif() - if(NOT HIDAPI_NO_ICONV AND NOT ANDROID AND NOT CMAKE_VERSION VERSION_LESS 3.11) - set(HIDAPI_NEED_EXPORT_ICONV 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") @@ -163,7 +185,7 @@ 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}/libhidapi-version.cmake" + 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" @@ -177,7 +199,7 @@ if(HIDAPI_INSTALL_TARGETS) FILE "libhidapi.cmake" ) install(FILES - "${EXPORT_DENERATED_LOCATION}/libhidapi-version.cmake" + "${EXPORT_DENERATED_LOCATION}/hidapi-config-version.cmake" "${EXPORT_DENERATED_LOCATION}/hidapi-config.cmake" DESTINATION "${EXPORT_DESTINATION}" ) diff --git a/subprojects/README.md b/subprojects/README.md new file mode 100644 index 000000000..8ba8f60cb --- /dev/null +++ b/subprojects/README.md @@ -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. \ No newline at end of file diff --git a/subprojects/hidapi_build_cmake/CMakeLists.txt b/subprojects/hidapi_build_cmake/CMakeLists.txt new file mode 100644 index 000000000..4586ce6a6 --- /dev/null +++ b/subprojects/hidapi_build_cmake/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.1.3...3.25 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) diff --git a/udev/69-hid.rules b/udev/69-hid.rules index a27113ca8..02d6a2cf0 100644 --- a/udev/69-hid.rules +++ b/udev/69-hid.rules @@ -17,7 +17,7 @@ KERNEL=="hidraw*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", TAG+="uacc # 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. +# NOTE: these rules must have priority 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. diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 74839fb51..c8228bc84 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -3,6 +3,8 @@ 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 @@ -20,6 +22,14 @@ 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" @@ -43,3 +53,11 @@ if(HIDAPI_INSTALL_TARGETS) 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() diff --git a/windows/hid.c b/windows/hid.c index da47ff6e6..35c2de04e 100644 --- a/windows/hid.c +++ b/windows/hid.c @@ -30,7 +30,7 @@ extern "C" { #endif -#include "hidapi.h" +#include "hidapi_winapi.h" #include @@ -52,7 +52,6 @@ typedef LONG NTSTATUS; /*#define HIDAPI_USE_DDK*/ -#include #include "hidapi_cfgmgr32.h" #include "hidapi_hidclass.h" #include "hidapi_hidsdi.h" @@ -70,6 +69,15 @@ typedef LONG NTSTATUS; /* BLUETOOTH_DEVICE_NAME_SIZE from bluetoothapis.h is 256 */ #define MAX_STRING_WCHARS 256 +/* For certain USB devices, using a buffer larger or equal to 127 wchars results + in successful completion of HID API functions, but a broken string is stored + in the output buffer. This behaviour persists even if HID API is bypassed and + HID IOCTLs are passed to the HID driver directly. Therefore, for USB devices, + the buffer MUST NOT exceed 126 WCHARs. +*/ + +#define MAX_STRING_WCHARS_USB 126 + static struct hid_api_version api_version = { .major = HID_API_VERSION_MAJOR, .minor = HID_API_VERSION_MINOR, @@ -89,6 +97,7 @@ static HidD_GetManufacturerString_ HidD_GetManufacturerString; static HidD_GetProductString_ HidD_GetProductString; static HidD_SetFeature_ HidD_SetFeature; static HidD_GetFeature_ HidD_GetFeature; +static HidD_SetOutputReport_ HidD_SetOutputReport; static HidD_GetInputReport_ HidD_GetInputReport; static HidD_GetIndexedString_ HidD_GetIndexedString; static HidD_GetPreparsedData_ HidD_GetPreparsedData; @@ -142,6 +151,7 @@ static int lookup_functions() RESOLVE(hid_lib_handle, HidD_GetProductString); RESOLVE(hid_lib_handle, HidD_SetFeature); RESOLVE(hid_lib_handle, HidD_GetFeature); + RESOLVE(hid_lib_handle, HidD_SetOutputReport); RESOLVE(hid_lib_handle, HidD_GetInputReport); RESOLVE(hid_lib_handle, HidD_GetIndexedString); RESOLVE(hid_lib_handle, HidD_GetPreparsedData); @@ -189,6 +199,11 @@ struct hid_device_ { static hid_device *new_hid_device() { hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device)); + + if (dev == NULL) { + return NULL; + } + dev->device_handle = INVALID_HANDLE_VALUE; dev->blocking = TRUE; dev->output_report_length = 0; @@ -202,7 +217,7 @@ static hid_device *new_hid_device() memset(&dev->ol, 0, sizeof(dev->ol)); dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); memset(&dev->write_ol, 0, sizeof(dev->write_ol)); - dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL); + dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL); dev->device_info = NULL; return dev; @@ -224,9 +239,6 @@ static void free_hid_device(hid_device *dev) static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR *op) { - if (!error_buffer) - return; - free(*error_buffer); *error_buffer = NULL; @@ -263,7 +275,7 @@ static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR if (!msg) return; - int printf_written = swprintf(msg, msg_len + 1, L"%.*ls: (0x%08X) %.*ls", op_len, op, error_code, system_err_len, system_err_buf); + int printf_written = swprintf(msg, msg_len + 1, L"%.*ls: (0x%08X) %.*ls", (int)op_len, op, error_code, (int)system_err_len, system_err_buf); if (printf_written < 0) { @@ -281,19 +293,17 @@ static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR } } -static void register_winapi_error(hid_device *dev, const WCHAR *op) -{ - if (!dev) - return; - - register_winapi_error_to_buffer(&dev->last_error_str, op); -} +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Warray-bounds" +#endif +/* A bug in GCC/mingw gives: + * error: array subscript 0 is outside array bounds of 'wchar_t *[0]' {aka 'short unsigned int *[]'} [-Werror=array-bounds] + * | free(*error_buffer); + * Which doesn't make sense in this context. */ static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR *string_error) { - if (!error_buffer) - return; - free(*error_buffer); *error_buffer = NULL; @@ -302,14 +312,32 @@ static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR } } -static void register_string_error(hid_device *dev, const WCHAR *string_error) +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + +static void register_winapi_error(hid_device *dev, const WCHAR *op) { - if (!dev) - return; + register_winapi_error_to_buffer(&dev->last_error_str, op); +} +static void register_string_error(hid_device *dev, const WCHAR *string_error) +{ register_string_error_to_buffer(&dev->last_error_str, string_error); } +static wchar_t *last_global_error_str = NULL; + +static void register_global_winapi_error(const WCHAR *op) +{ + register_winapi_error_to_buffer(&last_global_error_str, op); +} + +static void register_global_error(const WCHAR *string_error) +{ + register_string_error_to_buffer(&last_global_error_str, string_error); +} + static HANDLE open_device(const wchar_t *path, BOOL open_rw) { HANDLE handle; @@ -327,21 +355,23 @@ static HANDLE open_device(const wchar_t *path, BOOL open_rw) return handle; } -HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version() +HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void) { return &api_version; } -HID_API_EXPORT const char* HID_API_CALL hid_version_str() +HID_API_EXPORT const char* HID_API_CALL hid_version_str(void) { return HID_API_VERSION_STR; } int HID_API_EXPORT hid_init(void) { + register_global_error(NULL); #ifndef HIDAPI_USE_DDK if (!hidapi_initialized) { if (lookup_functions() < 0) { + register_global_winapi_error(L"resolve DLL functions"); return -1; } hidapi_initialized = TRUE; @@ -356,6 +386,7 @@ int HID_API_EXPORT hid_exit(void) free_library_handles(); hidapi_initialized = FALSE; #endif + register_global_error(NULL); return 0; } @@ -401,91 +432,201 @@ static void* hid_internal_get_device_interface_property(const wchar_t* interface return property_value; } -static void hid_internal_get_ble_info(struct hid_device_info* dev, DEVINST dev_node) +static void hid_internal_towupper(wchar_t* string) { - wchar_t *manufacturer_string, *serial_number, *product_string; - /* Manufacturer String */ - manufacturer_string = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_Manufacturer, DEVPROP_TYPE_STRING); - if (manufacturer_string) { - free(dev->manufacturer_string); - dev->manufacturer_string = manufacturer_string; - } - - /* Serial Number String (MAC Address) */ - serial_number = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_DeviceAddress, DEVPROP_TYPE_STRING); - if (serial_number) { - free(dev->serial_number); - dev->serial_number = serial_number; - } - - /* Get devnode grandparent to reach out Bluetooth LE device node */ - if (CM_Get_Parent(&dev_node, dev_node, 0) != CR_SUCCESS) - return; - - /* Product String */ - product_string = hid_internal_get_devnode_property(dev_node, &DEVPKEY_NAME, DEVPROP_TYPE_STRING); - if (product_string) { - free(dev->product_string); - dev->product_string = product_string; - } + for (wchar_t* p = string; *p; ++p) *p = towupper(*p); } -/* USB Device Interface Number. - It can be parsed out of the Hardware ID if a USB device is has multiple interfaces (composite device). - See https://docs.microsoft.com/windows-hardware/drivers/hid/hidclass-hardware-ids-for-top-level-collections - and https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers - - hardware_id is always expected to be uppercase. -*/ -static int hid_internal_get_interface_number(const wchar_t* hardware_id) +static int hid_internal_extract_int_token_value(wchar_t* string, const wchar_t* token) { - int interface_number; - wchar_t *startptr, *endptr; - const wchar_t *interface_token = L"&MI_"; + int token_value; + wchar_t* startptr, * endptr; - startptr = wcsstr(hardware_id, interface_token); + startptr = wcsstr(string, token); if (!startptr) return -1; - startptr += wcslen(interface_token); - interface_number = wcstol(startptr, &endptr, 16); + startptr += wcslen(token); + token_value = wcstol(startptr, &endptr, 16); if (endptr == startptr) return -1; - return interface_number; + return token_value; } -static void hid_internal_get_info(const wchar_t* interface_path, struct hid_device_info* dev) +static void hid_internal_get_usb_info(struct hid_device_info* dev, DEVINST dev_node) { - wchar_t *device_id = NULL, *compatible_ids = NULL, *hardware_ids = NULL; - CONFIGRET cr; - DEVINST dev_node; + wchar_t *device_id = NULL, *hardware_ids = NULL; - /* Get the device id from interface path */ - device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); + device_id = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); if (!device_id) goto end; - /* Open devnode from device id */ - cr = CM_Locate_DevNodeW(&dev_node, (DEVINSTID_W)device_id, CM_LOCATE_DEVNODE_NORMAL); - if (cr != CR_SUCCESS) - goto end; + /* Normalize to upper case */ + hid_internal_towupper(device_id); + + /* Check for Xbox Common Controller class (XUSB) device. + https://docs.microsoft.com/windows/win32/xinput/directinput-and-xusb-devices + https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput + */ + if (hid_internal_extract_int_token_value(device_id, L"IG_") != -1) { + /* Get devnode parent to reach out USB device. */ + if (CM_Get_Parent(&dev_node, dev_node, 0) != CR_SUCCESS) + goto end; + } /* Get the hardware ids from devnode */ hardware_ids = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_HardwareIds, DEVPROP_TYPE_STRING_LIST); if (!hardware_ids) goto end; - /* Search for interface number in hardware ids */ + /* Get additional information from USB device's Hardware ID + https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers + https://docs.microsoft.com/windows-hardware/drivers/usbcon/enumeration-of-interfaces-not-grouped-in-collections + */ for (wchar_t* hardware_id = hardware_ids; *hardware_id; hardware_id += wcslen(hardware_id) + 1) { /* Normalize to upper case */ - for (wchar_t* p = hardware_id; *p; ++p) *p = towupper(*p); + hid_internal_towupper(hardware_id); - dev->interface_number = hid_internal_get_interface_number(hardware_id); + if (dev->release_number == 0) { + /* USB_DEVICE_DESCRIPTOR.bcdDevice value. */ + int release_number = hid_internal_extract_int_token_value(hardware_id, L"REV_"); + if (release_number != -1) { + dev->release_number = (unsigned short)release_number; + } + } - if (dev->interface_number != -1) - break; + if (dev->interface_number == -1) { + /* USB_INTERFACE_DESCRIPTOR.bInterfaceNumber value. */ + int interface_number = hid_internal_extract_int_token_value(hardware_id, L"MI_"); + if (interface_number != -1) { + dev->interface_number = interface_number; + } + } + } + + /* Try to get USB device manufacturer string if not provided by HidD_GetManufacturerString. */ + if (wcslen(dev->manufacturer_string) == 0) { + wchar_t* manufacturer_string = hid_internal_get_devnode_property(dev_node, &DEVPKEY_Device_Manufacturer, DEVPROP_TYPE_STRING); + if (manufacturer_string) { + free(dev->manufacturer_string); + dev->manufacturer_string = manufacturer_string; + } + } + + /* Try to get USB device serial number if not provided by HidD_GetSerialNumberString. */ + if (wcslen(dev->serial_number) == 0) { + DEVINST usb_dev_node = dev_node; + if (dev->interface_number != -1) { + /* Get devnode parent to reach out composite parent USB device. + https://docs.microsoft.com/windows-hardware/drivers/usbcon/enumeration-of-the-composite-parent-device + */ + if (CM_Get_Parent(&usb_dev_node, dev_node, 0) != CR_SUCCESS) + goto end; + } + + /* Get the device id of the USB device. */ + free(device_id); + device_id = hid_internal_get_devnode_property(usb_dev_node, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); + if (!device_id) + goto end; + + /* Extract substring after last '\\' of Instance ID. + For USB devices it may contain device's serial number. + https://docs.microsoft.com/windows-hardware/drivers/install/instance-ids + */ + for (wchar_t *ptr = device_id + wcslen(device_id); ptr > device_id; --ptr) { + /* Instance ID is unique only within the scope of the bus. + For USB devices it means that serial number is not available. Skip. */ + if (*ptr == L'&') + break; + + if (*ptr == L'\\') { + free(dev->serial_number); + dev->serial_number = _wcsdup(ptr + 1); + break; + } + } + } + + /* If we can't get the interface number, it means that there is only one interface. */ + if (dev->interface_number == -1) + dev->interface_number = 0; + +end: + free(device_id); + free(hardware_ids); +} + +/* HidD_GetProductString/HidD_GetManufacturerString/HidD_GetSerialNumberString is not working for BLE HID devices + Request this info via dev node properties instead. + https://docs.microsoft.com/answers/questions/401236/hidd-getproductstring-with-ble-hid-device.html +*/ +static void hid_internal_get_ble_info(struct hid_device_info* dev, DEVINST dev_node) +{ + if (wcslen(dev->manufacturer_string) == 0) { + /* Manufacturer Name String (UUID: 0x2A29) */ + wchar_t* manufacturer_string = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_Manufacturer, DEVPROP_TYPE_STRING); + if (manufacturer_string) { + free(dev->manufacturer_string); + dev->manufacturer_string = manufacturer_string; + } + } + + if (wcslen(dev->serial_number) == 0) { + /* Serial Number String (UUID: 0x2A25) */ + wchar_t* serial_number = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_DeviceAddress, DEVPROP_TYPE_STRING); + if (serial_number) { + free(dev->serial_number); + dev->serial_number = serial_number; + } + } + + if (wcslen(dev->product_string) == 0) { + /* Model Number String (UUID: 0x2A24) */ + wchar_t* product_string = hid_internal_get_devnode_property(dev_node, (const DEVPROPKEY*)&PKEY_DeviceInterface_Bluetooth_ModelNumber, DEVPROP_TYPE_STRING); + if (!product_string) { + DEVINST parent_dev_node = 0; + /* Fallback: Get devnode grandparent to reach out Bluetooth LE device node */ + if (CM_Get_Parent(&parent_dev_node, dev_node, 0) == CR_SUCCESS) { + /* Device Name (UUID: 0x2A00) */ + product_string = hid_internal_get_devnode_property(parent_dev_node, &DEVPKEY_NAME, DEVPROP_TYPE_STRING); + } + } + + if (product_string) { + free(dev->product_string); + dev->product_string = product_string; + } } +} + +/* Unfortunately, HID_API_BUS_xxx constants alone aren't enough to distinguish between BLUETOOTH and BLE */ + +#define HID_API_BUS_FLAG_BLE 0x01 + +typedef struct hid_internal_detect_bus_type_result_ { + DEVINST dev_node; + hid_bus_type bus_type; + unsigned int bus_flags; +} hid_internal_detect_bus_type_result; + +static hid_internal_detect_bus_type_result hid_internal_detect_bus_type(const wchar_t* interface_path) +{ + wchar_t *device_id = NULL, *compatible_ids = NULL; + CONFIGRET cr; + DEVINST dev_node; + hid_internal_detect_bus_type_result result = { 0 }; + + /* Get the device id from interface path */ + device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); + if (!device_id) + goto end; + + /* Open devnode from device id */ + cr = CM_Locate_DevNodeW(&dev_node, (DEVINSTID_W)device_id, CM_LOCATE_DEVNODE_NORMAL); + if (cr != CR_SUCCESS) + goto end; /* Get devnode parent */ cr = CM_Get_Parent(&dev_node, dev_node, 0); @@ -500,21 +641,51 @@ static void hid_internal_get_info(const wchar_t* interface_path, struct hid_devi /* Now we can parse parent's compatible IDs to find out the device bus type */ for (wchar_t* compatible_id = compatible_ids; *compatible_id; compatible_id += wcslen(compatible_id) + 1) { /* Normalize to upper case */ - for (wchar_t* p = compatible_id; *p; ++p) *p = towupper(*p); + hid_internal_towupper(compatible_id); + + /* USB devices + https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support + https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers */ + if (wcsstr(compatible_id, L"USB") != NULL) { + result.bus_type = HID_API_BUS_USB; + break; + } + + /* Bluetooth devices + https://docs.microsoft.com/windows-hardware/drivers/bluetooth/installing-a-bluetooth-device */ + if (wcsstr(compatible_id, L"BTHENUM") != NULL) { + result.bus_type = HID_API_BUS_BLUETOOTH; + break; + } /* Bluetooth LE devices */ if (wcsstr(compatible_id, L"BTHLEDEVICE") != NULL) { - /* HidD_GetProductString/HidD_GetManufacturerString/HidD_GetSerialNumberString is not working for BLE HID devices - Request this info via dev node properties instead. - https://docs.microsoft.com/answers/questions/401236/hidd-getproductstring-with-ble-hid-device.html */ - hid_internal_get_ble_info(dev, dev_node); + result.bus_type = HID_API_BUS_BLUETOOTH; + result.bus_flags |= HID_API_BUS_FLAG_BLE; + break; + } + + /* I2C devices + https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-support-and-power-management */ + if (wcsstr(compatible_id, L"PNP0C50") != NULL) { + result.bus_type = HID_API_BUS_I2C; + break; + } + + /* SPI devices + https://docs.microsoft.com/windows-hardware/drivers/hid/plug-and-play-for-spi */ + if (wcsstr(compatible_id, L"PNP0C51") != NULL) { + result.bus_type = HID_API_BUS_SPI; break; } } + + result.dev_node = dev_node; + end: free(device_id); - free(hardware_ids); free(compatible_ids); + return result; } static char *hid_internal_UTF16toUTF8(const wchar_t *src) @@ -523,6 +694,9 @@ static char *hid_internal_UTF16toUTF8(const wchar_t *src) int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, NULL, 0, NULL, NULL); if (len) { dst = (char*)calloc(len, sizeof(char)); + if (dst == NULL) { + return NULL; + } WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, src, -1, dst, len, NULL, NULL); } @@ -535,6 +709,9 @@ static wchar_t *hid_internal_UTF8toUTF16(const char *src) int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, NULL, 0); if (len) { dst = (wchar_t*)calloc(len, sizeof(wchar_t)); + if (dst == NULL) { + return NULL; + } MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, src, -1, dst, len); } @@ -547,14 +724,22 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path, HIDD_ATTRIBUTES attrib; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; - wchar_t string[MAX_STRING_WCHARS]; + wchar_t string[MAX_STRING_WCHARS + 1]; + ULONG len; + ULONG size; + hid_internal_detect_bus_type_result detect_bus_type_result; /* Create the record. */ dev = (struct hid_device_info*)calloc(1, sizeof(struct hid_device_info)); + if (dev == NULL) { + return NULL; + } + /* Fill out the record */ dev->next = NULL; dev->path = hid_internal_UTF16toUTF8(path); + dev->interface_number = -1; attrib.Size = sizeof(HIDD_ATTRIBUTES); if (HidD_GetAttributes(handle, &attrib)) { @@ -576,25 +761,46 @@ static struct hid_device_info *hid_internal_get_device_info(const wchar_t *path, HidD_FreePreparsedData(pp_data); } + /* detect bus type before reading string descriptors */ + detect_bus_type_result = hid_internal_detect_bus_type(path); + dev->bus_type = detect_bus_type_result.bus_type; + + len = dev->bus_type == HID_API_BUS_USB ? MAX_STRING_WCHARS_USB : MAX_STRING_WCHARS; + string[len] = L'\0'; + size = len * sizeof(wchar_t); + /* Serial Number */ string[0] = L'\0'; - HidD_GetSerialNumberString(handle, string, sizeof(string)); - string[MAX_STRING_WCHARS - 1] = L'\0'; + HidD_GetSerialNumberString(handle, string, size); dev->serial_number = _wcsdup(string); /* Manufacturer String */ string[0] = L'\0'; - HidD_GetManufacturerString(handle, string, sizeof(string)); - string[MAX_STRING_WCHARS - 1] = L'\0'; + HidD_GetManufacturerString(handle, string, size); dev->manufacturer_string = _wcsdup(string); /* Product String */ string[0] = L'\0'; - HidD_GetProductString(handle, string, sizeof(string)); - string[MAX_STRING_WCHARS - 1] = L'\0'; + HidD_GetProductString(handle, string, size); dev->product_string = _wcsdup(string); - hid_internal_get_info(path, dev); + /* now, the portion that depends on string descriptors */ + switch (dev->bus_type) { + case HID_API_BUS_USB: + hid_internal_get_usb_info(dev, detect_bus_type_result.dev_node); + break; + + case HID_API_BUS_BLUETOOTH: + if (detect_bus_type_result.bus_flags & HID_API_BUS_FLAG_BLE) + hid_internal_get_ble_info(dev, detect_bus_type_result.dev_node); + break; + + case HID_API_BUS_UNKNOWN: + case HID_API_BUS_SPI: + case HID_API_BUS_I2C: + /* shut down -Wswitch */ + break; + } return dev; } @@ -608,8 +814,10 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor wchar_t* device_interface_list = NULL; DWORD len; - if (hid_init() < 0) + if (hid_init() < 0) { + /* register_global_error: global error is reset by hid_init */ return NULL; + } /* Retrieve HID Interface Class GUID https://docs.microsoft.com/windows-hardware/drivers/install/guid-devinterface-hid */ @@ -621,6 +829,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor do { cr = CM_Get_Device_Interface_List_SizeW(&len, &interface_class_guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (cr != CR_SUCCESS) { + register_global_error(L"Failed to get size of HID device interface list"); break; } @@ -630,9 +839,13 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor device_interface_list = (wchar_t*)calloc(len, sizeof(wchar_t)); if (device_interface_list == NULL) { + register_global_error(L"Failed to allocate memory for HID device interface list"); return NULL; } cr = CM_Get_Device_Interface_ListW(&interface_class_guid, NULL, device_interface_list, len, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (cr != CR_SUCCESS && cr != CR_BUFFER_SMALL) { + register_global_error(L"Failed to get HID device interface list"); + } } while (cr == CR_BUFFER_SMALL); if (cr != CR_SUCCESS) { @@ -684,6 +897,14 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor CloseHandle(device_handle); } + if (root == NULL) { + if (vendor_id == 0 && product_id == 0) { + register_global_error(L"No HID devices found in the system."); + } else { + register_global_error(L"No HID devices with requested VID/PID found in the system."); + } + } + end_of_function: free(device_interface_list); @@ -712,8 +933,10 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi const char *path_to_open = NULL; hid_device *handle = NULL; + /* register_global_error: global error is reset by hid_enumerate/hid_init */ devs = hid_enumerate(vendor_id, product_id); if (!devs) { + /* register_global_error: global error is already set by hid_enumerate */ return NULL; } @@ -738,6 +961,8 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi if (path_to_open) { /* Open the device */ handle = hid_open_path(path_to_open); + } else { + register_global_error(L"Device with requested VID/PID/(SerialNumber) not found"); } hid_free_enumeration(devs); @@ -753,12 +978,16 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; - if (hid_init() < 0) + if (hid_init() < 0) { + /* register_global_error: global error is reset by hid_init */ goto end_of_function; + } interface_path = hid_internal_UTF8toUTF16(path); - if (!interface_path) + if (!interface_path) { + register_global_error(L"Path conversion failure"); goto end_of_function; + } /* Open a handle to the device */ device_handle = open_device(interface_path, TRUE); @@ -773,23 +1002,36 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path) device_handle = open_device(interface_path, FALSE); /* Check the validity of the limited device_handle. */ - if (device_handle == INVALID_HANDLE_VALUE) + if (device_handle == INVALID_HANDLE_VALUE) { + register_global_winapi_error(L"open_device"); goto end_of_function; + } } /* Set the Input Report buffer size to 64 reports. */ - if (!HidD_SetNumInputBuffers(device_handle, 64)) + if (!HidD_SetNumInputBuffers(device_handle, 64)) { + register_global_winapi_error(L"set input buffers"); goto end_of_function; + } /* Get the Input Report length for the device. */ - if (!HidD_GetPreparsedData(device_handle, &pp_data)) + if (!HidD_GetPreparsedData(device_handle, &pp_data)) { + register_global_winapi_error(L"get preparsed data"); goto end_of_function; + } - if (HidP_GetCaps(pp_data, &caps) != HIDP_STATUS_SUCCESS) + if (HidP_GetCaps(pp_data, &caps) != HIDP_STATUS_SUCCESS) { + register_global_error(L"HidP_GetCaps"); goto end_of_function; + } dev = new_hid_device(); + if (dev == NULL) { + register_global_error(L"hid_device allocation error"); + goto end_of_function; + } + dev->device_handle = device_handle; device_handle = INVALID_HANDLE_VALUE; @@ -819,11 +1061,13 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * unsigned char *buf; - if (!data || (length==0)) { + if (!data || !length) { register_string_error(dev, L"Zero buffer/length"); return function_result; } + register_string_error(dev, NULL); + /* Make sure the right number of bytes are passed to WriteFile. Windows expects the number of bytes which are in the _longest_ report (plus one for the report number) bytes even if the data is a report @@ -887,6 +1131,13 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char BOOL res = FALSE; BOOL overlapped = FALSE; + if (!data || !length) { + register_string_error(dev, L"Zero buffer/length"); + return -1; + } + + register_string_error(dev, NULL); + /* Copy the handle for convenience. */ HANDLE ev = dev->ol.hEvent; @@ -914,20 +1165,19 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char } if (overlapped) { - if (milliseconds >= 0) { - /* See if there is any data yet. */ - res = WaitForSingleObject(ev, milliseconds); - if (res != WAIT_OBJECT_0) { - /* There was no data this time. Return zero bytes available, - but leave the Overlapped I/O running. */ - return 0; - } + /* See if there is any data yet. */ + res = WaitForSingleObject(ev, milliseconds >= 0 ? (DWORD)milliseconds : INFINITE); + if (res != WAIT_OBJECT_0) { + /* There was no data this time. Return zero bytes available, + but leave the Overlapped I/O running. */ + return 0; } - /* Either WaitForSingleObject() told us that ReadFile has completed, or - we are in non-blocking mode. Get the number of bytes read. The actual - data has been copied to the data[] array which was passed to ReadFile(). */ - res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); + /* Get the number of bytes read. The actual data has been copied to the data[] + array which was passed to ReadFile(). We must not wait here because we've + already waited on our event above, and since it's auto-reset, it will have + been reset back to unsignalled by now. */ + res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, FALSE/*don't wait now - already did on the prev step*/); } /* Set pending back to false, even if GetOverlappedResult() returned error. */ dev->read_pending = FALSE; @@ -977,6 +1227,13 @@ int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const u unsigned char *buf; size_t length_to_send; + if (!data || !length) { + register_string_error(dev, L"Zero buffer/length"); + return -1; + } + + register_string_error(dev, NULL); + /* Windows expects at least caps.FeatureReportByteLength bytes passed to HidD_SetFeature(), even if the report is shorter. Any less sent and the function fails with error ERROR_INVALID_PARAMETER set. Any more @@ -1012,6 +1269,13 @@ static int hid_get_report(hid_device *dev, DWORD report_type, unsigned char *dat OVERLAPPED ol; memset(&ol, 0, sizeof(ol)); + if (!data || !length) { + register_string_error(dev, L"Zero buffer/length"); + return -1; + } + + register_string_error(dev, NULL); + res = DeviceIoControl(dev->device_handle, report_type, data, (DWORD) length, @@ -1051,6 +1315,45 @@ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned return hid_get_report(dev, IOCTL_HID_GET_FEATURE, data, length); } +int HID_API_EXPORT HID_API_CALL hid_send_output_report(hid_device* dev, const unsigned char* data, size_t length) +{ + BOOL res = FALSE; + unsigned char *buf; + size_t length_to_send; + + if (!data || !length) { + register_string_error(dev, L"Zero buffer/length"); + return -1; + } + + register_string_error(dev, NULL); + + /* Windows expects at least caps.OutputeportByteLength bytes passed + to HidD_SetOutputReport(), even if the report is shorter. Any less sent and + the function fails with error ERROR_INVALID_PARAMETER set. Any more + and HidD_SetOutputReport() silently truncates the data sent in the report + to caps.OutputReportByteLength. */ + if (length >= dev->output_report_length) { + buf = (unsigned char *) data; + length_to_send = length; + } else { + if (dev->write_buf == NULL) + dev->write_buf = (unsigned char *) malloc(dev->output_report_length); + buf = dev->write_buf; + memcpy(buf, data, length); + memset(buf + length, 0, dev->output_report_length - length); + length_to_send = dev->output_report_length; + } + + res = HidD_SetOutputReport(dev->device_handle, (PVOID)buf, (DWORD) length_to_send); + if (!res) { + register_string_error(dev, L"HidD_SetOutputReport"); + return -1; + } + + return (int) length; +} + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) { /* We could use HidD_GetInputReport() instead, but it doesn't give us an actual length, unfortunately */ @@ -1068,76 +1371,91 @@ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev) int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { - if (!dev->device_info) - { - register_string_error(dev, L"NULL device/info"); + if (!string || !maxlen) { + register_string_error(dev, L"Zero buffer/length"); return -1; } - if (!string || !maxlen) - { - register_string_error(dev, L"Zero buffer/length"); + if (!dev->device_info) { + register_string_error(dev, L"NULL device info"); return -1; } wcsncpy(string, dev->device_info->manufacturer_string, maxlen); string[maxlen - 1] = L'\0'; + register_string_error(dev, NULL); + return 0; } int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { - if (!dev->device_info) - { - register_string_error(dev, L"NULL device/info"); + if (!string || !maxlen) { + register_string_error(dev, L"Zero buffer/length"); return -1; } - if (!string || !maxlen) - { - register_string_error(dev, L"Zero buffer/length"); + if (!dev->device_info) { + register_string_error(dev, L"NULL device info"); return -1; } - wcsncpy(string, dev->device_info->product_string, maxlen); string[maxlen - 1] = L'\0'; + register_string_error(dev, NULL); + return 0; } int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { - if (!dev->device_info) - { - register_string_error(dev, L"NULL device/info"); + if (!string || !maxlen) { + register_string_error(dev, L"Zero buffer/length"); return -1; } - if (!string || !maxlen) - { - register_string_error(dev, L"Zero buffer/length"); + if (!dev->device_info) { + register_string_error(dev, L"NULL device info"); return -1; } - wcsncpy(string, dev->device_info->serial_number, maxlen); string[maxlen - 1] = L'\0'; + register_string_error(dev, NULL); + return 0; } +HID_API_EXPORT struct hid_device_info * HID_API_CALL hid_get_device_info(hid_device *dev) { + if (!dev->device_info) + { + register_string_error(dev, L"NULL device info"); + return NULL; + } + + return dev->device_info; +} + int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { BOOL res; - res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * (DWORD) MIN(maxlen, MAX_STRING_WCHARS)); + if (dev->device_info && dev->device_info->bus_type == HID_API_BUS_USB && maxlen > MAX_STRING_WCHARS_USB) { + string[MAX_STRING_WCHARS_USB] = L'\0'; + maxlen = MAX_STRING_WCHARS_USB; + } + + res = HidD_GetIndexedString(dev->device_handle, string_index, string, (ULONG)maxlen * sizeof(wchar_t)); if (!res) { register_winapi_error(dev, L"HidD_GetIndexedString"); return -1; } + register_string_error(dev, NULL); + return 0; } @@ -1149,31 +1467,29 @@ int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *conta DEVPROPTYPE property_type; ULONG len; - if (!container_id) - { + if (!container_id) { register_string_error(dev, L"Invalid Container ID"); return -1; } + register_string_error(dev, NULL); + interface_path = hid_internal_UTF8toUTF16(dev->device_info->path); - if (!interface_path) - { + if (!interface_path) { register_string_error(dev, L"Path conversion failure"); goto end; } /* Get the device id from interface path */ device_id = hid_internal_get_device_interface_property(interface_path, &DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING); - if (!device_id) - { + if (!device_id) { register_string_error(dev, L"Failed to get device interface property InstanceId"); goto end; } /* Open devnode from device id */ cr = CM_Locate_DevNodeW(&dev_node, (DEVINSTID_W)device_id, CM_LOCATE_DEVNODE_NORMAL); - if (cr != CR_SUCCESS) - { + if (cr != CR_SUCCESS) { register_string_error(dev, L"Failed to locate device node"); goto end; } @@ -1195,6 +1511,22 @@ int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *conta } +int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size) +{ + PHIDP_PREPARSED_DATA pp_data = NULL; + + if (!HidD_GetPreparsedData(dev->device_handle, &pp_data) || pp_data == NULL) { + register_string_error(dev, L"HidD_GetPreparsedData"); + return -1; + } + + int res = hid_winapi_descriptor_reconstruct_pp_data(pp_data, buf, buf_size); + + HidD_FreePreparsedData(pp_data); + + return res; +} + HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { if (dev) { @@ -1203,10 +1535,15 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) return (wchar_t*)dev->last_error_str; } - /* Global error messages are not (yet) implemented on Windows. */ - return L"hid_error for global errors is not implemented yet"; + if (last_global_error_str == NULL) + return L"Success"; + return last_global_error_str; } +#ifndef hidapi_winapi_EXPORTS +#include "hidapi_descriptor_reconstruct.c" +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/windows/hidapi_cfgmgr32.h b/windows/hidapi_cfgmgr32.h index 720906e3d..638512a8b 100644 --- a/windows/hidapi_cfgmgr32.h +++ b/windows/hidapi_cfgmgr32.h @@ -32,6 +32,10 @@ /* This part of the header mimics cfgmgr32.h, but only what is used by HIDAPI */ +#include +#include +#include + typedef DWORD RETURN_TYPE; typedef RETURN_TYPE CONFIGRET; typedef DWORD DEVNODE, DEVINST; @@ -54,15 +58,17 @@ typedef CONFIGRET(__stdcall* CM_Get_Device_Interface_List_SizeW_)(PULONG pulLen, 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 diff --git a/windows/hidapi_descriptor_reconstruct.c b/windows/hidapi_descriptor_reconstruct.c new file mode 100644 index 000000000..c76d4ea68 --- /dev/null +++ b/windows/hidapi_descriptor_reconstruct.c @@ -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 rpt_desc Pointer to report descriptor buffer struct. + * + * @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 hierarchy 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 hierarchy, 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 the 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; +} diff --git a/windows/hidapi_descriptor_reconstruct.h b/windows/hidapi_descriptor_reconstruct.h new file mode 100644 index 000000000..4b8ca83fb --- /dev/null +++ b/windows/hidapi_descriptor_reconstruct.h @@ -0,0 +1,247 @@ +/******************************************************* + 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" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4200) +#pragma warning(disable: 4201) +#pragma warning(disable: 4214) +#endif + +#include + +#include "hidapi_hidsdi.h" +#include + +#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; + +// Note: This is risk-reduction-measure for this specific struct, as it has ULONG bit-field. +// Although very unlikely, it might still be possible that the compiler creates a memory layout that is +// not binary compatile. +// Other structs are not checked at the time of writing. +static_assert(sizeof(struct hid_pp_link_collection_node_) == 16, + "Size of struct hid_pp_link_collection_node_ not as expected. This might break binary compatibility"); + +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; + +#ifndef _MSC_VER + // 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 diff --git a/windows/hidapi_hidpi.h b/windows/hidapi_hidpi.h index 343ddeb05..75a5812c9 100644 --- a/windows/hidapi_hidpi.h +++ b/windows/hidapi_hidpi.h @@ -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 diff --git a/windows/hidapi_hidsdi.h b/windows/hidapi_hidsdi.h index 453f89973..ffed5b2f8 100644 --- a/windows/hidapi_hidsdi.h +++ b/windows/hidapi_hidsdi.h @@ -40,8 +40,6 @@ 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); @@ -49,6 +47,7 @@ typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID bu typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); +typedef BOOLEAN (__stdcall* HidD_SetOutputReport_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length); typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); diff --git a/windows/hidapi_winapi.h b/windows/hidapi_winapi.h index 884712af8..a9919923c 100644 --- a/windows/hidapi_winapi.h +++ b/windows/hidapi_winapi.h @@ -26,6 +26,8 @@ #ifndef HIDAPI_WINAPI_H__ #define HIDAPI_WINAPI_H__ +#include + #include #include "hidapi.h" @@ -44,13 +46,27 @@ extern "C" { @ingroup API @param dev A device handle returned from hid_open(). - @param guid The device's container ID on return. + @param container_id 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 diff --git a/windows/pp_data_dump/CMakeLists.txt b/windows/pp_data_dump/CMakeLists.txt new file mode 100644 index 000000000..f017de993 --- /dev/null +++ b/windows/pp_data_dump/CMakeLists.txt @@ -0,0 +1,15 @@ +project(pp_data_dump C) + +add_executable(pp_data_dump pp_data_dump.c) +set_target_properties(pp_data_dump + PROPERTIES + C_STANDARD 11 + C_STANDARD_REQUIRED TRUE +) +target_link_libraries(pp_data_dump + PRIVATE hidapi_winapi +) + +install(TARGETS pp_data_dump + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) diff --git a/windows/pp_data_dump/README.md b/windows/pp_data_dump/README.md new file mode 100644 index 000000000..a0989cd00 --- /dev/null +++ b/windows/pp_data_dump/README.md @@ -0,0 +1,122 @@ +## pp_data_dump.exe for Windows + + +pp_data_dump.exe is a small command line tool for Windows, which dumps the content of the [Preparsed Data](https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/preparsed-data) structure, provided by the Windows HID subsystem, into a file. + +The generated file is in a text format, which is readable for human, as by the hid_report_reconstructor_test.exe unit test executable of the HIDAPI project. This unit test allows it to test the HIDAPIs report descriptor reconstructor - offline, without the hardware device connected. + +pp_data_dump.exe has no arguments, just connect you HID device and execute pp_data_dump.exe. It will generate one file with the name +``` +___.pp_data +``` +for each top-level collection, of each connected HID device. + + +## File content + +The content of such a .pp_data file looks like the struct, which HIDAPI uses internally to represent the Preparsed Data. + +*NOTE: +Windows parses HID report descriptors into opaque `_HIDP_PREPARSED_DATA` objects. +The internal structure of `_HIDP_PREPARSED_DATA` is reserved for internal system use.\ +Microsoft doesn't document this structure. [hid_preparsed_data.cc](https://chromium.googlesource.com/chromium/src/+/73fdaaf605bb60caf34d5f30bb84a417688aa528/services/device/hid/hid_preparsed_data.cc) is taken as a reference for its parsing.* + +``` +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xB010 +dev->manufacturer_string = "Logitech" +dev->product_string = "Logitech Bluetooth Wireless Mouse" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0001 +dev->usage_page = 0x000C +dev->path = "\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002046d_pid&b010&col02#8&1cf1c1b9&3&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0x000C +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 2 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 1 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 1 +pp_data->caps_info[2]->LastCap = 1 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0068 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0006 +pp_data->cap[0]->ReportID = 0x03 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000C +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 0 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0020 +pp_data->cap[0]->NotRange.Reserved1 = 0x0020 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->NotButton.HasNull = 0 +pp_data->cap[0]->NotButton.Reserved4 = 0x000000 +pp_data->cap[0]->NotButton.LogicalMin = 0 +pp_data->cap[0]->NotButton.LogicalMax = 100 +pp_data->cap[0]->NotButton.PhysicalMin = 0 +pp_data->cap[0]->NotButton.PhysicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +``` \ No newline at end of file diff --git a/windows/pp_data_dump/pp_data_dump.c b/windows/pp_data_dump/pp_data_dump.c new file mode 100644 index 000000000..d5df68b50 --- /dev/null +++ b/windows/pp_data_dump/pp_data_dump.c @@ -0,0 +1,238 @@ +#if defined(__MINGW32__) + // Needed for %hh + #define __USE_MINGW_ANSI_STDIO 1 +#endif + +#include +#include <../windows/hidapi_descriptor_reconstruct.h> + +#include + +void dump_hid_pp_cap(FILE* file, phid_pp_cap pp_cap, unsigned int cap_idx) { + fprintf(file, "pp_data->cap[%u]->UsagePage = 0x%04hX\n", cap_idx, pp_cap->UsagePage); + fprintf(file, "pp_data->cap[%u]->ReportID = 0x%02hhX\n", cap_idx, pp_cap->ReportID); + fprintf(file, "pp_data->cap[%u]->BitPosition = %hhu\n", cap_idx, pp_cap->BitPosition); + fprintf(file, "pp_data->cap[%u]->BitSize = %hu\n", cap_idx, pp_cap->ReportSize); + fprintf(file, "pp_data->cap[%u]->ReportCount = %hu\n", cap_idx, pp_cap->ReportCount); + fprintf(file, "pp_data->cap[%u]->BytePosition = 0x%04hX\n", cap_idx, pp_cap->BytePosition); + fprintf(file, "pp_data->cap[%u]->BitCount = %hu\n", cap_idx, pp_cap->BitCount); + fprintf(file, "pp_data->cap[%u]->BitField = 0x%02lX\n", cap_idx, pp_cap->BitField); + fprintf(file, "pp_data->cap[%u]->NextBytePosition = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition); + fprintf(file, "pp_data->cap[%u]->LinkCollection = 0x%04hX\n", cap_idx, pp_cap->LinkCollection); + fprintf(file, "pp_data->cap[%u]->LinkUsagePage = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage); + fprintf(file, "pp_data->cap[%u]->LinkUsage = 0x%04hX\n", cap_idx, pp_cap->LinkUsage); + + // 8 Flags in one byte + fprintf(file, "pp_data->cap[%u]->IsMultipleItemsForArray = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray); + fprintf(file, "pp_data->cap[%u]->IsButtonCap = %hhu\n", cap_idx, pp_cap->IsButtonCap); + fprintf(file, "pp_data->cap[%u]->IsPadding = %hhu\n", cap_idx, pp_cap->IsPadding); + fprintf(file, "pp_data->cap[%u]->IsAbsolute = %hhu\n", cap_idx, pp_cap->IsAbsolute); + fprintf(file, "pp_data->cap[%u]->IsRange = %hhu\n", cap_idx, pp_cap->IsRange); + fprintf(file, "pp_data->cap[%u]->IsAlias = %hhu\n", cap_idx, pp_cap->IsAlias); + fprintf(file, "pp_data->cap[%u]->IsStringRange = %hhu\n", cap_idx, pp_cap->IsStringRange); + fprintf(file, "pp_data->cap[%u]->IsDesignatorRange = %hhu\n", cap_idx, pp_cap->IsDesignatorRange); + + fprintf(file, "pp_data->cap[%u]->Reserved1 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->Reserved1[0], pp_cap->Reserved1[1], pp_cap->Reserved1[2]); + + for (int token_idx = 0; token_idx < 4; token_idx++) { + fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Token = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token); + fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Reserved[0], pp_cap->UnknownTokens[token_idx].Reserved[1], pp_cap->UnknownTokens[token_idx].Reserved[2]); + fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].BitField); + } + + if (pp_cap->IsRange) { + fprintf(file, "pp_data->cap[%u]->Range.UsageMin = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin); + fprintf(file, "pp_data->cap[%u]->Range.UsageMax = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax); + fprintf(file, "pp_data->cap[%u]->Range.StringMin = %hu\n", cap_idx, pp_cap->Range.StringMin); + fprintf(file, "pp_data->cap[%u]->Range.StringMax = %hu\n", cap_idx, pp_cap->Range.StringMax); + fprintf(file, "pp_data->cap[%u]->Range.DesignatorMin = %hu\n", cap_idx, pp_cap->Range.DesignatorMin); + fprintf(file, "pp_data->cap[%u]->Range.DesignatorMax = %hu\n", cap_idx, pp_cap->Range.DesignatorMax); + fprintf(file, "pp_data->cap[%u]->Range.DataIndexMin = %hu\n", cap_idx, pp_cap->Range.DataIndexMin); + fprintf(file, "pp_data->cap[%u]->Range.DataIndexMax = %hu\n", cap_idx, pp_cap->Range.DataIndexMax); + } + else { + fprintf(file, "pp_data->cap[%u]->NotRange.Usage = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved1 = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1); + fprintf(file, "pp_data->cap[%u]->NotRange.StringIndex = %hu\n", cap_idx, pp_cap->NotRange.StringIndex); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved2 = %hu\n", cap_idx, pp_cap->NotRange.Reserved2); + fprintf(file, "pp_data->cap[%u]->NotRange.DesignatorIndex = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved3 = %hu\n", cap_idx, pp_cap->NotRange.Reserved3); + fprintf(file, "pp_data->cap[%u]->NotRange.DataIndex = %hu\n", cap_idx, pp_cap->NotRange.DataIndex); + fprintf(file, "pp_data->cap[%u]->NotRange.Reserved4 = %hu\n", cap_idx, pp_cap->NotRange.Reserved4); + } + + if (pp_cap->IsButtonCap) { + fprintf(file, "pp_data->cap[%u]->Button.LogicalMin = %ld\n", cap_idx, pp_cap->Button.LogicalMin); + fprintf(file, "pp_data->cap[%u]->Button.LogicalMax = %ld\n", cap_idx, pp_cap->Button.LogicalMax); + } + else + { + fprintf(file, "pp_data->cap[%u]->NotButton.HasNull = %hhu\n", cap_idx, pp_cap->NotButton.HasNull); + fprintf(file, "pp_data->cap[%u]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->NotButton.Reserved4[0], pp_cap->NotButton.Reserved4[1], pp_cap->NotButton.Reserved4[2]); + fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMin = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin); + fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMax = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax); + fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMin = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin); + fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMax = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax); + }; + fprintf(file, "pp_data->cap[%u]->Units = %lu\n", cap_idx, pp_cap->Units); + fprintf(file, "pp_data->cap[%u]->UnitsExp = %lu\n", cap_idx, pp_cap->UnitsExp); +} + +void dump_hidp_link_collection_node(FILE* file, phid_pp_link_collection_node pcoll, unsigned int coll_idx) { + fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsage = 0x%04hX\n", coll_idx, pcoll->LinkUsage); + fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsagePage = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage); + fprintf(file, "pp_data->LinkCollectionArray[%u]->Parent = %hu\n", coll_idx, pcoll->Parent); + fprintf(file, "pp_data->LinkCollectionArray[%u]->NumberOfChildren = %hu\n", coll_idx, pcoll->NumberOfChildren); + fprintf(file, "pp_data->LinkCollectionArray[%u]->NextSibling = %hu\n", coll_idx, pcoll->NextSibling); + fprintf(file, "pp_data->LinkCollectionArray[%u]->FirstChild = %hu\n", coll_idx, pcoll->FirstChild); + // The compilers are not consistent on ULONG-bit-fields: They lose the unsinged or define them as int. + // Thus just always cast them to unsinged int, which should be fine, as the biggest bit-field is 28 bit + fprintf(file, "pp_data->LinkCollectionArray[%u]->CollectionType = %u\n", coll_idx, (unsigned int)(pcoll->CollectionType)); + fprintf(file, "pp_data->LinkCollectionArray[%u]->IsAlias = %u\n", coll_idx, (unsigned int)(pcoll->IsAlias)); + fprintf(file, "pp_data->LinkCollectionArray[%u]->Reserved = 0x%08X\n", coll_idx, (unsigned int)(pcoll->Reserved)); +} + +int dump_pp_data(FILE* file, hid_device* dev) +{ + BOOL res; + hidp_preparsed_data* pp_data = NULL; + + res = HidD_GetPreparsedData(dev->device_handle, (PHIDP_PREPARSED_DATA*) &pp_data); + if (!res) { + printf("ERROR: HidD_GetPreparsedData failed!"); + return -1; + } + else { + fprintf(file, "pp_data->MagicKey = 0x%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX\n", pp_data->MagicKey[0], pp_data->MagicKey[1], pp_data->MagicKey[2], pp_data->MagicKey[3], pp_data->MagicKey[4], pp_data->MagicKey[5], pp_data->MagicKey[6], pp_data->MagicKey[7]); + fprintf(file, "pp_data->Usage = 0x%04hX\n", pp_data->Usage); + fprintf(file, "pp_data->UsagePage = 0x%04hX\n", pp_data->UsagePage); + fprintf(file, "pp_data->Reserved = 0x%04hX%04hX\n", pp_data->Reserved[0], pp_data->Reserved[1]); + fprintf(file, "# Input caps_info struct:\n"); + fprintf(file, "pp_data->caps_info[0]->FirstCap = %hu\n", pp_data->caps_info[0].FirstCap); + fprintf(file, "pp_data->caps_info[0]->LastCap = %hu\n", pp_data->caps_info[0].LastCap); + fprintf(file, "pp_data->caps_info[0]->NumberOfCaps = %hu\n", pp_data->caps_info[0].NumberOfCaps); + fprintf(file, "pp_data->caps_info[0]->ReportByteLength = %hu\n", pp_data->caps_info[0].ReportByteLength); + fprintf(file, "# Output caps_info struct:\n"); + fprintf(file, "pp_data->caps_info[1]->FirstCap = %hu\n", pp_data->caps_info[1].FirstCap); + fprintf(file, "pp_data->caps_info[1]->LastCap = %hu\n", pp_data->caps_info[1].LastCap); + fprintf(file, "pp_data->caps_info[1]->NumberOfCaps = %hu\n", pp_data->caps_info[1].NumberOfCaps); + fprintf(file, "pp_data->caps_info[1]->ReportByteLength = %hu\n", pp_data->caps_info[1].ReportByteLength); + fprintf(file, "# Feature caps_info struct:\n"); + fprintf(file, "pp_data->caps_info[2]->FirstCap = %hu\n", pp_data->caps_info[2].FirstCap); + fprintf(file, "pp_data->caps_info[2]->LastCap = %hu\n", pp_data->caps_info[2].LastCap); + fprintf(file, "pp_data->caps_info[2]->NumberOfCaps = %hu\n", pp_data->caps_info[2].NumberOfCaps); + fprintf(file, "pp_data->caps_info[2]->ReportByteLength = %hu\n", pp_data->caps_info[2].ReportByteLength); + fprintf(file, "# LinkCollectionArray Offset & Size:\n"); + fprintf(file, "pp_data->FirstByteOfLinkCollectionArray = 0x%04hX\n", pp_data->FirstByteOfLinkCollectionArray); + fprintf(file, "pp_data->NumberLinkCollectionNodes = %hu\n", pp_data->NumberLinkCollectionNodes); + + + phid_pp_cap pcap = (phid_pp_cap)(((unsigned char*)pp_data) + offsetof(hidp_preparsed_data, caps)); + fprintf(file, "# Input hid_pp_cap struct:\n"); + for (int caps_idx = pp_data->caps_info[0].FirstCap; caps_idx < pp_data->caps_info[0].LastCap; caps_idx++) { + dump_hid_pp_cap(file, pcap + caps_idx, caps_idx); + fprintf(file, "\n"); + } + fprintf(file, "# Output hid_pp_cap struct:\n"); + for (int caps_idx = pp_data->caps_info[1].FirstCap; caps_idx < pp_data->caps_info[1].LastCap; caps_idx++) { + dump_hid_pp_cap(file, pcap + caps_idx, caps_idx); + fprintf(file, "\n"); + } + fprintf(file, "# Feature hid_pp_cap struct:\n"); + for (int caps_idx = pp_data->caps_info[2].FirstCap; caps_idx < pp_data->caps_info[2].LastCap; caps_idx++) { + dump_hid_pp_cap(file, pcap + caps_idx, caps_idx); + fprintf(file, "\n"); + } + + phid_pp_link_collection_node pcoll = (phid_pp_link_collection_node)(((unsigned char*)pcap) + pp_data->FirstByteOfLinkCollectionArray); + fprintf(file, "# Link Collections:\n"); + for (int coll_idx = 0; coll_idx < pp_data->NumberLinkCollectionNodes; coll_idx++) { + dump_hidp_link_collection_node(file, pcoll + coll_idx, coll_idx); + } + + HidD_FreePreparsedData((PHIDP_PREPARSED_DATA) pp_data); + return 0; + } +} + +int main(int argc, char* argv[]) +{ + (void)argc; + (void)argv; + + #define MAX_STR 255 + + struct hid_device_info *devs, *cur_dev; + + printf("pp_data_dump tool. Compiled with hidapi version %s, runtime version %s.\n", HID_API_VERSION_STR, hid_version_str()); + if (hid_version()->major == HID_API_VERSION_MAJOR && hid_version()->minor == HID_API_VERSION_MINOR && hid_version()->patch == HID_API_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; + + 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(" Usage (page): %02X (%02X)\n", cur_dev->usage, cur_dev->usage_page); + + hid_device *device = hid_open_path(cur_dev->path); + if (device) { + char filename[MAX_STR]; + FILE* file; + + sprintf_s(filename, MAX_STR, "%04X_%04X_%04X_%04X.pp_data", cur_dev->vendor_id, cur_dev->product_id, cur_dev->usage, cur_dev->usage_page); + errno_t err = fopen_s(&file, filename, "w"); + if (err == 0) { + fprintf(file, "# HIDAPI device info struct:\n"); + fprintf(file, "dev->vendor_id = 0x%04hX\n", cur_dev->vendor_id); + fprintf(file, "dev->product_id = 0x%04hX\n", cur_dev->product_id); + fprintf(file, "dev->manufacturer_string = \"%ls\"\n", cur_dev->manufacturer_string); + fprintf(file, "dev->product_string = \"%ls\"\n", cur_dev->product_string); + fprintf(file, "dev->release_number = 0x%04hX\n", cur_dev->release_number); + fprintf(file, "dev->interface_number = %d\n", cur_dev->interface_number); + fprintf(file, "dev->usage = 0x%04hX\n", cur_dev->usage); + fprintf(file, "dev->usage_page = 0x%04hX\n", cur_dev->usage_page); + fprintf(file, "dev->path = \"%s\"\n", cur_dev->path); + fprintf(file, "\n# Preparsed Data struct:\n"); + int res = dump_pp_data(file, device); + + if (res == 0) { + printf("Dumped Preparsed Data to %s\n", filename); + } + else { + printf("ERROR: Dump Preparsed Data to %s failed!\n", filename); + } + + fclose(file); + } + + hid_close(device); + } + else { + printf(" Device: not available.\n"); + } + + printf("\n"); + cur_dev = cur_dev->next; + } + hid_free_enumeration(devs); + + + /* Free static HIDAPI objects. */ + hid_exit(); + + //system("pause"); + + return 0; +} diff --git a/windows/test/CMakeLists.txt b/windows/test/CMakeLists.txt new file mode 100644 index 000000000..eae3217ed --- /dev/null +++ b/windows/test/CMakeLists.txt @@ -0,0 +1,76 @@ +add_executable(hid_report_reconstructor_test hid_report_reconstructor_test.c) +set_target_properties(hid_report_reconstructor_test + PROPERTIES + C_STANDARD 11 + C_STANDARD_REQUIRED TRUE +) + +target_link_libraries(hid_report_reconstructor_test + PRIVATE hidapi_include hidapi_winapi +) + +# Each test case requires 2 files: +# .pp_data - textual representation of HIDP_PREPARSED_DATA; +# _expected.rpt_desc - reconstructed HID Report Descriptor out of .pp_data file; +# +# (Non-required by test): +# _real.dpt_desc - the original report rescriptor used to create a test case; +set(HID_DESCRIPTOR_RECONSTRUCT_TEST_CASES + 046D_C52F_0001_000C + 046D_C52F_0001_FF00 + 046D_C52F_0002_0001 + 046D_C52F_0002_FF00 + 17CC_1130_0000_FF01 + 046D_0A37_0001_000C + 046A_0011_0006_0001 + 046D_C077_0002_0001 + 046D_C283_0004_0001 + 046D_B010_0006_0001 + 046D_B010_0002_FF00 + 046D_B010_0002_0001 + 046D_B010_0001_FF00 + 046D_B010_0001_000C + 046D_C534_0001_000C + 046D_C534_0001_FF00 + 046D_C534_0002_0001 + 046D_C534_0002_FF00 + 046D_C534_0006_0001 + 046D_C534_0080_0001 + 047F_C056_0001_000C + 047F_C056_0003_FFA0 + 047F_C056_0005_000B + 045E_02FF_0005_0001 +) + +set(CMAKE_VERSION_SUPPORTS_ENVIRONMENT_MODIFICATION "3.22") + +if(HIDAPI_ENABLE_ASAN AND MSVC) + if(CMAKE_VERSION VERSION_LESS CMAKE_VERSION_SUPPORTS_ENVIRONMENT_MODIFICATION) + message("CTest/ASAN: Make sure to run ctest from MSVC Command Prompt") + endif() +endif() + +foreach(TEST_CASE ${HID_DESCRIPTOR_RECONSTRUCT_TEST_CASES}) + set(TEST_PP_DATA "${CMAKE_CURRENT_LIST_DIR}/data/${TEST_CASE}.pp_data") + if(NOT EXISTS "${TEST_PP_DATA}") + message(FATAL_ERROR "Missing '${TEST_PP_DATA}' file for '${TEST_CASE}' test case") + endif() + set(TEST_EXPECTED_DESCRIPTOR "${CMAKE_CURRENT_LIST_DIR}/data/${TEST_CASE}_expected.rpt_desc") + if(NOT EXISTS "${TEST_EXPECTED_DESCRIPTOR}") + message(FATAL_ERROR "Missing '${TEST_EXPECTED_DESCRIPTOR}' file for '${TEST_CASE}' test case") + endif() + + add_test(NAME "WinHidReportReconstructTest_${TEST_CASE}" + COMMAND hid_report_reconstructor_test "${TEST_PP_DATA}" "${TEST_EXPECTED_DESCRIPTOR}" + WORKING_DIRECTORY "$" + ) + if(HIDAPI_ENABLE_ASAN) + if(MSVC) + if(NOT CMAKE_VERSION VERSION_LESS CMAKE_VERSION_SUPPORTS_ENVIRONMENT_MODIFICATION) + get_filename_component(MSVC_BUILD_TOOLS_DIR "${CMAKE_LINKER}" DIRECTORY) + set_property(TEST "WinHidReportReconstructTest_${TEST_CASE}" PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_append:${MSVC_BUILD_TOOLS_DIR}") + endif() + endif() + set_property(TEST "WinHidReportReconstructTest_${TEST_CASE}" PROPERTY ENVIRONMENT "ASAN_SAVE_DUMPS=AsanDump_${TEST_CASE}.dmp") + endif() +endforeach() diff --git a/windows/test/data/045E_02FF_0005_0001.pp_data b/windows/test/data/045E_02FF_0005_0001.pp_data new file mode 100644 index 000000000..622699600 --- /dev/null +++ b/windows/test/data/045E_02FF_0005_0001.pp_data @@ -0,0 +1,420 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x045E +dev->product_id = 0x02FF +dev->manufacturer_string = "" +dev->product_string = "Controller (Xbox One For Windows)" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0005 +dev->usage_page = 0x0001 +dev->path = "\\?\HID#VID_045E&PID_02FF&IG_00#7&5ea4a81&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0005 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 7 +pp_data->caps_info[0]->NumberOfCaps = 7 +pp_data->caps_info[0]->ReportByteLength = 16 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 7 +pp_data->caps_info[1]->LastCap = 7 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 7 +pp_data->caps_info[2]->LastCap = 7 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x02D8 +pp_data->NumberLinkCollectionNodes = 4 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0001 +pp_data->cap[0]->ReportID = 0x00 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 16 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0003 +pp_data->cap[0]->BitCount = 16 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0005 +pp_data->cap[0]->LinkCollection = 0x0001 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0000 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 0 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0031 +pp_data->cap[0]->NotRange.Reserved1 = 0x0031 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->NotButton.HasNull = 0 +pp_data->cap[0]->NotButton.Reserved4 = 0x000000 +pp_data->cap[0]->NotButton.LogicalMin = 0 +pp_data->cap[0]->NotButton.LogicalMax = -1 +pp_data->cap[0]->NotButton.PhysicalMin = 0 +pp_data->cap[0]->NotButton.PhysicalMax = -1 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x00 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 16 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 16 +pp_data->cap[1]->BitField = 0x02 +pp_data->cap[1]->NextBytePosition = 0x0003 +pp_data->cap[1]->LinkCollection = 0x0001 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0000 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0030 +pp_data->cap[1]->NotRange.Reserved1 = 0x0030 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = 0 +pp_data->cap[1]->NotButton.LogicalMax = -1 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = -1 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x0001 +pp_data->cap[2]->ReportID = 0x00 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 16 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0007 +pp_data->cap[2]->BitCount = 16 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0009 +pp_data->cap[2]->LinkCollection = 0x0002 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0000 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0034 +pp_data->cap[2]->NotRange.Reserved1 = 0x0034 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = 0 +pp_data->cap[2]->NotButton.LogicalMax = -1 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = -1 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0001 +pp_data->cap[3]->ReportID = 0x00 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 16 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0005 +pp_data->cap[3]->BitCount = 16 +pp_data->cap[3]->BitField = 0x02 +pp_data->cap[3]->NextBytePosition = 0x0007 +pp_data->cap[3]->LinkCollection = 0x0002 +pp_data->cap[3]->LinkUsagePage = 0x0001 +pp_data->cap[3]->LinkUsage = 0x0000 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 1 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0033 +pp_data->cap[3]->NotRange.Reserved1 = 0x0033 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 3 +pp_data->cap[3]->NotRange.Reserved4 = 3 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = 0 +pp_data->cap[3]->NotButton.LogicalMax = -1 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = -1 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x0001 +pp_data->cap[4]->ReportID = 0x00 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 16 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0009 +pp_data->cap[4]->BitCount = 16 +pp_data->cap[4]->BitField = 0x02 +pp_data->cap[4]->NextBytePosition = 0x000B +pp_data->cap[4]->LinkCollection = 0x0003 +pp_data->cap[4]->LinkUsagePage = 0x0001 +pp_data->cap[4]->LinkUsage = 0x0000 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 0 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 1 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0032 +pp_data->cap[4]->NotRange.Reserved1 = 0x0032 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 4 +pp_data->cap[4]->NotRange.Reserved4 = 4 +pp_data->cap[4]->NotButton.HasNull = 0 +pp_data->cap[4]->NotButton.Reserved4 = 0x000000 +pp_data->cap[4]->NotButton.LogicalMin = 0 +pp_data->cap[4]->NotButton.LogicalMax = -1 +pp_data->cap[4]->NotButton.PhysicalMin = 0 +pp_data->cap[4]->NotButton.PhysicalMax = -1 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +pp_data->cap[5]->UsagePage = 0x0009 +pp_data->cap[5]->ReportID = 0x00 +pp_data->cap[5]->BitPosition = 0 +pp_data->cap[5]->BitSize = 1 +pp_data->cap[5]->ReportCount = 16 +pp_data->cap[5]->BytePosition = 0x000B +pp_data->cap[5]->BitCount = 16 +pp_data->cap[5]->BitField = 0x02 +pp_data->cap[5]->NextBytePosition = 0x000D +pp_data->cap[5]->LinkCollection = 0x0000 +pp_data->cap[5]->LinkUsagePage = 0x0001 +pp_data->cap[5]->LinkUsage = 0x0005 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 1 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 1 +pp_data->cap[5]->IsRange = 1 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->Range.UsageMin = 0x0001 +pp_data->cap[5]->Range.UsageMax = 0x0010 +pp_data->cap[5]->Range.StringMin = 0 +pp_data->cap[5]->Range.StringMax = 0 +pp_data->cap[5]->Range.DesignatorMin = 0 +pp_data->cap[5]->Range.DesignatorMax = 0 +pp_data->cap[5]->Range.DataIndexMin = 5 +pp_data->cap[5]->Range.DataIndexMax = 20 +pp_data->cap[5]->Button.LogicalMin = 0 +pp_data->cap[5]->Button.LogicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0x0001 +pp_data->cap[6]->ReportID = 0x00 +pp_data->cap[6]->BitPosition = 0 +pp_data->cap[6]->BitSize = 4 +pp_data->cap[6]->ReportCount = 1 +pp_data->cap[6]->BytePosition = 0x000D +pp_data->cap[6]->BitCount = 4 +pp_data->cap[6]->BitField = 0x42 +pp_data->cap[6]->NextBytePosition = 0x000E +pp_data->cap[6]->LinkCollection = 0x0000 +pp_data->cap[6]->LinkUsagePage = 0x0001 +pp_data->cap[6]->LinkUsage = 0x0005 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 0 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x0039 +pp_data->cap[6]->NotRange.Reserved1 = 0x0039 +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 21 +pp_data->cap[6]->NotRange.Reserved4 = 21 +pp_data->cap[6]->NotButton.HasNull = 1 +pp_data->cap[6]->NotButton.Reserved4 = 0x000000 +pp_data->cap[6]->NotButton.LogicalMin = 1 +pp_data->cap[6]->NotButton.LogicalMax = 8 +pp_data->cap[6]->NotButton.PhysicalMin = 0 +pp_data->cap[6]->NotButton.PhysicalMax = 4155 +pp_data->cap[6]->Units = 14 +pp_data->cap[6]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0005 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 3 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 3 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0000 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 0 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[2]->LinkUsage = 0x0000 +pp_data->LinkCollectionArray[2]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[2]->Parent = 0 +pp_data->LinkCollectionArray[2]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[2]->NextSibling = 1 +pp_data->LinkCollectionArray[2]->FirstChild = 0 +pp_data->LinkCollectionArray[2]->CollectionType = 0 +pp_data->LinkCollectionArray[2]->IsAlias = 0 +pp_data->LinkCollectionArray[2]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[3]->LinkUsage = 0x0000 +pp_data->LinkCollectionArray[3]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[3]->Parent = 0 +pp_data->LinkCollectionArray[3]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[3]->NextSibling = 2 +pp_data->LinkCollectionArray[3]->FirstChild = 0 +pp_data->LinkCollectionArray[3]->CollectionType = 0 +pp_data->LinkCollectionArray[3]->IsAlias = 0 +pp_data->LinkCollectionArray[3]->Reserved = 0x00000000 \ No newline at end of file diff --git a/windows/test/data/045E_02FF_0005_0001_expected.rpt_desc b/windows/test/data/045E_02FF_0005_0001_expected.rpt_desc new file mode 100644 index 000000000..58f80e482 --- /dev/null +++ b/windows/test/data/045E_02FF_0005_0001_expected.rpt_desc @@ -0,0 +1,12 @@ +0x05, 0x01, 0x09, 0x05, 0xA1, 0x01, 0x09, 0x00, 0xA1, 0x00, +0x09, 0x30, 0x09, 0x31, 0x15, 0x00, 0x25, 0xFF, 0x35, 0x00, +0x45, 0xFF, 0x75, 0x10, 0x95, 0x02, 0x81, 0x02, 0xC0, 0x09, +0x00, 0xA1, 0x00, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x25, +0xFF, 0x75, 0x10, 0x95, 0x02, 0x81, 0x02, 0xC0, 0x09, 0x00, +0xA1, 0x00, 0x09, 0x32, 0x15, 0x00, 0x25, 0xFF, 0x75, 0x10, +0x95, 0x01, 0x81, 0x02, 0xC0, 0x05, 0x09, 0x19, 0x01, 0x29, +0x10, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x10, 0x45, +0x00, 0x81, 0x02, 0x05, 0x01, 0x09, 0x39, 0x15, 0x01, 0x25, +0x08, 0x35, 0x00, 0x46, 0x3B, 0x10, 0x65, 0x0E, 0x75, 0x04, +0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01, 0x81, 0x03, +0xC0, \ No newline at end of file diff --git a/windows/test/data/045E_02FF_0005_0001_real.rpt_desc b/windows/test/data/045E_02FF_0005_0001_real.rpt_desc new file mode 100644 index 000000000..11cc78b18 --- /dev/null +++ b/windows/test/data/045E_02FF_0005_0001_real.rpt_desc @@ -0,0 +1,64 @@ +// Special cases of this device: +// 2 full padding bytes at the end +// Multiple child collections inside of the same report (byte position of Input items defines collection order) + +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x05, // Usage (Game Pad) +0xA1, 0x01, // Collection (Application) +0xA1, 0x00, // Collection (Physical) +0x09, 0x30, // Usage (X) +0x09, 0x31, // Usage (Y) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0xFF, // Logical Maximum (-1) +0x35, 0x00, // Physical Minimum (0) +0x46, 0xFF, 0xFF, // Physical Maximum (-1) +0x95, 0x02, // Report Count (2) +0x75, 0x10, // Report Size (16) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection +0xA1, 0x00, // Collection (Physical) +0x09, 0x33, // Usage (Rx) +0x09, 0x34, // Usage (Ry) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0xFF, // Logical Maximum (-1) +0x35, 0x00, // Physical Minimum (0) +0x46, 0xFF, 0xFF, // Physical Maximum (-1) +0x95, 0x02, // Report Count (2) +0x75, 0x10, // Report Size (16) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection +0xA1, 0x00, // Collection (Physical) +0x09, 0x32, // Usage (Z) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0xFF, // Logical Maximum (-1) +0x35, 0x00, // Physical Minimum (0) +0x46, 0xFF, 0xFF, // Physical Maximum (-1) +0x95, 0x01, // Report Count (1) +0x75, 0x10, // Report Size (16) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection +0x05, 0x09, // Usage Page (Button) +0x19, 0x01, // Usage Minimum (0x01) +0x29, 0x10, // Usage Maximum (0x10) +0x95, 0x10, // Report Count (16) +0x75, 0x01, // Report Size (1) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x39, // Usage (Hat switch) +0x15, 0x01, // Logical Minimum (1) +0x25, 0x08, // Logical Maximum (8) +0x35, 0x00, // Physical Minimum (0) +0x46, 0x3B, 0x10, // Physical Maximum (4155) +0x66, 0x0E, 0x00, // Unit (None) +0x75, 0x04, // Report Size (4) +0x95, 0x01, // Report Count (1) +0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) +0x75, 0x04, // Report Size (4) +0x95, 0x01, // Report Count (1) +0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x75, 0x08, // Report Size (8) +0x95, 0x02, // Report Count (2) +0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection + +// 120 bytes \ No newline at end of file diff --git a/windows/test/data/046A_0011_0006_0001.pp_data b/windows/test/data/046A_0011_0006_0001.pp_data new file mode 100644 index 000000000..59eb60026 --- /dev/null +++ b/windows/test/data/046A_0011_0006_0001.pp_data @@ -0,0 +1,183 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046A +dev->product_id = 0x0011 +dev->manufacturer_string = "dev->product_string = "dev->release_number = 0x0100 +dev->interface_number = -1 +dev->usage = 0x0006 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046a&pid_0011#7&2c7fd0a5&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0006 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 2 +pp_data->caps_info[0]->NumberOfCaps = 2 +pp_data->caps_info[0]->ReportByteLength = 9 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 2 +pp_data->caps_info[1]->LastCap = 3 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 2 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 3 +pp_data->caps_info[2]->LastCap = 3 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0138 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0007 +pp_data->cap[0]->ReportID = 0x00 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 8 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0006 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x00E0 +pp_data->cap[0]->Range.UsageMax = 0x00E7 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 7 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0007 +pp_data->cap[1]->ReportID = 0x00 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 6 +pp_data->cap[1]->BytePosition = 0x0003 +pp_data->cap[1]->BitCount = 48 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0009 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0006 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 1 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->Range.UsageMin = 0x0000 +pp_data->cap[1]->Range.UsageMax = 0x00DD +pp_data->cap[1]->Range.StringMin = 0 +pp_data->cap[1]->Range.StringMax = 0 +pp_data->cap[1]->Range.DesignatorMin = 0 +pp_data->cap[1]->Range.DesignatorMax = 0 +pp_data->cap[1]->Range.DataIndexMin = 8 +pp_data->cap[1]->Range.DataIndexMax = 229 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 221 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[2]->UsagePage = 0x0008 +pp_data->cap[2]->ReportID = 0x00 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 3 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 3 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0006 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 1 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->Range.UsageMin = 0x0001 +pp_data->cap[2]->Range.UsageMax = 0x0003 +pp_data->cap[2]->Range.StringMin = 0 +pp_data->cap[2]->Range.StringMax = 0 +pp_data->cap[2]->Range.DesignatorMin = 0 +pp_data->cap[2]->Range.DesignatorMax = 0 +pp_data->cap[2]->Range.DataIndexMin = 0 +pp_data->cap[2]->Range.DataIndexMax = 2 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0006 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046A_0011_0006_0001_expected.rpt_desc b/windows/test/data/046A_0011_0006_0001_expected.rpt_desc new file mode 100644 index 000000000..e9bc5013c --- /dev/null +++ b/windows/test/data/046A_0011_0006_0001_expected.rpt_desc @@ -0,0 +1,7 @@ +0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, +0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, +0x81, 0x02, 0x75, 0x08, 0x95, 0x01, 0x81, 0x03, 0x19, 0x00, +0x29, 0xDD, 0x15, 0x00, 0x26, 0xDD, 0x00, 0x75, 0x08, 0x95, +0x06, 0x81, 0x00, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x15, +0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x03, 0x91, 0x02, 0x75, +0x05, 0x95, 0x01, 0x91, 0x03, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046A_0011_0006_0001_real.rpt_desc b/windows/test/data/046A_0011_0006_0001_real.rpt_desc new file mode 100644 index 000000000..e9bc5013c --- /dev/null +++ b/windows/test/data/046A_0011_0006_0001_real.rpt_desc @@ -0,0 +1,7 @@ +0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, +0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, +0x81, 0x02, 0x75, 0x08, 0x95, 0x01, 0x81, 0x03, 0x19, 0x00, +0x29, 0xDD, 0x15, 0x00, 0x26, 0xDD, 0x00, 0x75, 0x08, 0x95, +0x06, 0x81, 0x00, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x15, +0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x03, 0x91, 0x02, 0x75, +0x05, 0x95, 0x01, 0x91, 0x03, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_0A37_0001_000C.pp_data b/windows/test/data/046D_0A37_0001_000C.pp_data new file mode 100644 index 000000000..3bc7aadba --- /dev/null +++ b/windows/test/data/046D_0A37_0001_000C.pp_data @@ -0,0 +1,532 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0x0A37 +dev->manufacturer_string = "Logitech Inc " +dev->product_string = "Logitech USB Headset H540" +dev->release_number = 0x0122 +dev->interface_number = 3 +dev->usage = 0x0001 +dev->usage_page = 0x000C +dev->path = "\\?\hid#vid_046d&pid_0a37&mi_03#8&1717f300&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0x000C +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 7 +pp_data->caps_info[0]->NumberOfCaps = 9 +pp_data->caps_info[0]->ReportByteLength = 33 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 9 +pp_data->caps_info[1]->LastCap = 12 +pp_data->caps_info[1]->NumberOfCaps = 3 +pp_data->caps_info[1]->ReportByteLength = 37 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 12 +pp_data->caps_info[2]->LastCap = 12 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x04E0 +pp_data->NumberLinkCollectionNodes = 2 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x000C +pp_data->cap[0]->ReportID = 0x01 +pp_data->cap[0]->BitPosition = 1 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 1 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000C +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x00EA +pp_data->cap[0]->NotRange.Reserved1 = 0x00EA +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x000C +pp_data->cap[1]->ReportID = 0x01 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 1 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 1 +pp_data->cap[1]->BitField = 0x02 +pp_data->cap[1]->NextBytePosition = 0x0002 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x000C +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x00E9 +pp_data->cap[1]->NotRange.Reserved1 = 0x00E9 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x000C +pp_data->cap[2]->ReportID = 0x01 +pp_data->cap[2]->BitPosition = 2 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 1 +pp_data->cap[2]->BitField = 0x06 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x000C +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 0 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x00E2 +pp_data->cap[2]->NotRange.Reserved1 = 0x00E2 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0009 +pp_data->cap[3]->ReportID = 0x01 +pp_data->cap[3]->BitPosition = 5 +pp_data->cap[3]->BitSize = 2 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0001 +pp_data->cap[3]->BitCount = 2 +pp_data->cap[3]->BitField = 0x40 +pp_data->cap[3]->NextBytePosition = 0x0002 +pp_data->cap[3]->LinkCollection = 0x0001 +pp_data->cap[3]->LinkUsagePage = 0x000C +pp_data->cap[3]->LinkUsage = 0x0036 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 1 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 1 +pp_data->cap[3]->IsRange = 1 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->Range.UsageMin = 0x0001 +pp_data->cap[3]->Range.UsageMax = 0x0002 +pp_data->cap[3]->Range.StringMin = 0 +pp_data->cap[3]->Range.StringMax = 0 +pp_data->cap[3]->Range.DesignatorMin = 0 +pp_data->cap[3]->Range.DesignatorMax = 0 +pp_data->cap[3]->Range.DataIndexMin = 3 +pp_data->cap[3]->Range.DataIndexMax = 4 +pp_data->cap[3]->Button.LogicalMin = 1 +pp_data->cap[3]->Button.LogicalMax = 2 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x000C +pp_data->cap[4]->ReportID = 0x02 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 1 +pp_data->cap[4]->ReportCount = 16 +pp_data->cap[4]->BytePosition = 0x0001 +pp_data->cap[4]->BitCount = 16 +pp_data->cap[4]->BitField = 0x02 +pp_data->cap[4]->NextBytePosition = 0x0003 +pp_data->cap[4]->LinkCollection = 0x0000 +pp_data->cap[4]->LinkUsagePage = 0x000C +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 1 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 1 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0000 +pp_data->cap[4]->NotRange.Reserved1 = 0x0000 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 5 +pp_data->cap[4]->NotRange.Reserved4 = 5 +pp_data->cap[4]->Button.LogicalMin = 0 +pp_data->cap[4]->Button.LogicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +pp_data->cap[5]->UsagePage = 0x000C +pp_data->cap[5]->ReportID = 0x05 +pp_data->cap[5]->BitPosition = 0 +pp_data->cap[5]->BitSize = 8 +pp_data->cap[5]->ReportCount = 32 +pp_data->cap[5]->BytePosition = 0x0001 +pp_data->cap[5]->BitCount = 256 +pp_data->cap[5]->BitField = 0x02 +pp_data->cap[5]->NextBytePosition = 0x0021 +pp_data->cap[5]->LinkCollection = 0x0000 +pp_data->cap[5]->LinkUsagePage = 0x000C +pp_data->cap[5]->LinkUsage = 0x0001 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 0 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 1 +pp_data->cap[5]->IsRange = 0 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->NotRange.Usage = 0x0000 +pp_data->cap[5]->NotRange.Reserved1 = 0x0000 +pp_data->cap[5]->NotRange.StringIndex = 0 +pp_data->cap[5]->NotRange.Reserved2 = 0 +pp_data->cap[5]->NotRange.DesignatorIndex = 0 +pp_data->cap[5]->NotRange.Reserved3 = 0 +pp_data->cap[5]->NotRange.DataIndex = 6 +pp_data->cap[5]->NotRange.Reserved4 = 6 +pp_data->cap[5]->NotButton.HasNull = 0 +pp_data->cap[5]->NotButton.Reserved4 = 0x000000 +pp_data->cap[5]->NotButton.LogicalMin = 0 +pp_data->cap[5]->NotButton.LogicalMax = 1 +pp_data->cap[5]->NotButton.PhysicalMin = 0 +pp_data->cap[5]->NotButton.PhysicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0x000C +pp_data->cap[6]->ReportID = 0x07 +pp_data->cap[6]->BitPosition = 0 +pp_data->cap[6]->BitSize = 8 +pp_data->cap[6]->ReportCount = 32 +pp_data->cap[6]->BytePosition = 0x0001 +pp_data->cap[6]->BitCount = 256 +pp_data->cap[6]->BitField = 0x02 +pp_data->cap[6]->NextBytePosition = 0x0021 +pp_data->cap[6]->LinkCollection = 0x0000 +pp_data->cap[6]->LinkUsagePage = 0x000C +pp_data->cap[6]->LinkUsage = 0x0001 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 0 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x0000 +pp_data->cap[6]->NotRange.Reserved1 = 0x0000 +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 7 +pp_data->cap[6]->NotRange.Reserved4 = 7 +pp_data->cap[6]->NotButton.HasNull = 0 +pp_data->cap[6]->NotButton.Reserved4 = 0x000000 +pp_data->cap[6]->NotButton.LogicalMin = 0 +pp_data->cap[6]->NotButton.LogicalMax = 1 +pp_data->cap[6]->NotButton.PhysicalMin = 0 +pp_data->cap[6]->NotButton.PhysicalMax = 0 +pp_data->cap[6]->Units = 0 +pp_data->cap[6]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[9]->UsagePage = 0x000C +pp_data->cap[9]->ReportID = 0x03 +pp_data->cap[9]->BitPosition = 0 +pp_data->cap[9]->BitSize = 1 +pp_data->cap[9]->ReportCount = 16 +pp_data->cap[9]->BytePosition = 0x0001 +pp_data->cap[9]->BitCount = 16 +pp_data->cap[9]->BitField = 0x02 +pp_data->cap[9]->NextBytePosition = 0x0003 +pp_data->cap[9]->LinkCollection = 0x0000 +pp_data->cap[9]->LinkUsagePage = 0x000C +pp_data->cap[9]->LinkUsage = 0x0001 +pp_data->cap[9]->IsMultipleItemsForArray = 0 +pp_data->cap[9]->IsButtonCap = 1 +pp_data->cap[9]->IsPadding = 0 +pp_data->cap[9]->IsAbsolute = 1 +pp_data->cap[9]->IsRange = 0 +pp_data->cap[9]->IsAlias = 0 +pp_data->cap[9]->IsStringRange = 0 +pp_data->cap[9]->IsDesignatorRange = 0 +pp_data->cap[9]->Reserved1 = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[9]->NotRange.Usage = 0x0000 +pp_data->cap[9]->NotRange.Reserved1 = 0x0000 +pp_data->cap[9]->NotRange.StringIndex = 0 +pp_data->cap[9]->NotRange.Reserved2 = 0 +pp_data->cap[9]->NotRange.DesignatorIndex = 0 +pp_data->cap[9]->NotRange.Reserved3 = 0 +pp_data->cap[9]->NotRange.DataIndex = 0 +pp_data->cap[9]->NotRange.Reserved4 = 0 +pp_data->cap[9]->Button.LogicalMin = 0 +pp_data->cap[9]->Button.LogicalMax = 0 +pp_data->cap[9]->Units = 0 +pp_data->cap[9]->UnitsExp = 0 + +pp_data->cap[10]->UsagePage = 0x000C +pp_data->cap[10]->ReportID = 0x04 +pp_data->cap[10]->BitPosition = 0 +pp_data->cap[10]->BitSize = 8 +pp_data->cap[10]->ReportCount = 36 +pp_data->cap[10]->BytePosition = 0x0001 +pp_data->cap[10]->BitCount = 288 +pp_data->cap[10]->BitField = 0x02 +pp_data->cap[10]->NextBytePosition = 0x0025 +pp_data->cap[10]->LinkCollection = 0x0000 +pp_data->cap[10]->LinkUsagePage = 0x000C +pp_data->cap[10]->LinkUsage = 0x0001 +pp_data->cap[10]->IsMultipleItemsForArray = 0 +pp_data->cap[10]->IsButtonCap = 0 +pp_data->cap[10]->IsPadding = 0 +pp_data->cap[10]->IsAbsolute = 1 +pp_data->cap[10]->IsRange = 0 +pp_data->cap[10]->IsAlias = 0 +pp_data->cap[10]->IsStringRange = 0 +pp_data->cap[10]->IsDesignatorRange = 0 +pp_data->cap[10]->Reserved1 = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[10]->NotRange.Usage = 0x0000 +pp_data->cap[10]->NotRange.Reserved1 = 0x0000 +pp_data->cap[10]->NotRange.StringIndex = 0 +pp_data->cap[10]->NotRange.Reserved2 = 0 +pp_data->cap[10]->NotRange.DesignatorIndex = 0 +pp_data->cap[10]->NotRange.Reserved3 = 0 +pp_data->cap[10]->NotRange.DataIndex = 1 +pp_data->cap[10]->NotRange.Reserved4 = 1 +pp_data->cap[10]->NotButton.HasNull = 0 +pp_data->cap[10]->NotButton.Reserved4 = 0x000000 +pp_data->cap[10]->NotButton.LogicalMin = 0 +pp_data->cap[10]->NotButton.LogicalMax = 1 +pp_data->cap[10]->NotButton.PhysicalMin = 0 +pp_data->cap[10]->NotButton.PhysicalMax = 0 +pp_data->cap[10]->Units = 0 +pp_data->cap[10]->UnitsExp = 0 + +pp_data->cap[11]->UsagePage = 0x000C +pp_data->cap[11]->ReportID = 0x06 +pp_data->cap[11]->BitPosition = 0 +pp_data->cap[11]->BitSize = 8 +pp_data->cap[11]->ReportCount = 36 +pp_data->cap[11]->BytePosition = 0x0001 +pp_data->cap[11]->BitCount = 288 +pp_data->cap[11]->BitField = 0x02 +pp_data->cap[11]->NextBytePosition = 0x0025 +pp_data->cap[11]->LinkCollection = 0x0000 +pp_data->cap[11]->LinkUsagePage = 0x000C +pp_data->cap[11]->LinkUsage = 0x0001 +pp_data->cap[11]->IsMultipleItemsForArray = 0 +pp_data->cap[11]->IsButtonCap = 0 +pp_data->cap[11]->IsPadding = 0 +pp_data->cap[11]->IsAbsolute = 1 +pp_data->cap[11]->IsRange = 0 +pp_data->cap[11]->IsAlias = 0 +pp_data->cap[11]->IsStringRange = 0 +pp_data->cap[11]->IsDesignatorRange = 0 +pp_data->cap[11]->Reserved1 = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[11]->NotRange.Usage = 0x0000 +pp_data->cap[11]->NotRange.Reserved1 = 0x0000 +pp_data->cap[11]->NotRange.StringIndex = 0 +pp_data->cap[11]->NotRange.Reserved2 = 0 +pp_data->cap[11]->NotRange.DesignatorIndex = 0 +pp_data->cap[11]->NotRange.Reserved3 = 0 +pp_data->cap[11]->NotRange.DataIndex = 2 +pp_data->cap[11]->NotRange.Reserved4 = 2 +pp_data->cap[11]->NotButton.HasNull = 0 +pp_data->cap[11]->NotButton.Reserved4 = 0x000000 +pp_data->cap[11]->NotButton.LogicalMin = 0 +pp_data->cap[11]->NotButton.LogicalMax = 1 +pp_data->cap[11]->NotButton.PhysicalMin = 0 +pp_data->cap[11]->NotButton.PhysicalMax = 0 +pp_data->cap[11]->Units = 0 +pp_data->cap[11]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 1 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 1 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0036 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 2 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_0A37_0001_000C_expected.rpt_desc b/windows/test/data/046D_0A37_0001_000C_expected.rpt_desc new file mode 100644 index 000000000..363a8f54e --- /dev/null +++ b/windows/test/data/046D_0A37_0001_000C_expected.rpt_desc @@ -0,0 +1,16 @@ +0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x01, 0x09, 0xE9, +0x09, 0xEA, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x02, +0x81, 0x02, 0x09, 0xE2, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, +0x95, 0x01, 0x81, 0x06, 0x75, 0x02, 0x95, 0x01, 0x81, 0x03, +0x09, 0x36, 0xA1, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29, 0x02, +0x15, 0x01, 0x25, 0x02, 0x75, 0x02, 0x95, 0x01, 0x81, 0x40, +0x75, 0x01, 0x95, 0x01, 0x81, 0x03, 0xC0, 0x85, 0x02, 0x05, +0x0C, 0x09, 0x00, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, +0x10, 0x81, 0x02, 0x85, 0x05, 0x09, 0x00, 0x15, 0x00, 0x25, +0x01, 0x75, 0x08, 0x95, 0x20, 0x81, 0x02, 0x85, 0x07, 0x09, +0x00, 0x15, 0x00, 0x25, 0x01, 0x75, 0x08, 0x95, 0x20, 0x81, +0x02, 0x85, 0x03, 0x09, 0x00, 0x15, 0x00, 0x25, 0x01, 0x75, +0x01, 0x95, 0x10, 0x91, 0x02, 0x85, 0x04, 0x09, 0x00, 0x15, +0x00, 0x25, 0x01, 0x75, 0x08, 0x95, 0x24, 0x91, 0x02, 0x85, +0x06, 0x09, 0x00, 0x15, 0x00, 0x25, 0x01, 0x75, 0x08, 0x95, +0x24, 0x91, 0x02, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_0A37_0001_000C_real.rpt_desc b/windows/test/data/046D_0A37_0001_000C_real.rpt_desc new file mode 100644 index 000000000..c78474349 --- /dev/null +++ b/windows/test/data/046D_0A37_0001_000C_real.rpt_desc @@ -0,0 +1,61 @@ +Usage Page (Consumer Devices) 05 0C +Usage (Consumer Control) 09 01 +Collection (Application) A1 01 + Report ID (1) 85 01 + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Usage (Volume Increment) 09 E9 + Usage (Volume Decrement) 09 EA + Report Size (1) 75 01 + Report Count (2) 95 02 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Usage (Mute) 09 E2 + Report Count (1) 95 01 + Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 81 06 + Usage (Undefined) 09 00 + Report Count (2) 95 02 + Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03 + Usage (Function Buttons) 09 36 + Collection (Logical) A1 02 + Usage Page (Button) 05 09 + Usage Minimum (Button 1) 19 01 + Usage Maximum (Button 2) 29 02 + Report Size (2) 75 02 + Report Count (1) 95 01 + Logical Minimum (1) 15 01 + Logical Maximum (2) 25 02 + Input (Data,Ary,Abs) 81 40 + End Collection C0 + Usage Page (Consumer Devices) 05 0C + Usage (Undefined) 09 00 + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Report Size (1) 75 01 + Report Count (1) 95 01 + Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03 + Report ID (2) 85 02 + Usage Page (Consumer Devices) 05 0C + Usage (Undefined) 09 00 + Report Count (16) 95 10 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Report ID (3) 85 03 + Usage (Undefined) 09 00 + Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02 + Report ID (4) 85 04 + Usage (Undefined) 09 00 + Report Size (8) 75 08 + Report Count (36) 95 24 + Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02 + Report ID (5) 85 05 + Usage (Undefined) 09 00 + Report Count (32) 95 20 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Report ID (6) 85 06 + Usage (Undefined) 09 00 + Report Count (36) 95 24 + Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02 + Report ID (7) 85 07 + Usage (Undefined) 09 00 + Report Count (32) 95 20 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 +End Collection C0 diff --git a/windows/test/data/046D_B010_0001_000C.pp_data b/windows/test/data/046D_B010_0001_000C.pp_data new file mode 100644 index 000000000..047445b3b --- /dev/null +++ b/windows/test/data/046D_B010_0001_000C.pp_data @@ -0,0 +1,97 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xB010 +dev->manufacturer_string = "Logitech" +dev->product_string = "Logitech Bluetooth Wireless Mouse" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0001 +dev->usage_page = 0x000C +dev->path = "\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002046d_pid&b010&col02#8&1cf1c1b9&3&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0x000C +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 2 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 1 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 1 +pp_data->caps_info[2]->LastCap = 1 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0068 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0006 +pp_data->cap[0]->ReportID = 0x03 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000C +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 0 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0020 +pp_data->cap[0]->NotRange.Reserved1 = 0x0020 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->NotButton.HasNull = 0 +pp_data->cap[0]->NotButton.Reserved4 = 0x000000 +pp_data->cap[0]->NotButton.LogicalMin = 0 +pp_data->cap[0]->NotButton.LogicalMax = 100 +pp_data->cap[0]->NotButton.PhysicalMin = 0 +pp_data->cap[0]->NotButton.PhysicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_B010_0001_000C_expected.rpt_desc b/windows/test/data/046D_B010_0001_000C_expected.rpt_desc new file mode 100644 index 000000000..c80dd13cd --- /dev/null +++ b/windows/test/data/046D_B010_0001_000C_expected.rpt_desc @@ -0,0 +1,3 @@ +0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x03, 0x05, 0x06, +0x09, 0x20, 0x15, 0x00, 0x25, 0x64, 0x75, 0x08, 0x95, 0x01, +0x81, 0x02, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_B010_0001_000C_real.rpt_desc b/windows/test/data/046D_B010_0001_000C_real.rpt_desc new file mode 100644 index 000000000..ff019a9fd --- /dev/null +++ b/windows/test/data/046D_B010_0001_000C_real.rpt_desc @@ -0,0 +1,38 @@ + +mac-hid-dump on  main ❯ ./mac-hid-dump +mac-hid-dump: +... +046D B010: Unknown - Bluetooth Mouse M557 +DESCRIPTOR: + 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 + 29 08 15 00 25 01 75 01 95 08 81 02 05 01 09 30 + 09 31 16 01 f8 26 ff 07 75 0c 95 02 81 06 09 38 + 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 75 + 08 95 01 81 06 c0 c0 05 0c 09 01 a1 01 85 03 05 + 06 09 20 15 00 26 64 00 75 08 95 01 81 02 c0 06 + 00 ff 09 01 a1 01 85 10 75 08 95 06 15 00 26 ff + 00 09 01 81 00 09 01 91 00 c0 06 00 ff 09 02 a1 + 01 85 11 75 08 95 13 15 00 26 ff 00 09 02 81 00 + 09 02 91 00 c0 05 01 09 06 a1 01 85 04 75 01 95 + 08 05 07 19 e0 29 e7 15 00 25 01 81 02 95 01 75 + 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 + 01 75 03 91 03 95 06 75 08 15 00 26 ff 00 05 07 + 19 00 29 ff 81 00 c0 05 0c 09 01 a1 01 85 05 15 + 00 25 01 75 01 95 02 0a 25 02 0a 24 02 81 02 95 + 01 75 06 81 03 c0 + (246 bytes) + +Parser output: + +0x05, 0x0C, // Usage Page (Consumer) +0x09, 0x01, // Usage (Consumer Control) +0xA1, 0x01, // Collection (Application) +0x85, 0x03, // Report ID (3) +0x05, 0x06, // Usage Page (Generic Dev Ctrls) +0x09, 0x20, // Usage (Battery Strength) +0x15, 0x00, // Logical Minimum (0) +0x26, 0x64, 0x00, // Logical Maximum (100) +0x75, 0x08, // Report Size (8) +0x95, 0x01, // Report Count (1) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection diff --git a/windows/test/data/046D_B010_0001_FF00.pp_data b/windows/test/data/046D_B010_0001_FF00.pp_data new file mode 100644 index 000000000..13b27da08 --- /dev/null +++ b/windows/test/data/046D_B010_0001_FF00.pp_data @@ -0,0 +1,139 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xB010 +dev->manufacturer_string = "Logitech" +dev->product_string = "Logitech Bluetooth Wireless Mouse" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0001 +dev->usage_page = 0xFF00 +dev->path = "\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002046d_pid&b010&col03#8&1cf1c1b9&3&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0xFF00 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 7 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 2 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 7 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 2 +pp_data->caps_info[2]->LastCap = 2 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x00D0 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF00 +pp_data->cap[0]->ReportID = 0x10 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 6 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 48 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0007 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFF00 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0001 +pp_data->cap[0]->NotRange.Reserved1 = 0x0001 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[1]->UsagePage = 0xFF00 +pp_data->cap[1]->ReportID = 0x10 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 6 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 48 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0007 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFF00 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0001 +pp_data->cap[1]->NotRange.Reserved1 = 0x0001 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 0 +pp_data->cap[1]->NotRange.Reserved4 = 0 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_B010_0001_FF00_expected.rpt_desc b/windows/test/data/046D_B010_0001_FF00_expected.rpt_desc new file mode 100644 index 000000000..812bd2a8f --- /dev/null +++ b/windows/test/data/046D_B010_0001_FF00_expected.rpt_desc @@ -0,0 +1,4 @@ +0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x10, 0x09, +0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x06, +0x81, 0x00, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x06, 0x91, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_B010_0001_FF00_real.rpt_desc b/windows/test/data/046D_B010_0001_FF00_real.rpt_desc new file mode 100644 index 000000000..340d08dae --- /dev/null +++ b/windows/test/data/046D_B010_0001_FF00_real.rpt_desc @@ -0,0 +1,39 @@ + +mac-hid-dump on  main ❯ ./mac-hid-dump +mac-hid-dump: +... +046D B010: Unknown - Bluetooth Mouse M557 +DESCRIPTOR: + 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 + 29 08 15 00 25 01 75 01 95 08 81 02 05 01 09 30 + 09 31 16 01 f8 26 ff 07 75 0c 95 02 81 06 09 38 + 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 75 + 08 95 01 81 06 c0 c0 05 0c 09 01 a1 01 85 03 05 + 06 09 20 15 00 26 64 00 75 08 95 01 81 02 c0 06 + 00 ff 09 01 a1 01 85 10 75 08 95 06 15 00 26 ff + 00 09 01 81 00 09 01 91 00 c0 06 00 ff 09 02 a1 + 01 85 11 75 08 95 13 15 00 26 ff 00 09 02 81 00 + 09 02 91 00 c0 05 01 09 06 a1 01 85 04 75 01 95 + 08 05 07 19 e0 29 e7 15 00 25 01 81 02 95 01 75 + 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 + 01 75 03 91 03 95 06 75 08 15 00 26 ff 00 05 07 + 19 00 29 ff 81 00 c0 05 0c 09 01 a1 01 85 05 15 + 00 25 01 75 01 95 02 0a 25 02 0a 24 02 81 02 95 + 01 75 06 81 03 c0 + (246 bytes) + +Parser output: + +0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) +0x09, 0x01, // Usage (0x01) +0xA1, 0x01, // Collection (Application) +0x85, 0x10, // Report ID (16) +0x75, 0x08, // Report Size (8) +0x95, 0x06, // Report Count (6) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0x00, // Logical Maximum (255) +0x09, 0x01, // Usage (0x01) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x09, 0x01, // Usage (0x01) +0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0xC0, // End Collection \ No newline at end of file diff --git a/windows/test/data/046D_B010_0002_0001.pp_data b/windows/test/data/046D_B010_0002_0001.pp_data new file mode 100644 index 000000000..1976766cd --- /dev/null +++ b/windows/test/data/046D_B010_0002_0001.pp_data @@ -0,0 +1,302 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xB010 +dev->manufacturer_string = "Logitech" +dev->product_string = "Logitech Bluetooth Wireless Mouse" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0002 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002046d_pid&b010&col01#8&1cf1c1b9&3&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 5 +pp_data->caps_info[0]->NumberOfCaps = 5 +pp_data->caps_info[0]->ReportByteLength = 7 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 5 +pp_data->caps_info[1]->LastCap = 5 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 5 +pp_data->caps_info[2]->LastCap = 5 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0208 +pp_data->NumberLinkCollectionNodes = 2 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0009 +pp_data->cap[0]->ReportID = 0x02 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 8 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0001 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x0001 +pp_data->cap[0]->Range.UsageMax = 0x0008 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 7 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x02 +pp_data->cap[1]->BitPosition = 4 +pp_data->cap[1]->BitSize = 12 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0003 +pp_data->cap[1]->BitCount = 12 +pp_data->cap[1]->BitField = 0x06 +pp_data->cap[1]->NextBytePosition = 0x0005 +pp_data->cap[1]->LinkCollection = 0x0001 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 0 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0031 +pp_data->cap[1]->NotRange.Reserved1 = 0x0031 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 8 +pp_data->cap[1]->NotRange.Reserved4 = 8 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = -2047 +pp_data->cap[1]->NotButton.LogicalMax = 2047 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x0001 +pp_data->cap[2]->ReportID = 0x02 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 12 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0002 +pp_data->cap[2]->BitCount = 12 +pp_data->cap[2]->BitField = 0x06 +pp_data->cap[2]->NextBytePosition = 0x0004 +pp_data->cap[2]->LinkCollection = 0x0001 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 0 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0030 +pp_data->cap[2]->NotRange.Reserved1 = 0x0030 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 9 +pp_data->cap[2]->NotRange.Reserved4 = 9 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = -2047 +pp_data->cap[2]->NotButton.LogicalMax = 2047 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0001 +pp_data->cap[3]->ReportID = 0x02 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 8 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0005 +pp_data->cap[3]->BitCount = 8 +pp_data->cap[3]->BitField = 0x06 +pp_data->cap[3]->NextBytePosition = 0x0006 +pp_data->cap[3]->LinkCollection = 0x0001 +pp_data->cap[3]->LinkUsagePage = 0x0001 +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 0 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0038 +pp_data->cap[3]->NotRange.Reserved1 = 0x0038 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 10 +pp_data->cap[3]->NotRange.Reserved4 = 10 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = -127 +pp_data->cap[3]->NotButton.LogicalMax = 127 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x000C +pp_data->cap[4]->ReportID = 0x02 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 8 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0006 +pp_data->cap[4]->BitCount = 8 +pp_data->cap[4]->BitField = 0x06 +pp_data->cap[4]->NextBytePosition = 0x0007 +pp_data->cap[4]->LinkCollection = 0x0001 +pp_data->cap[4]->LinkUsagePage = 0x0001 +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 0 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 0 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0238 +pp_data->cap[4]->NotRange.Reserved1 = 0x0238 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 11 +pp_data->cap[4]->NotRange.Reserved4 = 11 +pp_data->cap[4]->NotButton.HasNull = 0 +pp_data->cap[4]->NotButton.Reserved4 = 0x000000 +pp_data->cap[4]->NotButton.LogicalMin = -127 +pp_data->cap[4]->NotButton.LogicalMax = 127 +pp_data->cap[4]->NotButton.PhysicalMin = 0 +pp_data->cap[4]->NotButton.PhysicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 1 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 1 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 0 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_B010_0002_0001_expected.rpt_desc b/windows/test/data/046D_B010_0002_0001_expected.rpt_desc new file mode 100644 index 000000000..d782fa173 --- /dev/null +++ b/windows/test/data/046D_B010_0002_0001_expected.rpt_desc @@ -0,0 +1,8 @@ +0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, +0x85, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29, 0x08, 0x15, 0x00, +0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x05, 0x01, +0x09, 0x30, 0x09, 0x31, 0x16, 0x01, 0xF8, 0x26, 0xFF, 0x07, +0x75, 0x0C, 0x95, 0x02, 0x81, 0x06, 0x09, 0x38, 0x15, 0x81, +0x25, 0x7F, 0x75, 0x08, 0x95, 0x01, 0x81, 0x06, 0x05, 0x0C, +0x0A, 0x38, 0x02, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, +0x01, 0x81, 0x06, 0xC0, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_B010_0002_0001_real.rpt_desc b/windows/test/data/046D_B010_0002_0001_real.rpt_desc new file mode 100644 index 000000000..483f659d6 --- /dev/null +++ b/windows/test/data/046D_B010_0002_0001_real.rpt_desc @@ -0,0 +1,61 @@ + +mac-hid-dump on  main ❯ ./mac-hid-dump +mac-hid-dump: +... +046D B010: Unknown - Bluetooth Mouse M557 +DESCRIPTOR: + 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 + 29 08 15 00 25 01 75 01 95 08 81 02 05 01 09 30 + 09 31 16 01 f8 26 ff 07 75 0c 95 02 81 06 09 38 + 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 75 + 08 95 01 81 06 c0 c0 05 0c 09 01 a1 01 85 03 05 + 06 09 20 15 00 26 64 00 75 08 95 01 81 02 c0 06 + 00 ff 09 01 a1 01 85 10 75 08 95 06 15 00 26 ff + 00 09 01 81 00 09 01 91 00 c0 06 00 ff 09 02 a1 + 01 85 11 75 08 95 13 15 00 26 ff 00 09 02 81 00 + 09 02 91 00 c0 05 01 09 06 a1 01 85 04 75 01 95 + 08 05 07 19 e0 29 e7 15 00 25 01 81 02 95 01 75 + 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 + 01 75 03 91 03 95 06 75 08 15 00 26 ff 00 05 07 + 19 00 29 ff 81 00 c0 05 0c 09 01 a1 01 85 05 15 + 00 25 01 75 01 95 02 0a 25 02 0a 24 02 81 02 95 + 01 75 06 81 03 c0 + (246 bytes) + +Parser output: + +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x02, // Usage (Mouse) +0xA1, 0x01, // Collection (Application) +0x85, 0x02, // Report ID (2) +0x09, 0x01, // Usage (Pointer) +0xA1, 0x00, // Collection (Physical) +0x05, 0x09, // Usage Page (Button) +0x19, 0x01, // Usage Minimum (0x01) +0x29, 0x08, // Usage Maximum (0x08) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x75, 0x01, // Report Size (1) +0x95, 0x08, // Report Count (8) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x30, // Usage (X) +0x09, 0x31, // Usage (Y) +0x16, 0x01, 0xF8, // Logical Minimum (-2047) +0x26, 0xFF, 0x07, // Logical Maximum (2047) +0x75, 0x0C, // Report Size (12) +0x95, 0x02, // Report Count (2) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x09, 0x38, // Usage (Wheel) +0x15, 0x81, // Logical Minimum (-127) +0x25, 0x7F, // Logical Maximum (127) +0x75, 0x08, // Report Size (8) +0x95, 0x01, // Report Count (1) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x05, 0x0C, // Usage Page (Consumer) +0x0A, 0x38, 0x02, // Usage (AC Pan) +0x75, 0x08, // Report Size (8) +0x95, 0x01, // Report Count (1) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection +0xC0, // End Collection diff --git a/windows/test/data/046D_B010_0002_FF00.pp_data b/windows/test/data/046D_B010_0002_FF00.pp_data new file mode 100644 index 000000000..0dc64b254 --- /dev/null +++ b/windows/test/data/046D_B010_0002_FF00.pp_data @@ -0,0 +1,139 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xB010 +dev->manufacturer_string = "Logitech" +dev->product_string = "Logitech Bluetooth Wireless Mouse" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0002 +dev->usage_page = 0xFF00 +dev->path = "\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002046d_pid&b010&col04#8&1cf1c1b9&3&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0xFF00 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 20 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 2 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 20 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 2 +pp_data->caps_info[2]->LastCap = 2 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x00D0 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF00 +pp_data->cap[0]->ReportID = 0x11 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 19 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 152 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0014 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFF00 +pp_data->cap[0]->LinkUsage = 0x0002 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0002 +pp_data->cap[0]->NotRange.Reserved1 = 0x0002 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[1]->UsagePage = 0xFF00 +pp_data->cap[1]->ReportID = 0x11 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 19 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 152 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0014 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFF00 +pp_data->cap[1]->LinkUsage = 0x0002 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0002 +pp_data->cap[1]->NotRange.Reserved1 = 0x0002 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 0 +pp_data->cap[1]->NotRange.Reserved4 = 0 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_B010_0002_FF00_expected.rpt_desc b/windows/test/data/046D_B010_0002_FF00_expected.rpt_desc new file mode 100644 index 000000000..b1654e78c --- /dev/null +++ b/windows/test/data/046D_B010_0002_FF00_expected.rpt_desc @@ -0,0 +1,4 @@ +0x06, 0x00, 0xFF, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x11, 0x09, +0x02, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x13, +0x81, 0x00, 0x09, 0x02, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x13, 0x91, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_B010_0002_FF00_real.rpt_desc b/windows/test/data/046D_B010_0002_FF00_real.rpt_desc new file mode 100644 index 000000000..8b8dbfcc2 --- /dev/null +++ b/windows/test/data/046D_B010_0002_FF00_real.rpt_desc @@ -0,0 +1,39 @@ + +mac-hid-dump on  main ❯ ./mac-hid-dump +mac-hid-dump: +... +046D B010: Unknown - Bluetooth Mouse M557 +DESCRIPTOR: + 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 + 29 08 15 00 25 01 75 01 95 08 81 02 05 01 09 30 + 09 31 16 01 f8 26 ff 07 75 0c 95 02 81 06 09 38 + 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 75 + 08 95 01 81 06 c0 c0 05 0c 09 01 a1 01 85 03 05 + 06 09 20 15 00 26 64 00 75 08 95 01 81 02 c0 06 + 00 ff 09 01 a1 01 85 10 75 08 95 06 15 00 26 ff + 00 09 01 81 00 09 01 91 00 c0 06 00 ff 09 02 a1 + 01 85 11 75 08 95 13 15 00 26 ff 00 09 02 81 00 + 09 02 91 00 c0 05 01 09 06 a1 01 85 04 75 01 95 + 08 05 07 19 e0 29 e7 15 00 25 01 81 02 95 01 75 + 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 + 01 75 03 91 03 95 06 75 08 15 00 26 ff 00 05 07 + 19 00 29 ff 81 00 c0 05 0c 09 01 a1 01 85 05 15 + 00 25 01 75 01 95 02 0a 25 02 0a 24 02 81 02 95 + 01 75 06 81 03 c0 + (246 bytes) + +Parser output: + +0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) +0x09, 0x02, // Usage (0x02) +0xA1, 0x01, // Collection (Application) +0x85, 0x11, // Report ID (17) +0x75, 0x08, // Report Size (8) +0x95, 0x13, // Report Count (19) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0x00, // Logical Maximum (255) +0x09, 0x02, // Usage (0x02) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x09, 0x02, // Usage (0x02) +0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0xC0, // End Collection \ No newline at end of file diff --git a/windows/test/data/046D_B010_0006_0001.pp_data b/windows/test/data/046D_B010_0006_0001.pp_data new file mode 100644 index 000000000..7682a0d20 --- /dev/null +++ b/windows/test/data/046D_B010_0006_0001.pp_data @@ -0,0 +1,185 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xB010 +dev->manufacturer_string = "Logitech" +dev->product_string = "Logitech Bluetooth Wireless Mouse" +dev->release_number = 0x0000 +dev->interface_number = -1 +dev->usage = 0x0006 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#{00001124-0000-1000-8000-00805f9b34fb}_vid&0002046d_pid&b010&col05#8&1cf1c1b9&3&0004#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0006 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 2 +pp_data->caps_info[0]->NumberOfCaps = 2 +pp_data->caps_info[0]->ReportByteLength = 9 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 2 +pp_data->caps_info[1]->LastCap = 3 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 2 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 3 +pp_data->caps_info[2]->LastCap = 3 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0138 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0007 +pp_data->cap[0]->ReportID = 0x04 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 8 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0006 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x00E0 +pp_data->cap[0]->Range.UsageMax = 0x00E7 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 7 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0007 +pp_data->cap[1]->ReportID = 0x04 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 6 +pp_data->cap[1]->BytePosition = 0x0003 +pp_data->cap[1]->BitCount = 48 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0009 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0006 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 1 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->Range.UsageMin = 0x0000 +pp_data->cap[1]->Range.UsageMax = 0x00FF +pp_data->cap[1]->Range.StringMin = 0 +pp_data->cap[1]->Range.StringMax = 0 +pp_data->cap[1]->Range.DesignatorMin = 0 +pp_data->cap[1]->Range.DesignatorMax = 0 +pp_data->cap[1]->Range.DataIndexMin = 8 +pp_data->cap[1]->Range.DataIndexMax = 263 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[2]->UsagePage = 0x0008 +pp_data->cap[2]->ReportID = 0x04 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 5 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 5 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0006 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 1 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->Range.UsageMin = 0x0001 +pp_data->cap[2]->Range.UsageMax = 0x0005 +pp_data->cap[2]->Range.StringMin = 0 +pp_data->cap[2]->Range.StringMax = 0 +pp_data->cap[2]->Range.DesignatorMin = 0 +pp_data->cap[2]->Range.DesignatorMax = 0 +pp_data->cap[2]->Range.DataIndexMin = 0 +pp_data->cap[2]->Range.DataIndexMax = 4 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0006 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_B010_0006_0001_expected.rpt_desc b/windows/test/data/046D_B010_0006_0001_expected.rpt_desc new file mode 100644 index 000000000..1ec0b16e1 --- /dev/null +++ b/windows/test/data/046D_B010_0006_0001_expected.rpt_desc @@ -0,0 +1,7 @@ +0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x85, 0x04, 0x05, 0x07, +0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, +0x95, 0x08, 0x81, 0x02, 0x75, 0x08, 0x95, 0x01, 0x81, 0x03, +0x19, 0x00, 0x29, 0xFF, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x06, 0x81, 0x00, 0x05, 0x08, 0x19, 0x01, 0x29, +0x05, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x05, 0x91, +0x02, 0x75, 0x03, 0x95, 0x01, 0x91, 0x03, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_B010_0006_0001_real.rpt_desc b/windows/test/data/046D_B010_0006_0001_real.rpt_desc new file mode 100644 index 000000000..59ab03d1b --- /dev/null +++ b/windows/test/data/046D_B010_0006_0001_real.rpt_desc @@ -0,0 +1,58 @@ + +mac-hid-dump on  main ❯ ./mac-hid-dump +mac-hid-dump: +... +046D B010: Unknown - Bluetooth Mouse M557 +DESCRIPTOR: + 05 01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 + 29 08 15 00 25 01 75 01 95 08 81 02 05 01 09 30 + 09 31 16 01 f8 26 ff 07 75 0c 95 02 81 06 09 38 + 15 81 25 7f 75 08 95 01 81 06 05 0c 0a 38 02 75 + 08 95 01 81 06 c0 c0 05 0c 09 01 a1 01 85 03 05 + 06 09 20 15 00 26 64 00 75 08 95 01 81 02 c0 06 + 00 ff 09 01 a1 01 85 10 75 08 95 06 15 00 26 ff + 00 09 01 81 00 09 01 91 00 c0 06 00 ff 09 02 a1 + 01 85 11 75 08 95 13 15 00 26 ff 00 09 02 81 00 + 09 02 91 00 c0 05 01 09 06 a1 01 85 04 75 01 95 + 08 05 07 19 e0 29 e7 15 00 25 01 81 02 95 01 75 + 08 81 03 95 05 75 01 05 08 19 01 29 05 91 02 95 + 01 75 03 91 03 95 06 75 08 15 00 26 ff 00 05 07 + 19 00 29 ff 81 00 c0 05 0c 09 01 a1 01 85 05 15 + 00 25 01 75 01 95 02 0a 25 02 0a 24 02 81 02 95 + 01 75 06 81 03 c0 + (246 bytes) + +Parser output: +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x06, // Usage (Keyboard) +0xA1, 0x01, // Collection (Application) +0x85, 0x04, // Report ID (4) +0x75, 0x01, // Report Size (1) +0x95, 0x08, // Report Count (8) +0x05, 0x07, // Usage Page (Kbrd/Keypad) +0x19, 0xE0, // Usage Minimum (0xE0) +0x29, 0xE7, // Usage Maximum (0xE7) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x95, 0x01, // Report Count (1) +0x75, 0x08, // Report Size (8) +0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x95, 0x05, // Report Count (5) +0x75, 0x01, // Report Size (1) +0x05, 0x08, // Usage Page (LEDs) +0x19, 0x01, // Usage Minimum (Num Lock) +0x29, 0x05, // Usage Maximum (Kana) +0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x95, 0x01, // Report Count (1) +0x75, 0x03, // Report Size (3) +0x91, 0x03, // Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x95, 0x06, // Report Count (6) +0x75, 0x08, // Report Size (8) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0x00, // Logical Maximum (255) +0x05, 0x07, // Usage Page (Kbrd/Keypad) +0x19, 0x00, // Usage Minimum (0x00) +0x29, 0xFF, // Usage Maximum (0xFF) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection \ No newline at end of file diff --git a/windows/test/data/046D_C077_0002_0001.pp_data b/windows/test/data/046D_C077_0002_0001.pp_data new file mode 100644 index 000000000..3e9fcea81 --- /dev/null +++ b/windows/test/data/046D_C077_0002_0001.pp_data @@ -0,0 +1,252 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC077 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Optical Mouse" +dev->release_number = 0x7200 +dev->interface_number = -1 +dev->usage = 0x0002 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046d&pid_c077#7&1875dbae&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 4 +pp_data->caps_info[0]->NumberOfCaps = 4 +pp_data->caps_info[0]->ReportByteLength = 5 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 4 +pp_data->caps_info[1]->LastCap = 4 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 4 +pp_data->caps_info[2]->LastCap = 4 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x01A0 +pp_data->NumberLinkCollectionNodes = 2 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0009 +pp_data->cap[0]->ReportID = 0x00 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 8 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0001 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x0001 +pp_data->cap[0]->Range.UsageMax = 0x0003 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 2 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x00 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0004 +pp_data->cap[1]->BitCount = 8 +pp_data->cap[1]->BitField = 0x06 +pp_data->cap[1]->NextBytePosition = 0x0005 +pp_data->cap[1]->LinkCollection = 0x0001 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 0 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0038 +pp_data->cap[1]->NotRange.Reserved1 = 0x0038 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 3 +pp_data->cap[1]->NotRange.Reserved4 = 3 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = -127 +pp_data->cap[1]->NotButton.LogicalMax = 127 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x0001 +pp_data->cap[2]->ReportID = 0x00 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 8 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0003 +pp_data->cap[2]->BitCount = 8 +pp_data->cap[2]->BitField = 0x06 +pp_data->cap[2]->NextBytePosition = 0x0004 +pp_data->cap[2]->LinkCollection = 0x0001 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 0 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0031 +pp_data->cap[2]->NotRange.Reserved1 = 0x0031 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 4 +pp_data->cap[2]->NotRange.Reserved4 = 4 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = -127 +pp_data->cap[2]->NotButton.LogicalMax = 127 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0001 +pp_data->cap[3]->ReportID = 0x00 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 8 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0002 +pp_data->cap[3]->BitCount = 8 +pp_data->cap[3]->BitField = 0x06 +pp_data->cap[3]->NextBytePosition = 0x0003 +pp_data->cap[3]->LinkCollection = 0x0001 +pp_data->cap[3]->LinkUsagePage = 0x0001 +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 0 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0030 +pp_data->cap[3]->NotRange.Reserved1 = 0x0030 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 5 +pp_data->cap[3]->NotRange.Reserved4 = 5 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = -127 +pp_data->cap[3]->NotButton.LogicalMax = 127 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 1 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 1 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 0 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C077_0002_0001_expected.rpt_desc b/windows/test/data/046D_C077_0002_0001_expected.rpt_desc new file mode 100644 index 000000000..7e144b4bc --- /dev/null +++ b/windows/test/data/046D_C077_0002_0001_expected.rpt_desc @@ -0,0 +1,5 @@ +0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, +0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, +0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, +0x95, 0x03, 0x81, 0x06, 0xC0, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C077_0002_0001_real.rpt_desc b/windows/test/data/046D_C077_0002_0001_real.rpt_desc new file mode 100644 index 000000000..7604c55bc --- /dev/null +++ b/windows/test/data/046D_C077_0002_0001_real.rpt_desc @@ -0,0 +1,24 @@ +Usage Page (Generic Desktop) 05 01 +Usage (Mouse) 09 02 +Collection (Application) A1 01 + Usage (Pointer) 09 01 + Collection (Physical) A1 00 + Usage Page (Button) 05 09 + Usage Minimum (Button 1) 19 01 + Usage Maximum (Button 3) 29 03 + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Report Count (8) 95 08 + Report Size (1) 75 01 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Usage Page (Generic Desktop) 05 01 + Usage (X) 09 30 + Usage (Y) 09 31 + Usage (Wheel) 09 38 + Logical Minimum (-127) 15 81 + Logical Maximum (127) 25 7F + Report Size (8) 75 08 + Report Count (3) 95 03 + Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 81 06 + End Collection C0 +End Collection C0 diff --git a/windows/test/data/046D_C283_0004_0001.pp_data b/windows/test/data/046D_C283_0004_0001.pp_data new file mode 100644 index 000000000..0f70d06ff --- /dev/null +++ b/windows/test/data/046D_C283_0004_0001.pp_data @@ -0,0 +1,520 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC283 +dev->manufacturer_string = "Logitech Inc." +dev->product_string = "WingMan Force 3D" +dev->release_number = 0x0106 +dev->interface_number = -1 +dev->usage = 0x0004 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046d&pid_c283#7&d7fb4bf&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0004 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 8 +pp_data->caps_info[0]->NumberOfCaps = 8 +pp_data->caps_info[0]->ReportByteLength = 8 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 8 +pp_data->caps_info[1]->LastCap = 9 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 9 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 9 +pp_data->caps_info[2]->LastCap = 9 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x03A8 +pp_data->NumberLinkCollectionNodes = 4 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0001 +pp_data->cap[0]->ReportID = 0x00 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0002 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0003 +pp_data->cap[0]->LinkCollection = 0x0002 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 0 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0031 +pp_data->cap[0]->NotRange.Reserved1 = 0x0031 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->NotButton.HasNull = 0 +pp_data->cap[0]->NotButton.Reserved4 = 0x000000 +pp_data->cap[0]->NotButton.LogicalMin = 0 +pp_data->cap[0]->NotButton.LogicalMax = 255 +pp_data->cap[0]->NotButton.PhysicalMin = 0 +pp_data->cap[0]->NotButton.PhysicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x00 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 8 +pp_data->cap[1]->BitField = 0x02 +pp_data->cap[1]->NextBytePosition = 0x0002 +pp_data->cap[1]->LinkCollection = 0x0002 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0030 +pp_data->cap[1]->NotRange.Reserved1 = 0x0030 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = 0 +pp_data->cap[1]->NotButton.LogicalMax = 255 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0xFF00 +pp_data->cap[2]->ReportID = 0x00 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 4 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0003 +pp_data->cap[2]->BitCount = 4 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0004 +pp_data->cap[2]->LinkCollection = 0x0002 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0001 +pp_data->cap[2]->NotRange.Reserved1 = 0x0001 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = 0 +pp_data->cap[2]->NotButton.LogicalMax = 15 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = 255 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0001 +pp_data->cap[3]->ReportID = 0x00 +pp_data->cap[3]->BitPosition = 4 +pp_data->cap[3]->BitSize = 4 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0003 +pp_data->cap[3]->BitCount = 4 +pp_data->cap[3]->BitField = 0x42 +pp_data->cap[3]->NextBytePosition = 0x0004 +pp_data->cap[3]->LinkCollection = 0x0002 +pp_data->cap[3]->LinkUsagePage = 0x0001 +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 1 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0039 +pp_data->cap[3]->NotRange.Reserved1 = 0x0039 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 3 +pp_data->cap[3]->NotRange.Reserved4 = 3 +pp_data->cap[3]->NotButton.HasNull = 1 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = 0 +pp_data->cap[3]->NotButton.LogicalMax = 7 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 315 +pp_data->cap[3]->Units = 20 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x0001 +pp_data->cap[4]->ReportID = 0x00 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 8 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0004 +pp_data->cap[4]->BitCount = 8 +pp_data->cap[4]->BitField = 0x02 +pp_data->cap[4]->NextBytePosition = 0x0005 +pp_data->cap[4]->LinkCollection = 0x0002 +pp_data->cap[4]->LinkUsagePage = 0x0001 +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 0 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 1 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0035 +pp_data->cap[4]->NotRange.Reserved1 = 0x0035 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 4 +pp_data->cap[4]->NotRange.Reserved4 = 4 +pp_data->cap[4]->NotButton.HasNull = 0 +pp_data->cap[4]->NotButton.Reserved4 = 0x000000 +pp_data->cap[4]->NotButton.LogicalMin = 0 +pp_data->cap[4]->NotButton.LogicalMax = 255 +pp_data->cap[4]->NotButton.PhysicalMin = 0 +pp_data->cap[4]->NotButton.PhysicalMax = 255 +pp_data->cap[4]->Units = 20 +pp_data->cap[4]->UnitsExp = 0 + +pp_data->cap[5]->UsagePage = 0x0009 +pp_data->cap[5]->ReportID = 0x00 +pp_data->cap[5]->BitPosition = 0 +pp_data->cap[5]->BitSize = 1 +pp_data->cap[5]->ReportCount = 7 +pp_data->cap[5]->BytePosition = 0x0005 +pp_data->cap[5]->BitCount = 7 +pp_data->cap[5]->BitField = 0x02 +pp_data->cap[5]->NextBytePosition = 0x0006 +pp_data->cap[5]->LinkCollection = 0x0001 +pp_data->cap[5]->LinkUsagePage = 0x0001 +pp_data->cap[5]->LinkUsage = 0x0000 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 1 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 1 +pp_data->cap[5]->IsRange = 1 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->Range.UsageMin = 0x0001 +pp_data->cap[5]->Range.UsageMax = 0x0007 +pp_data->cap[5]->Range.StringMin = 0 +pp_data->cap[5]->Range.StringMax = 0 +pp_data->cap[5]->Range.DesignatorMin = 0 +pp_data->cap[5]->Range.DesignatorMax = 0 +pp_data->cap[5]->Range.DataIndexMin = 5 +pp_data->cap[5]->Range.DataIndexMax = 11 +pp_data->cap[5]->Button.LogicalMin = 0 +pp_data->cap[5]->Button.LogicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0x0001 +pp_data->cap[6]->ReportID = 0x00 +pp_data->cap[6]->BitPosition = 0 +pp_data->cap[6]->BitSize = 8 +pp_data->cap[6]->ReportCount = 1 +pp_data->cap[6]->BytePosition = 0x0006 +pp_data->cap[6]->BitCount = 8 +pp_data->cap[6]->BitField = 0x02 +pp_data->cap[6]->NextBytePosition = 0x0007 +pp_data->cap[6]->LinkCollection = 0x0001 +pp_data->cap[6]->LinkUsagePage = 0x0001 +pp_data->cap[6]->LinkUsage = 0x0000 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 0 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x0036 +pp_data->cap[6]->NotRange.Reserved1 = 0x0036 +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 12 +pp_data->cap[6]->NotRange.Reserved4 = 12 +pp_data->cap[6]->NotButton.HasNull = 0 +pp_data->cap[6]->NotButton.Reserved4 = 0x000000 +pp_data->cap[6]->NotButton.LogicalMin = 0 +pp_data->cap[6]->NotButton.LogicalMax = 255 +pp_data->cap[6]->NotButton.PhysicalMin = 0 +pp_data->cap[6]->NotButton.PhysicalMax = 255 +pp_data->cap[6]->Units = 0 +pp_data->cap[6]->UnitsExp = 0 + +pp_data->cap[7]->UsagePage = 0xFF00 +pp_data->cap[7]->ReportID = 0x00 +pp_data->cap[7]->BitPosition = 0 +pp_data->cap[7]->BitSize = 8 +pp_data->cap[7]->ReportCount = 1 +pp_data->cap[7]->BytePosition = 0x0007 +pp_data->cap[7]->BitCount = 8 +pp_data->cap[7]->BitField = 0x02 +pp_data->cap[7]->NextBytePosition = 0x0008 +pp_data->cap[7]->LinkCollection = 0x0001 +pp_data->cap[7]->LinkUsagePage = 0x0001 +pp_data->cap[7]->LinkUsage = 0x0000 +pp_data->cap[7]->IsMultipleItemsForArray = 0 +pp_data->cap[7]->IsButtonCap = 0 +pp_data->cap[7]->IsPadding = 0 +pp_data->cap[7]->IsAbsolute = 1 +pp_data->cap[7]->IsRange = 0 +pp_data->cap[7]->IsAlias = 0 +pp_data->cap[7]->IsStringRange = 0 +pp_data->cap[7]->IsDesignatorRange = 0 +pp_data->cap[7]->Reserved1 = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[7]->NotRange.Usage = 0x0001 +pp_data->cap[7]->NotRange.Reserved1 = 0x0001 +pp_data->cap[7]->NotRange.StringIndex = 0 +pp_data->cap[7]->NotRange.Reserved2 = 0 +pp_data->cap[7]->NotRange.DesignatorIndex = 0 +pp_data->cap[7]->NotRange.Reserved3 = 0 +pp_data->cap[7]->NotRange.DataIndex = 13 +pp_data->cap[7]->NotRange.Reserved4 = 13 +pp_data->cap[7]->NotButton.HasNull = 0 +pp_data->cap[7]->NotButton.Reserved4 = 0x000000 +pp_data->cap[7]->NotButton.LogicalMin = 0 +pp_data->cap[7]->NotButton.LogicalMax = 255 +pp_data->cap[7]->NotButton.PhysicalMin = 0 +pp_data->cap[7]->NotButton.PhysicalMax = 255 +pp_data->cap[7]->Units = 0 +pp_data->cap[7]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[8]->UsagePage = 0xFF00 +pp_data->cap[8]->ReportID = 0x00 +pp_data->cap[8]->BitPosition = 0 +pp_data->cap[8]->BitSize = 8 +pp_data->cap[8]->ReportCount = 8 +pp_data->cap[8]->BytePosition = 0x0001 +pp_data->cap[8]->BitCount = 64 +pp_data->cap[8]->BitField = 0x02 +pp_data->cap[8]->NextBytePosition = 0x0009 +pp_data->cap[8]->LinkCollection = 0x0003 +pp_data->cap[8]->LinkUsagePage = 0xFF00 +pp_data->cap[8]->LinkUsage = 0x0000 +pp_data->cap[8]->IsMultipleItemsForArray = 0 +pp_data->cap[8]->IsButtonCap = 0 +pp_data->cap[8]->IsPadding = 0 +pp_data->cap[8]->IsAbsolute = 1 +pp_data->cap[8]->IsRange = 0 +pp_data->cap[8]->IsAlias = 0 +pp_data->cap[8]->IsStringRange = 0 +pp_data->cap[8]->IsDesignatorRange = 0 +pp_data->cap[8]->Reserved1 = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[8]->NotRange.Usage = 0x0002 +pp_data->cap[8]->NotRange.Reserved1 = 0x0002 +pp_data->cap[8]->NotRange.StringIndex = 0 +pp_data->cap[8]->NotRange.Reserved2 = 0 +pp_data->cap[8]->NotRange.DesignatorIndex = 0 +pp_data->cap[8]->NotRange.Reserved3 = 0 +pp_data->cap[8]->NotRange.DataIndex = 0 +pp_data->cap[8]->NotRange.Reserved4 = 0 +pp_data->cap[8]->NotButton.HasNull = 0 +pp_data->cap[8]->NotButton.Reserved4 = 0x000000 +pp_data->cap[8]->NotButton.LogicalMin = 0 +pp_data->cap[8]->NotButton.LogicalMax = 255 +pp_data->cap[8]->NotButton.PhysicalMin = 0 +pp_data->cap[8]->NotButton.PhysicalMax = 255 +pp_data->cap[8]->Units = 0 +pp_data->cap[8]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0004 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 2 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 3 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0000 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 1 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 2 +pp_data->LinkCollectionArray[1]->CollectionType = 2 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[2]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[2]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[2]->Parent = 1 +pp_data->LinkCollectionArray[2]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[2]->NextSibling = 0 +pp_data->LinkCollectionArray[2]->FirstChild = 0 +pp_data->LinkCollectionArray[2]->CollectionType = 0 +pp_data->LinkCollectionArray[2]->IsAlias = 0 +pp_data->LinkCollectionArray[2]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[3]->LinkUsage = 0x0000 +pp_data->LinkCollectionArray[3]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[3]->Parent = 0 +pp_data->LinkCollectionArray[3]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[3]->NextSibling = 1 +pp_data->LinkCollectionArray[3]->FirstChild = 0 +pp_data->LinkCollectionArray[3]->CollectionType = 2 +pp_data->LinkCollectionArray[3]->IsAlias = 0 +pp_data->LinkCollectionArray[3]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C283_0004_0001_expected.rpt_desc b/windows/test/data/046D_C283_0004_0001_expected.rpt_desc new file mode 100644 index 000000000..fca719a7d --- /dev/null +++ b/windows/test/data/046D_C283_0004_0001_expected.rpt_desc @@ -0,0 +1,18 @@ +0x05, 0x01, 0x09, 0x04, 0xA1, 0x01, 0x09, 0x00, 0xA1, 0x02, +0x09, 0x01, 0xA1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x15, 0x00, +0x26, 0xFF, 0x00, 0x35, 0x00, 0x46, 0xFF, 0x00, 0x75, 0x08, +0x95, 0x02, 0x81, 0x02, 0x06, 0x00, 0xFF, 0x09, 0x01, 0x15, +0x00, 0x25, 0x0F, 0x75, 0x04, 0x95, 0x01, 0x81, 0x02, 0x05, +0x01, 0x09, 0x39, 0x15, 0x00, 0x25, 0x07, 0x35, 0x00, 0x46, +0x3B, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, +0x09, 0x35, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x35, 0x00, 0x46, +0xFF, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81, 0x02, 0xC0, 0x05, +0x09, 0x19, 0x01, 0x29, 0x07, 0x15, 0x00, 0x25, 0x01, 0x75, +0x01, 0x95, 0x07, 0x45, 0x00, 0x65, 0x00, 0x81, 0x02, 0x75, +0x01, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x36, 0x15, +0x00, 0x26, 0xFF, 0x00, 0x35, 0x00, 0x46, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x01, 0x81, 0x02, 0x06, 0x00, 0xFF, 0x09, 0x01, +0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81, +0x02, 0xC0, 0x09, 0x00, 0xA1, 0x02, 0x09, 0x02, 0x15, 0x00, +0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x08, 0x91, 0x02, 0xC0, +0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C283_0004_0001_real.rpt_desc b/windows/test/data/046D_C283_0004_0001_real.rpt_desc new file mode 100644 index 000000000..fca719a7d --- /dev/null +++ b/windows/test/data/046D_C283_0004_0001_real.rpt_desc @@ -0,0 +1,18 @@ +0x05, 0x01, 0x09, 0x04, 0xA1, 0x01, 0x09, 0x00, 0xA1, 0x02, +0x09, 0x01, 0xA1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x15, 0x00, +0x26, 0xFF, 0x00, 0x35, 0x00, 0x46, 0xFF, 0x00, 0x75, 0x08, +0x95, 0x02, 0x81, 0x02, 0x06, 0x00, 0xFF, 0x09, 0x01, 0x15, +0x00, 0x25, 0x0F, 0x75, 0x04, 0x95, 0x01, 0x81, 0x02, 0x05, +0x01, 0x09, 0x39, 0x15, 0x00, 0x25, 0x07, 0x35, 0x00, 0x46, +0x3B, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, +0x09, 0x35, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x35, 0x00, 0x46, +0xFF, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81, 0x02, 0xC0, 0x05, +0x09, 0x19, 0x01, 0x29, 0x07, 0x15, 0x00, 0x25, 0x01, 0x75, +0x01, 0x95, 0x07, 0x45, 0x00, 0x65, 0x00, 0x81, 0x02, 0x75, +0x01, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x36, 0x15, +0x00, 0x26, 0xFF, 0x00, 0x35, 0x00, 0x46, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x01, 0x81, 0x02, 0x06, 0x00, 0xFF, 0x09, 0x01, +0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81, +0x02, 0xC0, 0x09, 0x00, 0xA1, 0x02, 0x09, 0x02, 0x15, 0x00, +0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x08, 0x91, 0x02, 0xC0, +0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C52F_0001_000C.pp_data b/windows/test/data/046D_C52F_0001_000C.pp_data new file mode 100644 index 000000000..7f6b369fe --- /dev/null +++ b/windows/test/data/046D_C52F_0001_000C.pp_data @@ -0,0 +1,93 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC52F +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2200 +dev->interface_number = 1 +dev->usage = 0x0001 +dev->usage_page = 0x000C +dev->path = "\\?\hid#vid_046d&pid_c52f&mi_01&col01#8&28ca146b&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0x000C +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 5 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 1 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 1 +pp_data->caps_info[2]->LastCap = 1 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0068 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x000C +pp_data->cap[0]->ReportID = 0x03 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 16 +pp_data->cap[0]->ReportCount = 2 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 32 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0005 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000C +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x0001 +pp_data->cap[0]->Range.UsageMax = 0x028C +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 651 +pp_data->cap[0]->Button.LogicalMin = 1 +pp_data->cap[0]->Button.LogicalMax = 652 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C52F_0001_000C_expected.rpt_desc b/windows/test/data/046D_C52F_0001_000C_expected.rpt_desc new file mode 100644 index 000000000..85953ae47 --- /dev/null +++ b/windows/test/data/046D_C52F_0001_000C_expected.rpt_desc @@ -0,0 +1,3 @@ +0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x03, 0x19, 0x01, +0x2A, 0x8C, 0x02, 0x15, 0x01, 0x26, 0x8C, 0x02, 0x75, 0x10, +0x95, 0x02, 0x81, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C52F_0001_000C_real.rpt_desc b/windows/test/data/046D_C52F_0001_000C_real.rpt_desc new file mode 100644 index 000000000..280e58f44 --- /dev/null +++ b/windows/test/data/046D_C52F_0001_000C_real.rpt_desc @@ -0,0 +1,12 @@ +Usage Page (Consumer Devices) 05 0C +Usage (Consumer Control) 09 01 +Collection (Application) A1 01 + Report ID (3) 85 03 + Report Size (16) 75 10 + Report Count (2) 95 02 + Logical Minimum (1) 15 01 + Logical Maximum (652) 26 8C 02 + Usage Minimum (Consumer Control) 19 01 + Usage Maximum (AC Send) 2A 8C 02 + Input (Data,Ary,Abs) 81 00 +End Collection C0 diff --git a/windows/test/data/046D_C52F_0001_FF00.pp_data b/windows/test/data/046D_C52F_0001_FF00.pp_data new file mode 100644 index 000000000..5e8ece103 --- /dev/null +++ b/windows/test/data/046D_C52F_0001_FF00.pp_data @@ -0,0 +1,139 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC52F +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2200 +dev->interface_number = 1 +dev->usage = 0x0001 +dev->usage_page = 0xFF00 +dev->path = "\\?\hid#vid_046d&pid_c52f&mi_01&col02#8&28ca146b&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0xFF00 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 7 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 2 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 7 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 2 +pp_data->caps_info[2]->LastCap = 2 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x00D0 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF00 +pp_data->cap[0]->ReportID = 0x10 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 6 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 48 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0007 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFF00 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0001 +pp_data->cap[0]->NotRange.Reserved1 = 0x0001 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[1]->UsagePage = 0xFF00 +pp_data->cap[1]->ReportID = 0x10 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 6 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 48 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0007 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFF00 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0001 +pp_data->cap[1]->NotRange.Reserved1 = 0x0001 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 0 +pp_data->cap[1]->NotRange.Reserved4 = 0 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C52F_0001_FF00_expected.rpt_desc b/windows/test/data/046D_C52F_0001_FF00_expected.rpt_desc new file mode 100644 index 000000000..812bd2a8f --- /dev/null +++ b/windows/test/data/046D_C52F_0001_FF00_expected.rpt_desc @@ -0,0 +1,4 @@ +0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x10, 0x09, +0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x06, +0x81, 0x00, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x06, 0x91, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C52F_0001_FF00_real.rpt_desc b/windows/test/data/046D_C52F_0001_FF00_real.rpt_desc new file mode 100644 index 000000000..0db6898fe --- /dev/null +++ b/windows/test/data/046D_C52F_0001_FF00_real.rpt_desc @@ -0,0 +1,13 @@ +Usage Page (Vendor-Defined 1) 06 00 FF +Usage (Vendor-Defined 1) 09 01 +Collection (Application) A1 01 + Report ID (16) 85 10 + Report Size (8) 75 08 + Report Count (6) 95 06 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Usage (Vendor-Defined 1) 09 01 + Input (Data,Ary,Abs) 81 00 + Usage (Vendor-Defined 1) 09 01 + Output (Data,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 00 +End Collection C0 diff --git a/windows/test/data/046D_C52F_0002_0001.pp_data b/windows/test/data/046D_C52F_0002_0001.pp_data new file mode 100644 index 000000000..d90e666e0 --- /dev/null +++ b/windows/test/data/046D_C52F_0002_0001.pp_data @@ -0,0 +1,302 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC52F +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2200 +dev->interface_number = 0 +dev->usage = 0x0002 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046d&pid_c52f&mi_00#8&1599f82d&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 5 +pp_data->caps_info[0]->NumberOfCaps = 5 +pp_data->caps_info[0]->ReportByteLength = 9 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 5 +pp_data->caps_info[1]->LastCap = 5 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 5 +pp_data->caps_info[2]->LastCap = 5 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0208 +pp_data->NumberLinkCollectionNodes = 2 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0009 +pp_data->cap[0]->ReportID = 0x00 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 16 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 16 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0003 +pp_data->cap[0]->LinkCollection = 0x0001 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x0001 +pp_data->cap[0]->Range.UsageMax = 0x0010 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 15 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x00 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 16 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0005 +pp_data->cap[1]->BitCount = 16 +pp_data->cap[1]->BitField = 0x06 +pp_data->cap[1]->NextBytePosition = 0x0007 +pp_data->cap[1]->LinkCollection = 0x0001 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 0 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0031 +pp_data->cap[1]->NotRange.Reserved1 = 0x0031 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 16 +pp_data->cap[1]->NotRange.Reserved4 = 16 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = -32767 +pp_data->cap[1]->NotButton.LogicalMax = 32767 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x0001 +pp_data->cap[2]->ReportID = 0x00 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 16 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0003 +pp_data->cap[2]->BitCount = 16 +pp_data->cap[2]->BitField = 0x06 +pp_data->cap[2]->NextBytePosition = 0x0005 +pp_data->cap[2]->LinkCollection = 0x0001 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 0 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0030 +pp_data->cap[2]->NotRange.Reserved1 = 0x0030 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 17 +pp_data->cap[2]->NotRange.Reserved4 = 17 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = -32767 +pp_data->cap[2]->NotButton.LogicalMax = 32767 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0001 +pp_data->cap[3]->ReportID = 0x00 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 8 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0007 +pp_data->cap[3]->BitCount = 8 +pp_data->cap[3]->BitField = 0x06 +pp_data->cap[3]->NextBytePosition = 0x0008 +pp_data->cap[3]->LinkCollection = 0x0001 +pp_data->cap[3]->LinkUsagePage = 0x0001 +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 0 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0038 +pp_data->cap[3]->NotRange.Reserved1 = 0x0038 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 18 +pp_data->cap[3]->NotRange.Reserved4 = 18 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = -127 +pp_data->cap[3]->NotButton.LogicalMax = 127 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x000C +pp_data->cap[4]->ReportID = 0x00 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 8 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0008 +pp_data->cap[4]->BitCount = 8 +pp_data->cap[4]->BitField = 0x06 +pp_data->cap[4]->NextBytePosition = 0x0009 +pp_data->cap[4]->LinkCollection = 0x0001 +pp_data->cap[4]->LinkUsagePage = 0x0001 +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 0 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 0 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0238 +pp_data->cap[4]->NotRange.Reserved1 = 0x0238 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 19 +pp_data->cap[4]->NotRange.Reserved4 = 19 +pp_data->cap[4]->NotButton.HasNull = 0 +pp_data->cap[4]->NotButton.Reserved4 = 0x000000 +pp_data->cap[4]->NotButton.LogicalMin = -127 +pp_data->cap[4]->NotButton.LogicalMax = 127 +pp_data->cap[4]->NotButton.PhysicalMin = 0 +pp_data->cap[4]->NotButton.PhysicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 1 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 1 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 0 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C52F_0002_0001_expected.rpt_desc b/windows/test/data/046D_C52F_0002_0001_expected.rpt_desc new file mode 100644 index 000000000..128c411ed --- /dev/null +++ b/windows/test/data/046D_C52F_0002_0001_expected.rpt_desc @@ -0,0 +1,8 @@ +0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, +0x05, 0x09, 0x19, 0x01, 0x29, 0x10, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x10, 0x81, 0x02, 0x05, 0x01, 0x09, 0x30, +0x09, 0x31, 0x16, 0x01, 0x80, 0x26, 0xFF, 0x7F, 0x75, 0x10, +0x95, 0x02, 0x81, 0x06, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7F, +0x75, 0x08, 0x95, 0x01, 0x81, 0x06, 0x05, 0x0C, 0x0A, 0x38, +0x02, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, 0x01, 0x81, +0x06, 0xC0, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C52F_0002_0001_real.rpt_desc b/windows/test/data/046D_C52F_0002_0001_real.rpt_desc new file mode 100644 index 000000000..9c0521df4 --- /dev/null +++ b/windows/test/data/046D_C52F_0002_0001_real.rpt_desc @@ -0,0 +1,33 @@ +Usage Page (Generic Desktop) 05 01 +Usage (Mouse) 09 02 +Collection (Application) A1 01 + Usage (Pointer) 09 01 + Collection (Physical) A1 00 + Usage Page (Button) 05 09 + Usage Minimum (Button 1) 19 01 + Usage Maximum (Button 16) 29 10 + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Report Count (16) 95 10 + Report Size (1) 75 01 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Usage Page (Generic Desktop) 05 01 + Logical Minimum (-32767) 16 01 80 + Logical Maximum (32767) 26 FF 7F + Report Size (16) 75 10 + Report Count (2) 95 02 + Usage (X) 09 30 + Usage (Y) 09 31 + Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 81 06 + Logical Minimum (-127) 15 81 + Logical Maximum (127) 25 7F + Report Size (8) 75 08 + Report Count (1) 95 01 + Usage (Wheel) 09 38 + Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 81 06 + Usage Page (Consumer Devices) 05 0C + Usage (AC Pan) 0A 38 02 + Report Count (1) 95 01 + Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 81 06 + End Collection C0 +End Collection C0 diff --git a/windows/test/data/046D_C52F_0002_FF00.pp_data b/windows/test/data/046D_C52F_0002_FF00.pp_data new file mode 100644 index 000000000..09a3689ac --- /dev/null +++ b/windows/test/data/046D_C52F_0002_FF00.pp_data @@ -0,0 +1,139 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC52F +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2200 +dev->interface_number = 1 +dev->usage = 0x0002 +dev->usage_page = 0xFF00 +dev->path = "\\?\hid#vid_046d&pid_c52f&mi_01&col03#8&28ca146b&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0xFF00 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 20 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 2 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 20 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 2 +pp_data->caps_info[2]->LastCap = 2 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x00D0 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF00 +pp_data->cap[0]->ReportID = 0x11 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 19 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 152 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0014 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFF00 +pp_data->cap[0]->LinkUsage = 0x0002 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0002 +pp_data->cap[0]->NotRange.Reserved1 = 0x0002 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[1]->UsagePage = 0xFF00 +pp_data->cap[1]->ReportID = 0x11 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 19 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 152 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0014 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFF00 +pp_data->cap[1]->LinkUsage = 0x0002 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0002 +pp_data->cap[1]->NotRange.Reserved1 = 0x0002 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 0 +pp_data->cap[1]->NotRange.Reserved4 = 0 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C52F_0002_FF00_expected.rpt_desc b/windows/test/data/046D_C52F_0002_FF00_expected.rpt_desc new file mode 100644 index 000000000..b1654e78c --- /dev/null +++ b/windows/test/data/046D_C52F_0002_FF00_expected.rpt_desc @@ -0,0 +1,4 @@ +0x06, 0x00, 0xFF, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x11, 0x09, +0x02, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x13, +0x81, 0x00, 0x09, 0x02, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x13, 0x91, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C52F_0002_FF00_real.rpt_desc b/windows/test/data/046D_C52F_0002_FF00_real.rpt_desc new file mode 100644 index 000000000..68043e15c --- /dev/null +++ b/windows/test/data/046D_C52F_0002_FF00_real.rpt_desc @@ -0,0 +1,13 @@ +Usage Page (Vendor-Defined 1) 06 00 FF +Usage (Vendor-Defined 2) 09 02 +Collection (Application) A1 01 + Report ID (17) 85 11 + Report Size (8) 75 08 + Report Count (19) 95 13 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Usage (Vendor-Defined 2) 09 02 + Input (Data,Ary,Abs) 81 00 + Usage (Vendor-Defined 2) 09 02 + Output (Data,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 00 +End Collection C0 diff --git a/windows/test/data/046D_C534_0001_000C.pp_data b/windows/test/data/046D_C534_0001_000C.pp_data new file mode 100644 index 000000000..5e44a319b --- /dev/null +++ b/windows/test/data/046D_C534_0001_000C.pp_data @@ -0,0 +1,93 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC534 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2901 +dev->interface_number = 1 +dev->usage = 0x0001 +dev->usage_page = 0x000C +dev->path = "\\?\hid#vid_046d&pid_c534&mi_01&col02#7&1ebb799e&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0x000C +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 5 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 1 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 1 +pp_data->caps_info[2]->LastCap = 1 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0068 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x000C +pp_data->cap[0]->ReportID = 0x03 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 16 +pp_data->cap[0]->ReportCount = 2 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 32 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0005 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000C +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x0001 +pp_data->cap[0]->Range.UsageMax = 0x028C +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 651 +pp_data->cap[0]->Button.LogicalMin = 1 +pp_data->cap[0]->Button.LogicalMax = 652 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C534_0001_000C_expected.rpt_desc b/windows/test/data/046D_C534_0001_000C_expected.rpt_desc new file mode 100644 index 000000000..85953ae47 --- /dev/null +++ b/windows/test/data/046D_C534_0001_000C_expected.rpt_desc @@ -0,0 +1,3 @@ +0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x03, 0x19, 0x01, +0x2A, 0x8C, 0x02, 0x15, 0x01, 0x26, 0x8C, 0x02, 0x75, 0x10, +0x95, 0x02, 0x81, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C534_0001_000C_real.rpt_desc b/windows/test/data/046D_C534_0001_000C_real.rpt_desc new file mode 100644 index 000000000..e08f1f3fe --- /dev/null +++ b/windows/test/data/046D_C534_0001_000C_real.rpt_desc @@ -0,0 +1,18 @@ +macOS USB prober output for Logitech USB Receiver + 05 0C 09 01 A1 01 + 85 03 75 10 95 02 15 01 26 8C 02 19 01 2A 8C 02 81 00 + C0 + + Parser output: +0x05, 0x0C, // Usage Page (Consumer) +0x09, 0x01, // Usage (Consumer Control) +0xA1, 0x01, // Collection (Application) +0x85, 0x03, // Report ID (3) +0x75, 0x10, // Report Size (16) +0x95, 0x02, // Report Count (2) +0x15, 0x01, // Logical Minimum (1) +0x26, 0x8C, 0x02, // Logical Maximum (652) +0x19, 0x01, // Usage Minimum (Consumer Control) +0x2A, 0x8C, 0x02, // Usage Maximum (AC Send) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection \ No newline at end of file diff --git a/windows/test/data/046D_C534_0001_FF00.pp_data b/windows/test/data/046D_C534_0001_FF00.pp_data new file mode 100644 index 000000000..6d42a1577 --- /dev/null +++ b/windows/test/data/046D_C534_0001_FF00.pp_data @@ -0,0 +1,139 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC534 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2901 +dev->interface_number = 1 +dev->usage = 0x0001 +dev->usage_page = 0xFF00 +dev->path = "\\?\hid#vid_046d&pid_c534&mi_01&col04#7&1ebb799e&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0xFF00 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 7 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 2 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 7 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 2 +pp_data->caps_info[2]->LastCap = 2 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x00D0 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF00 +pp_data->cap[0]->ReportID = 0x10 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 6 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 48 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0007 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFF00 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0001 +pp_data->cap[0]->NotRange.Reserved1 = 0x0001 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[1]->UsagePage = 0xFF00 +pp_data->cap[1]->ReportID = 0x10 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 6 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 48 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0007 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFF00 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0001 +pp_data->cap[1]->NotRange.Reserved1 = 0x0001 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 0 +pp_data->cap[1]->NotRange.Reserved4 = 0 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C534_0001_FF00_expected.rpt_desc b/windows/test/data/046D_C534_0001_FF00_expected.rpt_desc new file mode 100644 index 000000000..812bd2a8f --- /dev/null +++ b/windows/test/data/046D_C534_0001_FF00_expected.rpt_desc @@ -0,0 +1,4 @@ +0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x10, 0x09, +0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x06, +0x81, 0x00, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x06, 0x91, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C534_0001_FF00_real.rpt_desc b/windows/test/data/046D_C534_0001_FF00_real.rpt_desc new file mode 100644 index 000000000..953193c4b --- /dev/null +++ b/windows/test/data/046D_C534_0001_FF00_real.rpt_desc @@ -0,0 +1,20 @@ +macOS USB prober output for Logitech USB Receiver + +06 00 FF 09 01 A1 01 85 10 75 08 95 06 +15 00 26 FF 00 09 01 81 +00 09 01 91 00 C0 + +Parser Output: +0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) +0x09, 0x01, // Usage (0x01) +0xA1, 0x01, // Collection (Application) +0x85, 0x10, // Report ID (16) +0x75, 0x08, // Report Size (8) +0x95, 0x06, // Report Count (6) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0x00, // Logical Maximum (255) +0x09, 0x01, // Usage (0x01) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x09, 0x01, // Usage (0x01) +0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0xC0, // End Collection diff --git a/windows/test/data/046D_C534_0002_0001.pp_data b/windows/test/data/046D_C534_0002_0001.pp_data new file mode 100644 index 000000000..f50d8a224 --- /dev/null +++ b/windows/test/data/046D_C534_0002_0001.pp_data @@ -0,0 +1,302 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC534 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2901 +dev->interface_number = 1 +dev->usage = 0x0002 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046d&pid_c534&mi_01&col01#7&1ebb799e&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 5 +pp_data->caps_info[0]->NumberOfCaps = 5 +pp_data->caps_info[0]->ReportByteLength = 8 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 5 +pp_data->caps_info[1]->LastCap = 5 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 5 +pp_data->caps_info[2]->LastCap = 5 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0208 +pp_data->NumberLinkCollectionNodes = 2 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0009 +pp_data->cap[0]->ReportID = 0x02 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 16 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 16 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0003 +pp_data->cap[0]->LinkCollection = 0x0001 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x0001 +pp_data->cap[0]->Range.UsageMax = 0x0010 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 15 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x02 +pp_data->cap[1]->BitPosition = 4 +pp_data->cap[1]->BitSize = 12 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0004 +pp_data->cap[1]->BitCount = 12 +pp_data->cap[1]->BitField = 0x06 +pp_data->cap[1]->NextBytePosition = 0x0006 +pp_data->cap[1]->LinkCollection = 0x0001 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 0 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0031 +pp_data->cap[1]->NotRange.Reserved1 = 0x0031 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 16 +pp_data->cap[1]->NotRange.Reserved4 = 16 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = -2047 +pp_data->cap[1]->NotButton.LogicalMax = 2047 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x0001 +pp_data->cap[2]->ReportID = 0x02 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 12 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0003 +pp_data->cap[2]->BitCount = 12 +pp_data->cap[2]->BitField = 0x06 +pp_data->cap[2]->NextBytePosition = 0x0005 +pp_data->cap[2]->LinkCollection = 0x0001 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 0 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0030 +pp_data->cap[2]->NotRange.Reserved1 = 0x0030 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 17 +pp_data->cap[2]->NotRange.Reserved4 = 17 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = -2047 +pp_data->cap[2]->NotButton.LogicalMax = 2047 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x0001 +pp_data->cap[3]->ReportID = 0x02 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 8 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0006 +pp_data->cap[3]->BitCount = 8 +pp_data->cap[3]->BitField = 0x06 +pp_data->cap[3]->NextBytePosition = 0x0007 +pp_data->cap[3]->LinkCollection = 0x0001 +pp_data->cap[3]->LinkUsagePage = 0x0001 +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 0 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0038 +pp_data->cap[3]->NotRange.Reserved1 = 0x0038 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 18 +pp_data->cap[3]->NotRange.Reserved4 = 18 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = -127 +pp_data->cap[3]->NotButton.LogicalMax = 127 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x000C +pp_data->cap[4]->ReportID = 0x02 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 8 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0007 +pp_data->cap[4]->BitCount = 8 +pp_data->cap[4]->BitField = 0x06 +pp_data->cap[4]->NextBytePosition = 0x0008 +pp_data->cap[4]->LinkCollection = 0x0001 +pp_data->cap[4]->LinkUsagePage = 0x0001 +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 0 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 0 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0238 +pp_data->cap[4]->NotRange.Reserved1 = 0x0238 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 19 +pp_data->cap[4]->NotRange.Reserved4 = 19 +pp_data->cap[4]->NotButton.HasNull = 0 +pp_data->cap[4]->NotButton.Reserved4 = 0x000000 +pp_data->cap[4]->NotButton.LogicalMin = -127 +pp_data->cap[4]->NotButton.LogicalMax = 127 +pp_data->cap[4]->NotButton.PhysicalMin = 0 +pp_data->cap[4]->NotButton.PhysicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 1 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 1 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 0 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C534_0002_0001_expected.rpt_desc b/windows/test/data/046D_C534_0002_0001_expected.rpt_desc new file mode 100644 index 000000000..48701c6fb --- /dev/null +++ b/windows/test/data/046D_C534_0002_0001_expected.rpt_desc @@ -0,0 +1,8 @@ +0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, +0x85, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29, 0x10, 0x15, 0x00, +0x25, 0x01, 0x75, 0x01, 0x95, 0x10, 0x81, 0x02, 0x05, 0x01, +0x09, 0x30, 0x09, 0x31, 0x16, 0x01, 0xF8, 0x26, 0xFF, 0x07, +0x75, 0x0C, 0x95, 0x02, 0x81, 0x06, 0x09, 0x38, 0x15, 0x81, +0x25, 0x7F, 0x75, 0x08, 0x95, 0x01, 0x81, 0x06, 0x05, 0x0C, +0x0A, 0x38, 0x02, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, +0x01, 0x81, 0x06, 0xC0, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C534_0002_0001_real.rpt_desc b/windows/test/data/046D_C534_0002_0001_real.rpt_desc new file mode 100644 index 000000000..1c5dea978 --- /dev/null +++ b/windows/test/data/046D_C534_0002_0001_real.rpt_desc @@ -0,0 +1,44 @@ + +05 01 09 02 A1 01 85 02 09 01 A1 00 05 09 19 01 +29 10 15 00 25 01 95 10 75 01 81 02 05 01 16 01 +F8 26 FF 07 75 0C 95 02 09 30 09 31 81 06 15 81 +25 7F 75 08 95 01 09 38 81 06 05 0C 0A 38 02 95 +01 81 06 C0 C0 + +Parser Output: +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x02, // Usage (Mouse) +0xA1, 0x01, // Collection (Application) +0x85, 0x02, // Report ID (2) +0x09, 0x01, // Usage (Pointer) +0xA1, 0x00, // Collection (Physical) +0x05, 0x09, // Usage Page (Button) +0x19, 0x01, // Usage Minimum (0x01) +0x29, 0x10, // Usage Maximum (0x10) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x95, 0x10, // Report Count (16) +0x75, 0x01, // Report Size (1) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x16, 0x01, 0xF8, // Logical Minimum (-2047) +0x26, 0xFF, 0x07, // Logical Maximum (2047) +0x75, 0x0C, // Report Size (12) +0x95, 0x02, // Report Count (2) +0x09, 0x30, // Usage (X) +0x09, 0x31, // Usage (Y) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x15, 0x81, // Logical Minimum (-127) +0x25, 0x7F, // Logical Maximum (127) +0x75, 0x08, // Report Size (8) +0x95, 0x01, // Report Count (1) +0x09, 0x38, // Usage (Wheel) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x05, 0x0C, // Usage Page (Consumer) +0x0A, 0x38, 0x02, // Usage (AC Pan) +0x95, 0x01, // Report Count (1) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection +0xC0, // End Collection + +// 69 bytes diff --git a/windows/test/data/046D_C534_0002_FF00.pp_data b/windows/test/data/046D_C534_0002_FF00.pp_data new file mode 100644 index 000000000..b5fae3a1d --- /dev/null +++ b/windows/test/data/046D_C534_0002_FF00.pp_data @@ -0,0 +1,139 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC534 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2901 +dev->interface_number = 1 +dev->usage = 0x0002 +dev->usage_page = 0xFF00 +dev->path = "\\?\hid#vid_046d&pid_c534&mi_01&col05#7&1ebb799e&0&0004#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0002 +pp_data->UsagePage = 0xFF00 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 1 +pp_data->caps_info[0]->NumberOfCaps = 1 +pp_data->caps_info[0]->ReportByteLength = 20 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 1 +pp_data->caps_info[1]->LastCap = 2 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 20 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 2 +pp_data->caps_info[2]->LastCap = 2 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x00D0 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF00 +pp_data->cap[0]->ReportID = 0x11 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 19 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 152 +pp_data->cap[0]->BitField = 0x00 +pp_data->cap[0]->NextBytePosition = 0x0014 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFF00 +pp_data->cap[0]->LinkUsage = 0x0002 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0002 +pp_data->cap[0]->NotRange.Reserved1 = 0x0002 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 255 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[1]->UsagePage = 0xFF00 +pp_data->cap[1]->ReportID = 0x11 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 19 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 152 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0014 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFF00 +pp_data->cap[1]->LinkUsage = 0x0002 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0002 +pp_data->cap[1]->NotRange.Reserved1 = 0x0002 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 0 +pp_data->cap[1]->NotRange.Reserved4 = 0 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 255 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF00 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C534_0002_FF00_expected.rpt_desc b/windows/test/data/046D_C534_0002_FF00_expected.rpt_desc new file mode 100644 index 000000000..b1654e78c --- /dev/null +++ b/windows/test/data/046D_C534_0002_FF00_expected.rpt_desc @@ -0,0 +1,4 @@ +0x06, 0x00, 0xFF, 0x09, 0x02, 0xA1, 0x01, 0x85, 0x11, 0x09, +0x02, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, 0x08, 0x95, 0x13, +0x81, 0x00, 0x09, 0x02, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x13, 0x91, 0x00, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C534_0002_FF00_real.rpt_desc b/windows/test/data/046D_C534_0002_FF00_real.rpt_desc new file mode 100644 index 000000000..42a0ad88c --- /dev/null +++ b/windows/test/data/046D_C534_0002_FF00_real.rpt_desc @@ -0,0 +1,22 @@ +macOS USB prober output for Logitech USB Receiver + +06 00 FF 09 02 A1 01 85 11 +75 08 95 13 15 00 26 FF +00 09 02 81 00 09 02 91 00 C0 + +Parser output: +0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) +0x09, 0x02, // Usage (0x02) +0xA1, 0x01, // Collection (Application) +0x85, 0x11, // Report ID (17) +0x75, 0x08, // Report Size (8) +0x95, 0x13, // Report Count (19) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xFF, 0x00, // Logical Maximum (255) +0x09, 0x02, // Usage (0x02) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x09, 0x02, // Usage (0x02) +0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0xC0, // End Collection + +// 27 bytes diff --git a/windows/test/data/046D_C534_0006_0001.pp_data b/windows/test/data/046D_C534_0006_0001.pp_data new file mode 100644 index 000000000..2b42d5fbf --- /dev/null +++ b/windows/test/data/046D_C534_0006_0001.pp_data @@ -0,0 +1,185 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC534 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2901 +dev->interface_number = 0 +dev->usage = 0x0006 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046d&pid_c534&mi_00#7&51bc424&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0006 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 2 +pp_data->caps_info[0]->NumberOfCaps = 2 +pp_data->caps_info[0]->ReportByteLength = 9 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 2 +pp_data->caps_info[1]->LastCap = 3 +pp_data->caps_info[1]->NumberOfCaps = 1 +pp_data->caps_info[1]->ReportByteLength = 2 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 3 +pp_data->caps_info[2]->LastCap = 3 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0138 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0007 +pp_data->cap[0]->ReportID = 0x00 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 8 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 8 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0006 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 1 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->Range.UsageMin = 0x00E0 +pp_data->cap[0]->Range.UsageMax = 0x00E7 +pp_data->cap[0]->Range.StringMin = 0 +pp_data->cap[0]->Range.StringMax = 0 +pp_data->cap[0]->Range.DesignatorMin = 0 +pp_data->cap[0]->Range.DesignatorMax = 0 +pp_data->cap[0]->Range.DataIndexMin = 0 +pp_data->cap[0]->Range.DataIndexMax = 7 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0007 +pp_data->cap[1]->ReportID = 0x00 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 8 +pp_data->cap[1]->ReportCount = 6 +pp_data->cap[1]->BytePosition = 0x0003 +pp_data->cap[1]->BitCount = 48 +pp_data->cap[1]->BitField = 0x00 +pp_data->cap[1]->NextBytePosition = 0x0009 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0006 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 1 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->Range.UsageMin = 0x0000 +pp_data->cap[1]->Range.UsageMax = 0x00A4 +pp_data->cap[1]->Range.StringMin = 0 +pp_data->cap[1]->Range.StringMax = 0 +pp_data->cap[1]->Range.DesignatorMin = 0 +pp_data->cap[1]->Range.DesignatorMax = 0 +pp_data->cap[1]->Range.DataIndexMin = 8 +pp_data->cap[1]->Range.DataIndexMax = 172 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 164 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[2]->UsagePage = 0x0008 +pp_data->cap[2]->ReportID = 0x00 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 5 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 5 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0006 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 1 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->Range.UsageMin = 0x0001 +pp_data->cap[2]->Range.UsageMax = 0x0005 +pp_data->cap[2]->Range.StringMin = 0 +pp_data->cap[2]->Range.StringMax = 0 +pp_data->cap[2]->Range.DesignatorMin = 0 +pp_data->cap[2]->Range.DesignatorMax = 0 +pp_data->cap[2]->Range.DataIndexMin = 0 +pp_data->cap[2]->Range.DataIndexMax = 4 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0006 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C534_0006_0001_expected.rpt_desc b/windows/test/data/046D_C534_0006_0001_expected.rpt_desc new file mode 100644 index 000000000..d41d4712e --- /dev/null +++ b/windows/test/data/046D_C534_0006_0001_expected.rpt_desc @@ -0,0 +1,7 @@ +0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, +0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, +0x81, 0x02, 0x75, 0x08, 0x95, 0x01, 0x81, 0x03, 0x19, 0x00, +0x29, 0xA4, 0x15, 0x00, 0x26, 0xA4, 0x00, 0x75, 0x08, 0x95, +0x06, 0x81, 0x00, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x15, +0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x05, 0x91, 0x02, 0x75, +0x03, 0x95, 0x01, 0x91, 0x03, 0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C534_0006_0001_real.rpt_desc b/windows/test/data/046D_C534_0006_0001_real.rpt_desc new file mode 100644 index 000000000..d65aa572a --- /dev/null +++ b/windows/test/data/046D_C534_0006_0001_real.rpt_desc @@ -0,0 +1,42 @@ +macOS USB prober output for Logitech USB Receiver + + +Type: 0x22 (Report Descriptor) +Length (and contents): 59 + Raw Descriptor (hex) 0000: 05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 + Raw Descriptor (hex) 0010: 75 01 95 08 81 02 81 03 95 05 05 08 19 01 29 05 + Raw Descriptor (hex) 0020: 91 02 95 01 75 03 91 01 95 06 75 08 15 00 26 A4 + Raw Descriptor (hex) 0030: 00 05 07 19 00 2A A4 00 81 00 C0 + +Parser output: +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x06, // Usage (Keyboard) +0xA1, 0x01, // Collection (Application) +0x05, 0x07, // Usage Page (Kbrd/Keypad) +0x19, 0xE0, // Usage Minimum (0xE0) +0x29, 0xE7, // Usage Maximum (0xE7) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x75, 0x01, // Report Size (1) +0x95, 0x08, // Report Count (8) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x95, 0x05, // Report Count (5) +0x05, 0x08, // Usage Page (LEDs) +0x19, 0x01, // Usage Minimum (Num Lock) +0x29, 0x05, // Usage Maximum (Kana) +0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x95, 0x01, // Report Count (1) +0x75, 0x03, // Report Size (3) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x95, 0x06, // Report Count (6) +0x75, 0x08, // Report Size (8) +0x15, 0x00, // Logical Minimum (0) +0x26, 0xA4, 0x00, // Logical Maximum (164) +0x05, 0x07, // Usage Page (Kbrd/Keypad) +0x19, 0x00, // Usage Minimum (0x00) +0x2A, 0xA4, 0x00, // Usage Maximum (0xA4) +0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection + +// 59 bytes diff --git a/windows/test/data/046D_C534_0080_0001.pp_data b/windows/test/data/046D_C534_0080_0001.pp_data new file mode 100644 index 000000000..a829f7012 --- /dev/null +++ b/windows/test/data/046D_C534_0080_0001.pp_data @@ -0,0 +1,185 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x046D +dev->product_id = 0xC534 +dev->manufacturer_string = "Logitech" +dev->product_string = "USB Receiver" +dev->release_number = 0x2901 +dev->interface_number = 1 +dev->usage = 0x0080 +dev->usage_page = 0x0001 +dev->path = "\\?\hid#vid_046d&pid_c534&mi_01&col03#7&1ebb799e&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0080 +pp_data->UsagePage = 0x0001 +pp_data->Reserved = 0x00038000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 3 +pp_data->caps_info[0]->NumberOfCaps = 3 +pp_data->caps_info[0]->ReportByteLength = 2 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 3 +pp_data->caps_info[1]->LastCap = 3 +pp_data->caps_info[1]->NumberOfCaps = 0 +pp_data->caps_info[1]->ReportByteLength = 0 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 3 +pp_data->caps_info[2]->LastCap = 3 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0138 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x0001 +pp_data->cap[0]->ReportID = 0x04 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 2 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 2 +pp_data->cap[0]->BitField = 0x60 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x0001 +pp_data->cap[0]->LinkUsage = 0x0080 +pp_data->cap[0]->IsMultipleItemsForArray = 1 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0083 +pp_data->cap[0]->NotRange.Reserved1 = 0x0083 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 2 +pp_data->cap[0]->NotRange.Reserved4 = 2 +pp_data->cap[0]->Button.LogicalMin = 1 +pp_data->cap[0]->Button.LogicalMax = 3 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x0001 +pp_data->cap[1]->ReportID = 0x04 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 2 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 2 +pp_data->cap[1]->BitField = 0x60 +pp_data->cap[1]->NextBytePosition = 0x0002 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x0001 +pp_data->cap[1]->LinkUsage = 0x0080 +pp_data->cap[1]->IsMultipleItemsForArray = 1 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0081 +pp_data->cap[1]->NotRange.Reserved1 = 0x0081 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->Button.LogicalMin = 1 +pp_data->cap[1]->Button.LogicalMax = 3 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x0001 +pp_data->cap[2]->ReportID = 0x04 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 2 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 2 +pp_data->cap[2]->BitField = 0x60 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x0001 +pp_data->cap[2]->LinkUsage = 0x0080 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0082 +pp_data->cap[2]->NotRange.Reserved1 = 0x0082 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 0 +pp_data->cap[2]->NotRange.Reserved4 = 0 +pp_data->cap[2]->Button.LogicalMin = 1 +pp_data->cap[2]->Button.LogicalMax = 3 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +# Output hid_pp_cap struct: +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0080 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x0001 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/046D_C534_0080_0001_expected.rpt_desc b/windows/test/data/046D_C534_0080_0001_expected.rpt_desc new file mode 100644 index 000000000..e7a9677a7 --- /dev/null +++ b/windows/test/data/046D_C534_0080_0001_expected.rpt_desc @@ -0,0 +1,4 @@ +0x05, 0x01, 0x09, 0x80, 0xA1, 0x01, 0x85, 0x04, 0x09, 0x82, +0x09, 0x81, 0x09, 0x83, 0x15, 0x01, 0x25, 0x03, 0x75, 0x02, +0x95, 0x01, 0x81, 0x60, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, +0xC0, \ No newline at end of file diff --git a/windows/test/data/046D_C534_0080_0001_real.rpt_desc b/windows/test/data/046D_C534_0080_0001_real.rpt_desc new file mode 100644 index 000000000..7ebe8c954 --- /dev/null +++ b/windows/test/data/046D_C534_0080_0001_real.rpt_desc @@ -0,0 +1,22 @@ + +05 01 09 80 A1 01 85 04 75 02 95 01 15 01 25 03 +09 82 09 81 09 83 81 60 75 06 81 03 C0 + +Parser output: +0x05, 0x01, // Usage Page (Generic Desktop Ctrls) +0x09, 0x80, // Usage (Sys Control) +0xA1, 0x01, // Collection (Application) +0x85, 0x04, // Report ID (4) +0x75, 0x02, // Report Size (2) +0x95, 0x01, // Report Count (1) +0x15, 0x01, // Logical Minimum (1) +0x25, 0x03, // Logical Maximum (3) +0x09, 0x82, // Usage (Sys Sleep) +0x09, 0x81, // Usage (Sys Power Down) +0x09, 0x83, // Usage (Sys Wake Up) +0x81, 0x60, // Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State) +0x75, 0x06, // Report Size (6) +0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection + +// 29 bytes diff --git a/windows/test/data/047F_C056_0001_000C.pp_data b/windows/test/data/047F_C056_0001_000C.pp_data new file mode 100644 index 000000000..87da2b257 --- /dev/null +++ b/windows/test/data/047F_C056_0001_000C.pp_data @@ -0,0 +1,385 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x047F +dev->product_id = 0xC056 +dev->manufacturer_string = "Plantronics" +dev->product_string = "Plantronics Blackwire 3220 Series" +dev->release_number = 0x0210 +dev->interface_number = 3 +dev->usage = 0x0001 +dev->usage_page = 0x000C +dev->path = "\\?\hid#vid_047f&pid_c056&mi_03&col01#f&39e6f119&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0001 +pp_data->UsagePage = 0x000C +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 5 +pp_data->caps_info[0]->NumberOfCaps = 5 +pp_data->caps_info[0]->ReportByteLength = 33 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 5 +pp_data->caps_info[1]->LastCap = 7 +pp_data->caps_info[1]->NumberOfCaps = 2 +pp_data->caps_info[1]->ReportByteLength = 37 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 7 +pp_data->caps_info[2]->LastCap = 7 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x02D8 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x000C +pp_data->cap[0]->ReportID = 0x01 +pp_data->cap[0]->BitPosition = 1 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 1 +pp_data->cap[0]->BitField = 0x06 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000C +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 0 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x00EA +pp_data->cap[0]->NotRange.Reserved1 = 0x00EA +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x000C +pp_data->cap[1]->ReportID = 0x01 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 1 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 1 +pp_data->cap[1]->BitField = 0x06 +pp_data->cap[1]->NextBytePosition = 0x0002 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x000C +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 0 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x00E9 +pp_data->cap[1]->NotRange.Reserved1 = 0x00E9 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x000C +pp_data->cap[2]->ReportID = 0x02 +pp_data->cap[2]->BitPosition = 0 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 16 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 16 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0003 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x000C +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0000 +pp_data->cap[2]->NotRange.Reserved1 = 0x0000 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0x000C +pp_data->cap[3]->ReportID = 0x05 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 8 +pp_data->cap[3]->ReportCount = 32 +pp_data->cap[3]->BytePosition = 0x0001 +pp_data->cap[3]->BitCount = 256 +pp_data->cap[3]->BitField = 0x02 +pp_data->cap[3]->NextBytePosition = 0x0021 +pp_data->cap[3]->LinkCollection = 0x0000 +pp_data->cap[3]->LinkUsagePage = 0x000C +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 1 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0000 +pp_data->cap[3]->NotRange.Reserved1 = 0x0000 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 3 +pp_data->cap[3]->NotRange.Reserved4 = 3 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = 0 +pp_data->cap[3]->NotButton.LogicalMax = 1 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x000C +pp_data->cap[4]->ReportID = 0x07 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 8 +pp_data->cap[4]->ReportCount = 32 +pp_data->cap[4]->BytePosition = 0x0001 +pp_data->cap[4]->BitCount = 256 +pp_data->cap[4]->BitField = 0x02 +pp_data->cap[4]->NextBytePosition = 0x0021 +pp_data->cap[4]->LinkCollection = 0x0000 +pp_data->cap[4]->LinkUsagePage = 0x000C +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 0 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 1 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0000 +pp_data->cap[4]->NotRange.Reserved1 = 0x0000 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 4 +pp_data->cap[4]->NotRange.Reserved4 = 4 +pp_data->cap[4]->NotButton.HasNull = 0 +pp_data->cap[4]->NotButton.Reserved4 = 0x000000 +pp_data->cap[4]->NotButton.LogicalMin = 0 +pp_data->cap[4]->NotButton.LogicalMax = 1 +pp_data->cap[4]->NotButton.PhysicalMin = 0 +pp_data->cap[4]->NotButton.PhysicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[5]->UsagePage = 0x000C +pp_data->cap[5]->ReportID = 0x04 +pp_data->cap[5]->BitPosition = 0 +pp_data->cap[5]->BitSize = 8 +pp_data->cap[5]->ReportCount = 36 +pp_data->cap[5]->BytePosition = 0x0001 +pp_data->cap[5]->BitCount = 288 +pp_data->cap[5]->BitField = 0x02 +pp_data->cap[5]->NextBytePosition = 0x0025 +pp_data->cap[5]->LinkCollection = 0x0000 +pp_data->cap[5]->LinkUsagePage = 0x000C +pp_data->cap[5]->LinkUsage = 0x0001 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 0 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 1 +pp_data->cap[5]->IsRange = 0 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->NotRange.Usage = 0x0000 +pp_data->cap[5]->NotRange.Reserved1 = 0x0000 +pp_data->cap[5]->NotRange.StringIndex = 0 +pp_data->cap[5]->NotRange.Reserved2 = 0 +pp_data->cap[5]->NotRange.DesignatorIndex = 0 +pp_data->cap[5]->NotRange.Reserved3 = 0 +pp_data->cap[5]->NotRange.DataIndex = 0 +pp_data->cap[5]->NotRange.Reserved4 = 0 +pp_data->cap[5]->NotButton.HasNull = 0 +pp_data->cap[5]->NotButton.Reserved4 = 0x000000 +pp_data->cap[5]->NotButton.LogicalMin = 0 +pp_data->cap[5]->NotButton.LogicalMax = 1 +pp_data->cap[5]->NotButton.PhysicalMin = 0 +pp_data->cap[5]->NotButton.PhysicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0x000C +pp_data->cap[6]->ReportID = 0x06 +pp_data->cap[6]->BitPosition = 0 +pp_data->cap[6]->BitSize = 8 +pp_data->cap[6]->ReportCount = 36 +pp_data->cap[6]->BytePosition = 0x0001 +pp_data->cap[6]->BitCount = 288 +pp_data->cap[6]->BitField = 0x02 +pp_data->cap[6]->NextBytePosition = 0x0025 +pp_data->cap[6]->LinkCollection = 0x0000 +pp_data->cap[6]->LinkUsagePage = 0x000C +pp_data->cap[6]->LinkUsage = 0x0001 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 0 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x0000 +pp_data->cap[6]->NotRange.Reserved1 = 0x0000 +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 1 +pp_data->cap[6]->NotRange.Reserved4 = 1 +pp_data->cap[6]->NotButton.HasNull = 0 +pp_data->cap[6]->NotButton.Reserved4 = 0x000000 +pp_data->cap[6]->NotButton.LogicalMin = 0 +pp_data->cap[6]->NotButton.LogicalMax = 1 +pp_data->cap[6]->NotButton.PhysicalMin = 0 +pp_data->cap[6]->NotButton.PhysicalMax = 0 +pp_data->cap[6]->Units = 0 +pp_data->cap[6]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000C +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/047F_C056_0001_000C_expected.rpt_desc b/windows/test/data/047F_C056_0001_000C_expected.rpt_desc new file mode 100644 index 000000000..d7ca0452e --- /dev/null +++ b/windows/test/data/047F_C056_0001_000C_expected.rpt_desc @@ -0,0 +1,10 @@ +0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x01, 0x09, 0xE9, +0x09, 0xEA, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x02, +0x81, 0x06, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x85, 0x02, +0x09, 0x00, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x10, +0x81, 0x02, 0x85, 0x05, 0x09, 0x00, 0x15, 0x00, 0x25, 0x01, +0x75, 0x08, 0x95, 0x20, 0x81, 0x02, 0x85, 0x07, 0x09, 0x00, +0x15, 0x00, 0x25, 0x01, 0x75, 0x08, 0x95, 0x20, 0x81, 0x02, +0x85, 0x04, 0x09, 0x00, 0x15, 0x00, 0x25, 0x01, 0x75, 0x08, +0x95, 0x24, 0x91, 0x02, 0x85, 0x06, 0x09, 0x00, 0x15, 0x00, +0x25, 0x01, 0x75, 0x08, 0x95, 0x24, 0x91, 0x02, 0xC0, \ No newline at end of file diff --git a/windows/test/data/047F_C056_0001_000C_real.rpt_desc b/windows/test/data/047F_C056_0001_000C_real.rpt_desc new file mode 100644 index 000000000..ba0fc3a5f --- /dev/null +++ b/windows/test/data/047F_C056_0001_000C_real.rpt_desc @@ -0,0 +1,47 @@ +macOS USB Prober about 0x047F/0xC056 "Plantronics Blackwire 3220 Series" +05 0C 09 01 A1 01 85 01 15 00 25 01 09 E9 09 EA +75 01 95 02 81 06 95 06 81 01 85 02 05 0C 09 00 +95 10 81 02 85 04 09 00 75 08 95 24 91 02 85 05 +09 00 95 20 81 02 85 06 09 00 95 24 91 02 85 07 +09 00 95 20 81 02 C0 + +# Parser output: + +0x05, 0x0C, // Usage Page (Consumer) +0x09, 0x01, // Usage (Consumer Control) +0xA1, 0x01, // Collection (Application) +0x85, 0x01, // Report ID (1) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x09, 0xE9, // Usage (Volume Increment) +0x09, 0xEA, // Usage (Volume Decrement) +0x75, 0x01, // Report Size (1) +0x95, 0x02, // Report Count (2) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x95, 0x06, // Report Count (6) +0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x85, 0x02, // Report ID (2) +0x05, 0x0C, // Usage Page (Consumer) +0x09, 0x00, // Usage (Unassigned) +0x95, 0x10, // Report Count (16) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x85, 0x04, // Report ID (4) +0x09, 0x00, // Usage (Unassigned) +0x75, 0x08, // Report Size (8) +0x95, 0x24, // Report Count (36) +0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x05, // Report ID (5) +0x09, 0x00, // Usage (Unassigned) +0x95, 0x20, // Report Count (32) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x85, 0x06, // Report ID (6) +0x09, 0x00, // Usage (Unassigned) +0x95, 0x24, // Report Count (36) +0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x07, // Report ID (7) +0x09, 0x00, // Usage (Unassigned) +0x95, 0x20, // Report Count (32) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection + +// 71 bytes diff --git a/windows/test/data/047F_C056_0003_FFA0.pp_data b/windows/test/data/047F_C056_0003_FFA0.pp_data new file mode 100644 index 000000000..6def73665 --- /dev/null +++ b/windows/test/data/047F_C056_0003_FFA0.pp_data @@ -0,0 +1,1255 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x047F +dev->product_id = 0xC056 +dev->manufacturer_string = "Plantronics" +dev->product_string = "Plantronics Blackwire 3220 Series" +dev->release_number = 0x0210 +dev->interface_number = 3 +dev->usage = 0x0003 +dev->usage_page = 0xFFA0 +dev->path = "\\?\hid#vid_047f&pid_c056&mi_03&col03#f&39e6f119&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0003 +pp_data->UsagePage = 0xFFA0 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 8 +pp_data->caps_info[0]->NumberOfCaps = 8 +pp_data->caps_info[0]->ReportByteLength = 33 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 8 +pp_data->caps_info[1]->LastCap = 16 +pp_data->caps_info[1]->NumberOfCaps = 8 +pp_data->caps_info[1]->ReportByteLength = 33 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 16 +pp_data->caps_info[2]->LastCap = 26 +pp_data->caps_info[2]->NumberOfCaps = 10 +pp_data->caps_info[2]->ReportByteLength = 3 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x0A90 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFFA0 +pp_data->cap[0]->ReportID = 0x03 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 8 +pp_data->cap[0]->ReportCount = 32 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 256 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0021 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0xFFA0 +pp_data->cap[0]->LinkUsage = 0x0003 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 0 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0030 +pp_data->cap[0]->NotRange.Reserved1 = 0x0030 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->NotButton.HasNull = 0 +pp_data->cap[0]->NotButton.Reserved4 = 0x000000 +pp_data->cap[0]->NotButton.LogicalMin = 0 +pp_data->cap[0]->NotButton.LogicalMax = 1 +pp_data->cap[0]->NotButton.PhysicalMin = 0 +pp_data->cap[0]->NotButton.PhysicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0xFFA0 +pp_data->cap[1]->ReportID = 0x14 +pp_data->cap[1]->BitPosition = 4 +pp_data->cap[1]->BitSize = 1 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 1 +pp_data->cap[1]->BitField = 0x06 +pp_data->cap[1]->NextBytePosition = 0x0002 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0xFFA0 +pp_data->cap[1]->LinkUsage = 0x0003 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 0 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x00B3 +pp_data->cap[1]->NotRange.Reserved1 = 0x00B3 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0xFFA0 +pp_data->cap[2]->ReportID = 0x14 +pp_data->cap[2]->BitPosition = 3 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 1 +pp_data->cap[2]->BitField = 0x06 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0xFFA0 +pp_data->cap[2]->LinkUsage = 0x0003 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 0 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x00B7 +pp_data->cap[2]->NotRange.Reserved1 = 0x00B7 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0xFFA0 +pp_data->cap[3]->ReportID = 0x14 +pp_data->cap[3]->BitPosition = 2 +pp_data->cap[3]->BitSize = 1 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0001 +pp_data->cap[3]->BitCount = 1 +pp_data->cap[3]->BitField = 0x06 +pp_data->cap[3]->NextBytePosition = 0x0002 +pp_data->cap[3]->LinkCollection = 0x0000 +pp_data->cap[3]->LinkUsagePage = 0xFFA0 +pp_data->cap[3]->LinkUsage = 0x0003 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 1 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 0 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x00B5 +pp_data->cap[3]->NotRange.Reserved1 = 0x00B5 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 3 +pp_data->cap[3]->NotRange.Reserved4 = 3 +pp_data->cap[3]->Button.LogicalMin = 0 +pp_data->cap[3]->Button.LogicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0xFFA0 +pp_data->cap[4]->ReportID = 0x14 +pp_data->cap[4]->BitPosition = 1 +pp_data->cap[4]->BitSize = 1 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0001 +pp_data->cap[4]->BitCount = 1 +pp_data->cap[4]->BitField = 0x06 +pp_data->cap[4]->NextBytePosition = 0x0002 +pp_data->cap[4]->LinkCollection = 0x0000 +pp_data->cap[4]->LinkUsagePage = 0xFFA0 +pp_data->cap[4]->LinkUsage = 0x0003 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 1 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 0 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x00B2 +pp_data->cap[4]->NotRange.Reserved1 = 0x00B2 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 4 +pp_data->cap[4]->NotRange.Reserved4 = 4 +pp_data->cap[4]->Button.LogicalMin = 0 +pp_data->cap[4]->Button.LogicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +pp_data->cap[5]->UsagePage = 0xFFA0 +pp_data->cap[5]->ReportID = 0x14 +pp_data->cap[5]->BitPosition = 0 +pp_data->cap[5]->BitSize = 1 +pp_data->cap[5]->ReportCount = 1 +pp_data->cap[5]->BytePosition = 0x0001 +pp_data->cap[5]->BitCount = 1 +pp_data->cap[5]->BitField = 0x06 +pp_data->cap[5]->NextBytePosition = 0x0002 +pp_data->cap[5]->LinkCollection = 0x0000 +pp_data->cap[5]->LinkUsagePage = 0xFFA0 +pp_data->cap[5]->LinkUsage = 0x0003 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 1 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 0 +pp_data->cap[5]->IsRange = 0 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->NotRange.Usage = 0x00B1 +pp_data->cap[5]->NotRange.Reserved1 = 0x00B1 +pp_data->cap[5]->NotRange.StringIndex = 0 +pp_data->cap[5]->NotRange.Reserved2 = 0 +pp_data->cap[5]->NotRange.DesignatorIndex = 0 +pp_data->cap[5]->NotRange.Reserved3 = 0 +pp_data->cap[5]->NotRange.DataIndex = 5 +pp_data->cap[5]->NotRange.Reserved4 = 5 +pp_data->cap[5]->Button.LogicalMin = 0 +pp_data->cap[5]->Button.LogicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0xFFA0 +pp_data->cap[6]->ReportID = 0x15 +pp_data->cap[6]->BitPosition = 0 +pp_data->cap[6]->BitSize = 16 +pp_data->cap[6]->ReportCount = 1 +pp_data->cap[6]->BytePosition = 0x0001 +pp_data->cap[6]->BitCount = 16 +pp_data->cap[6]->BitField = 0x22 +pp_data->cap[6]->NextBytePosition = 0x0003 +pp_data->cap[6]->LinkCollection = 0x0000 +pp_data->cap[6]->LinkUsagePage = 0xFFA0 +pp_data->cap[6]->LinkUsage = 0x0003 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 0 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x008C +pp_data->cap[6]->NotRange.Reserved1 = 0x008C +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 6 +pp_data->cap[6]->NotRange.Reserved4 = 6 +pp_data->cap[6]->NotButton.HasNull = 0 +pp_data->cap[6]->NotButton.Reserved4 = 0x000000 +pp_data->cap[6]->NotButton.LogicalMin = 0 +pp_data->cap[6]->NotButton.LogicalMax = 65535 +pp_data->cap[6]->NotButton.PhysicalMin = 0 +pp_data->cap[6]->NotButton.PhysicalMax = 0 +pp_data->cap[6]->Units = 0 +pp_data->cap[6]->UnitsExp = 0 + +pp_data->cap[7]->UsagePage = 0xFFA0 +pp_data->cap[7]->ReportID = 0x1F +pp_data->cap[7]->BitPosition = 0 +pp_data->cap[7]->BitSize = 1 +pp_data->cap[7]->ReportCount = 1 +pp_data->cap[7]->BytePosition = 0x0001 +pp_data->cap[7]->BitCount = 1 +pp_data->cap[7]->BitField = 0x06 +pp_data->cap[7]->NextBytePosition = 0x0002 +pp_data->cap[7]->LinkCollection = 0x0000 +pp_data->cap[7]->LinkUsagePage = 0xFFA0 +pp_data->cap[7]->LinkUsage = 0x0003 +pp_data->cap[7]->IsMultipleItemsForArray = 0 +pp_data->cap[7]->IsButtonCap = 1 +pp_data->cap[7]->IsPadding = 0 +pp_data->cap[7]->IsAbsolute = 0 +pp_data->cap[7]->IsRange = 0 +pp_data->cap[7]->IsAlias = 0 +pp_data->cap[7]->IsStringRange = 0 +pp_data->cap[7]->IsDesignatorRange = 0 +pp_data->cap[7]->Reserved1 = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[7]->NotRange.Usage = 0x009C +pp_data->cap[7]->NotRange.Reserved1 = 0x009C +pp_data->cap[7]->NotRange.StringIndex = 0 +pp_data->cap[7]->NotRange.Reserved2 = 0 +pp_data->cap[7]->NotRange.DesignatorIndex = 0 +pp_data->cap[7]->NotRange.Reserved3 = 0 +pp_data->cap[7]->NotRange.DataIndex = 7 +pp_data->cap[7]->NotRange.Reserved4 = 7 +pp_data->cap[7]->Button.LogicalMin = 0 +pp_data->cap[7]->Button.LogicalMax = 0 +pp_data->cap[7]->Units = 0 +pp_data->cap[7]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[8]->UsagePage = 0xFFA0 +pp_data->cap[8]->ReportID = 0x03 +pp_data->cap[8]->BitPosition = 0 +pp_data->cap[8]->BitSize = 8 +pp_data->cap[8]->ReportCount = 32 +pp_data->cap[8]->BytePosition = 0x0001 +pp_data->cap[8]->BitCount = 256 +pp_data->cap[8]->BitField = 0x02 +pp_data->cap[8]->NextBytePosition = 0x0021 +pp_data->cap[8]->LinkCollection = 0x0000 +pp_data->cap[8]->LinkUsagePage = 0xFFA0 +pp_data->cap[8]->LinkUsage = 0x0003 +pp_data->cap[8]->IsMultipleItemsForArray = 0 +pp_data->cap[8]->IsButtonCap = 0 +pp_data->cap[8]->IsPadding = 0 +pp_data->cap[8]->IsAbsolute = 1 +pp_data->cap[8]->IsRange = 0 +pp_data->cap[8]->IsAlias = 0 +pp_data->cap[8]->IsStringRange = 0 +pp_data->cap[8]->IsDesignatorRange = 0 +pp_data->cap[8]->Reserved1 = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[8]->NotRange.Usage = 0x0030 +pp_data->cap[8]->NotRange.Reserved1 = 0x0030 +pp_data->cap[8]->NotRange.StringIndex = 0 +pp_data->cap[8]->NotRange.Reserved2 = 0 +pp_data->cap[8]->NotRange.DesignatorIndex = 0 +pp_data->cap[8]->NotRange.Reserved3 = 0 +pp_data->cap[8]->NotRange.DataIndex = 0 +pp_data->cap[8]->NotRange.Reserved4 = 0 +pp_data->cap[8]->NotButton.HasNull = 0 +pp_data->cap[8]->NotButton.Reserved4 = 0x000000 +pp_data->cap[8]->NotButton.LogicalMin = 0 +pp_data->cap[8]->NotButton.LogicalMax = 1 +pp_data->cap[8]->NotButton.PhysicalMin = 0 +pp_data->cap[8]->NotButton.PhysicalMax = 0 +pp_data->cap[8]->Units = 0 +pp_data->cap[8]->UnitsExp = 0 + +pp_data->cap[9]->UsagePage = 0xFFA0 +pp_data->cap[9]->ReportID = 0x19 +pp_data->cap[9]->BitPosition = 3 +pp_data->cap[9]->BitSize = 1 +pp_data->cap[9]->ReportCount = 1 +pp_data->cap[9]->BytePosition = 0x0001 +pp_data->cap[9]->BitCount = 1 +pp_data->cap[9]->BitField = 0x22 +pp_data->cap[9]->NextBytePosition = 0x0002 +pp_data->cap[9]->LinkCollection = 0x0000 +pp_data->cap[9]->LinkUsagePage = 0xFFA0 +pp_data->cap[9]->LinkUsage = 0x0003 +pp_data->cap[9]->IsMultipleItemsForArray = 0 +pp_data->cap[9]->IsButtonCap = 1 +pp_data->cap[9]->IsPadding = 0 +pp_data->cap[9]->IsAbsolute = 1 +pp_data->cap[9]->IsRange = 0 +pp_data->cap[9]->IsAlias = 0 +pp_data->cap[9]->IsStringRange = 0 +pp_data->cap[9]->IsDesignatorRange = 0 +pp_data->cap[9]->Reserved1 = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[9]->NotRange.Usage = 0x00DC +pp_data->cap[9]->NotRange.Reserved1 = 0x00DC +pp_data->cap[9]->NotRange.StringIndex = 0 +pp_data->cap[9]->NotRange.Reserved2 = 0 +pp_data->cap[9]->NotRange.DesignatorIndex = 0 +pp_data->cap[9]->NotRange.Reserved3 = 0 +pp_data->cap[9]->NotRange.DataIndex = 1 +pp_data->cap[9]->NotRange.Reserved4 = 1 +pp_data->cap[9]->Button.LogicalMin = 0 +pp_data->cap[9]->Button.LogicalMax = 0 +pp_data->cap[9]->Units = 0 +pp_data->cap[9]->UnitsExp = 0 + +pp_data->cap[10]->UsagePage = 0xFFA0 +pp_data->cap[10]->ReportID = 0x19 +pp_data->cap[10]->BitPosition = 2 +pp_data->cap[10]->BitSize = 1 +pp_data->cap[10]->ReportCount = 1 +pp_data->cap[10]->BytePosition = 0x0001 +pp_data->cap[10]->BitCount = 1 +pp_data->cap[10]->BitField = 0x22 +pp_data->cap[10]->NextBytePosition = 0x0002 +pp_data->cap[10]->LinkCollection = 0x0000 +pp_data->cap[10]->LinkUsagePage = 0xFFA0 +pp_data->cap[10]->LinkUsage = 0x0003 +pp_data->cap[10]->IsMultipleItemsForArray = 0 +pp_data->cap[10]->IsButtonCap = 1 +pp_data->cap[10]->IsPadding = 0 +pp_data->cap[10]->IsAbsolute = 1 +pp_data->cap[10]->IsRange = 0 +pp_data->cap[10]->IsAlias = 0 +pp_data->cap[10]->IsStringRange = 0 +pp_data->cap[10]->IsDesignatorRange = 0 +pp_data->cap[10]->Reserved1 = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[10]->NotRange.Usage = 0x009E +pp_data->cap[10]->NotRange.Reserved1 = 0x009E +pp_data->cap[10]->NotRange.StringIndex = 0 +pp_data->cap[10]->NotRange.Reserved2 = 0 +pp_data->cap[10]->NotRange.DesignatorIndex = 0 +pp_data->cap[10]->NotRange.Reserved3 = 0 +pp_data->cap[10]->NotRange.DataIndex = 2 +pp_data->cap[10]->NotRange.Reserved4 = 2 +pp_data->cap[10]->Button.LogicalMin = 0 +pp_data->cap[10]->Button.LogicalMax = 0 +pp_data->cap[10]->Units = 0 +pp_data->cap[10]->UnitsExp = 0 + +pp_data->cap[11]->UsagePage = 0xFFA0 +pp_data->cap[11]->ReportID = 0x19 +pp_data->cap[11]->BitPosition = 1 +pp_data->cap[11]->BitSize = 1 +pp_data->cap[11]->ReportCount = 1 +pp_data->cap[11]->BytePosition = 0x0001 +pp_data->cap[11]->BitCount = 1 +pp_data->cap[11]->BitField = 0x22 +pp_data->cap[11]->NextBytePosition = 0x0002 +pp_data->cap[11]->LinkCollection = 0x0000 +pp_data->cap[11]->LinkUsagePage = 0xFFA0 +pp_data->cap[11]->LinkUsage = 0x0003 +pp_data->cap[11]->IsMultipleItemsForArray = 0 +pp_data->cap[11]->IsButtonCap = 1 +pp_data->cap[11]->IsPadding = 0 +pp_data->cap[11]->IsAbsolute = 1 +pp_data->cap[11]->IsRange = 0 +pp_data->cap[11]->IsAlias = 0 +pp_data->cap[11]->IsStringRange = 0 +pp_data->cap[11]->IsDesignatorRange = 0 +pp_data->cap[11]->Reserved1 = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[11]->NotRange.Usage = 0x008F +pp_data->cap[11]->NotRange.Reserved1 = 0x008F +pp_data->cap[11]->NotRange.StringIndex = 0 +pp_data->cap[11]->NotRange.Reserved2 = 0 +pp_data->cap[11]->NotRange.DesignatorIndex = 0 +pp_data->cap[11]->NotRange.Reserved3 = 0 +pp_data->cap[11]->NotRange.DataIndex = 3 +pp_data->cap[11]->NotRange.Reserved4 = 3 +pp_data->cap[11]->Button.LogicalMin = 0 +pp_data->cap[11]->Button.LogicalMax = 0 +pp_data->cap[11]->Units = 0 +pp_data->cap[11]->UnitsExp = 0 + +pp_data->cap[12]->UsagePage = 0xFFA0 +pp_data->cap[12]->ReportID = 0x19 +pp_data->cap[12]->BitPosition = 0 +pp_data->cap[12]->BitSize = 1 +pp_data->cap[12]->ReportCount = 1 +pp_data->cap[12]->BytePosition = 0x0001 +pp_data->cap[12]->BitCount = 1 +pp_data->cap[12]->BitField = 0x22 +pp_data->cap[12]->NextBytePosition = 0x0002 +pp_data->cap[12]->LinkCollection = 0x0000 +pp_data->cap[12]->LinkUsagePage = 0xFFA0 +pp_data->cap[12]->LinkUsage = 0x0003 +pp_data->cap[12]->IsMultipleItemsForArray = 0 +pp_data->cap[12]->IsButtonCap = 1 +pp_data->cap[12]->IsPadding = 0 +pp_data->cap[12]->IsAbsolute = 1 +pp_data->cap[12]->IsRange = 0 +pp_data->cap[12]->IsAlias = 0 +pp_data->cap[12]->IsStringRange = 0 +pp_data->cap[12]->IsDesignatorRange = 0 +pp_data->cap[12]->Reserved1 = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[12]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[12]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[12]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[12]->NotRange.Usage = 0x008D +pp_data->cap[12]->NotRange.Reserved1 = 0x008D +pp_data->cap[12]->NotRange.StringIndex = 0 +pp_data->cap[12]->NotRange.Reserved2 = 0 +pp_data->cap[12]->NotRange.DesignatorIndex = 0 +pp_data->cap[12]->NotRange.Reserved3 = 0 +pp_data->cap[12]->NotRange.DataIndex = 4 +pp_data->cap[12]->NotRange.Reserved4 = 4 +pp_data->cap[12]->Button.LogicalMin = 0 +pp_data->cap[12]->Button.LogicalMax = 0 +pp_data->cap[12]->Units = 0 +pp_data->cap[12]->UnitsExp = 0 + +pp_data->cap[13]->UsagePage = 0xFFA0 +pp_data->cap[13]->ReportID = 0x19 +pp_data->cap[13]->BitPosition = 5 +pp_data->cap[13]->BitSize = 1 +pp_data->cap[13]->ReportCount = 1 +pp_data->cap[13]->BytePosition = 0x0001 +pp_data->cap[13]->BitCount = 1 +pp_data->cap[13]->BitField = 0x06 +pp_data->cap[13]->NextBytePosition = 0x0002 +pp_data->cap[13]->LinkCollection = 0x0000 +pp_data->cap[13]->LinkUsagePage = 0xFFA0 +pp_data->cap[13]->LinkUsage = 0x0003 +pp_data->cap[13]->IsMultipleItemsForArray = 0 +pp_data->cap[13]->IsButtonCap = 1 +pp_data->cap[13]->IsPadding = 0 +pp_data->cap[13]->IsAbsolute = 0 +pp_data->cap[13]->IsRange = 0 +pp_data->cap[13]->IsAlias = 0 +pp_data->cap[13]->IsStringRange = 0 +pp_data->cap[13]->IsDesignatorRange = 0 +pp_data->cap[13]->Reserved1 = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[13]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[13]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[13]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[13]->NotRange.Usage = 0x00D9 +pp_data->cap[13]->NotRange.Reserved1 = 0x00D9 +pp_data->cap[13]->NotRange.StringIndex = 0 +pp_data->cap[13]->NotRange.Reserved2 = 0 +pp_data->cap[13]->NotRange.DesignatorIndex = 0 +pp_data->cap[13]->NotRange.Reserved3 = 0 +pp_data->cap[13]->NotRange.DataIndex = 5 +pp_data->cap[13]->NotRange.Reserved4 = 5 +pp_data->cap[13]->Button.LogicalMin = 0 +pp_data->cap[13]->Button.LogicalMax = 0 +pp_data->cap[13]->Units = 0 +pp_data->cap[13]->UnitsExp = 0 + +pp_data->cap[14]->UsagePage = 0xFFA0 +pp_data->cap[14]->ReportID = 0x19 +pp_data->cap[14]->BitPosition = 4 +pp_data->cap[14]->BitSize = 1 +pp_data->cap[14]->ReportCount = 1 +pp_data->cap[14]->BytePosition = 0x0001 +pp_data->cap[14]->BitCount = 1 +pp_data->cap[14]->BitField = 0x06 +pp_data->cap[14]->NextBytePosition = 0x0002 +pp_data->cap[14]->LinkCollection = 0x0000 +pp_data->cap[14]->LinkUsagePage = 0xFFA0 +pp_data->cap[14]->LinkUsage = 0x0003 +pp_data->cap[14]->IsMultipleItemsForArray = 0 +pp_data->cap[14]->IsButtonCap = 1 +pp_data->cap[14]->IsPadding = 0 +pp_data->cap[14]->IsAbsolute = 0 +pp_data->cap[14]->IsRange = 0 +pp_data->cap[14]->IsAlias = 0 +pp_data->cap[14]->IsStringRange = 0 +pp_data->cap[14]->IsDesignatorRange = 0 +pp_data->cap[14]->Reserved1 = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[14]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[14]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[14]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[14]->NotRange.Usage = 0x00D2 +pp_data->cap[14]->NotRange.Reserved1 = 0x00D2 +pp_data->cap[14]->NotRange.StringIndex = 0 +pp_data->cap[14]->NotRange.Reserved2 = 0 +pp_data->cap[14]->NotRange.DesignatorIndex = 0 +pp_data->cap[14]->NotRange.Reserved3 = 0 +pp_data->cap[14]->NotRange.DataIndex = 6 +pp_data->cap[14]->NotRange.Reserved4 = 6 +pp_data->cap[14]->Button.LogicalMin = 0 +pp_data->cap[14]->Button.LogicalMax = 0 +pp_data->cap[14]->Units = 0 +pp_data->cap[14]->UnitsExp = 0 + +pp_data->cap[15]->UsagePage = 0xFFA0 +pp_data->cap[15]->ReportID = 0x1A +pp_data->cap[15]->BitPosition = 0 +pp_data->cap[15]->BitSize = 1 +pp_data->cap[15]->ReportCount = 1 +pp_data->cap[15]->BytePosition = 0x0001 +pp_data->cap[15]->BitCount = 1 +pp_data->cap[15]->BitField = 0x22 +pp_data->cap[15]->NextBytePosition = 0x0002 +pp_data->cap[15]->LinkCollection = 0x0000 +pp_data->cap[15]->LinkUsagePage = 0xFFA0 +pp_data->cap[15]->LinkUsage = 0x0003 +pp_data->cap[15]->IsMultipleItemsForArray = 0 +pp_data->cap[15]->IsButtonCap = 1 +pp_data->cap[15]->IsPadding = 0 +pp_data->cap[15]->IsAbsolute = 1 +pp_data->cap[15]->IsRange = 0 +pp_data->cap[15]->IsAlias = 0 +pp_data->cap[15]->IsStringRange = 0 +pp_data->cap[15]->IsDesignatorRange = 0 +pp_data->cap[15]->Reserved1 = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[15]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[15]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[15]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[15]->NotRange.Usage = 0x00B5 +pp_data->cap[15]->NotRange.Reserved1 = 0x00B5 +pp_data->cap[15]->NotRange.StringIndex = 0 +pp_data->cap[15]->NotRange.Reserved2 = 0 +pp_data->cap[15]->NotRange.DesignatorIndex = 0 +pp_data->cap[15]->NotRange.Reserved3 = 0 +pp_data->cap[15]->NotRange.DataIndex = 7 +pp_data->cap[15]->NotRange.Reserved4 = 7 +pp_data->cap[15]->Button.LogicalMin = 0 +pp_data->cap[15]->Button.LogicalMax = 0 +pp_data->cap[15]->Units = 0 +pp_data->cap[15]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +pp_data->cap[16]->UsagePage = 0xFFA0 +pp_data->cap[16]->ReportID = 0x1B +pp_data->cap[16]->BitPosition = 1 +pp_data->cap[16]->BitSize = 1 +pp_data->cap[16]->ReportCount = 1 +pp_data->cap[16]->BytePosition = 0x0001 +pp_data->cap[16]->BitCount = 1 +pp_data->cap[16]->BitField = 0x22 +pp_data->cap[16]->NextBytePosition = 0x0002 +pp_data->cap[16]->LinkCollection = 0x0000 +pp_data->cap[16]->LinkUsagePage = 0xFFA0 +pp_data->cap[16]->LinkUsage = 0x0003 +pp_data->cap[16]->IsMultipleItemsForArray = 0 +pp_data->cap[16]->IsButtonCap = 1 +pp_data->cap[16]->IsPadding = 0 +pp_data->cap[16]->IsAbsolute = 1 +pp_data->cap[16]->IsRange = 0 +pp_data->cap[16]->IsAlias = 0 +pp_data->cap[16]->IsStringRange = 0 +pp_data->cap[16]->IsDesignatorRange = 0 +pp_data->cap[16]->Reserved1 = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[16]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[16]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[16]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[16]->NotRange.Usage = 0x00B5 +pp_data->cap[16]->NotRange.Reserved1 = 0x00B5 +pp_data->cap[16]->NotRange.StringIndex = 0 +pp_data->cap[16]->NotRange.Reserved2 = 0 +pp_data->cap[16]->NotRange.DesignatorIndex = 0 +pp_data->cap[16]->NotRange.Reserved3 = 0 +pp_data->cap[16]->NotRange.DataIndex = 0 +pp_data->cap[16]->NotRange.Reserved4 = 0 +pp_data->cap[16]->Button.LogicalMin = 0 +pp_data->cap[16]->Button.LogicalMax = 0 +pp_data->cap[16]->Units = 0 +pp_data->cap[16]->UnitsExp = 0 + +pp_data->cap[17]->UsagePage = 0xFFA0 +pp_data->cap[17]->ReportID = 0x1B +pp_data->cap[17]->BitPosition = 0 +pp_data->cap[17]->BitSize = 1 +pp_data->cap[17]->ReportCount = 1 +pp_data->cap[17]->BytePosition = 0x0001 +pp_data->cap[17]->BitCount = 1 +pp_data->cap[17]->BitField = 0x22 +pp_data->cap[17]->NextBytePosition = 0x0002 +pp_data->cap[17]->LinkCollection = 0x0000 +pp_data->cap[17]->LinkUsagePage = 0xFFA0 +pp_data->cap[17]->LinkUsage = 0x0003 +pp_data->cap[17]->IsMultipleItemsForArray = 0 +pp_data->cap[17]->IsButtonCap = 1 +pp_data->cap[17]->IsPadding = 0 +pp_data->cap[17]->IsAbsolute = 1 +pp_data->cap[17]->IsRange = 0 +pp_data->cap[17]->IsAlias = 0 +pp_data->cap[17]->IsStringRange = 0 +pp_data->cap[17]->IsDesignatorRange = 0 +pp_data->cap[17]->Reserved1 = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[17]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[17]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[17]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[17]->NotRange.Usage = 0x00CF +pp_data->cap[17]->NotRange.Reserved1 = 0x00CF +pp_data->cap[17]->NotRange.StringIndex = 0 +pp_data->cap[17]->NotRange.Reserved2 = 0 +pp_data->cap[17]->NotRange.DesignatorIndex = 0 +pp_data->cap[17]->NotRange.Reserved3 = 0 +pp_data->cap[17]->NotRange.DataIndex = 1 +pp_data->cap[17]->NotRange.Reserved4 = 1 +pp_data->cap[17]->Button.LogicalMin = 0 +pp_data->cap[17]->Button.LogicalMax = 0 +pp_data->cap[17]->Units = 0 +pp_data->cap[17]->UnitsExp = 0 + +pp_data->cap[18]->UsagePage = 0xFFA0 +pp_data->cap[18]->ReportID = 0x1B +pp_data->cap[18]->BitPosition = 2 +pp_data->cap[18]->BitSize = 1 +pp_data->cap[18]->ReportCount = 1 +pp_data->cap[18]->BytePosition = 0x0001 +pp_data->cap[18]->BitCount = 1 +pp_data->cap[18]->BitField = 0x23 +pp_data->cap[18]->NextBytePosition = 0x0002 +pp_data->cap[18]->LinkCollection = 0x0000 +pp_data->cap[18]->LinkUsagePage = 0xFFA0 +pp_data->cap[18]->LinkUsage = 0x0003 +pp_data->cap[18]->IsMultipleItemsForArray = 0 +pp_data->cap[18]->IsButtonCap = 1 +pp_data->cap[18]->IsPadding = 1 +pp_data->cap[18]->IsAbsolute = 1 +pp_data->cap[18]->IsRange = 0 +pp_data->cap[18]->IsAlias = 0 +pp_data->cap[18]->IsStringRange = 0 +pp_data->cap[18]->IsDesignatorRange = 0 +pp_data->cap[18]->Reserved1 = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[18]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[18]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[18]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[18]->NotRange.Usage = 0x00DE +pp_data->cap[18]->NotRange.Reserved1 = 0x00DE +pp_data->cap[18]->NotRange.StringIndex = 0 +pp_data->cap[18]->NotRange.Reserved2 = 0 +pp_data->cap[18]->NotRange.DesignatorIndex = 0 +pp_data->cap[18]->NotRange.Reserved3 = 0 +pp_data->cap[18]->NotRange.DataIndex = 2 +pp_data->cap[18]->NotRange.Reserved4 = 2 +pp_data->cap[18]->Button.LogicalMin = 0 +pp_data->cap[18]->Button.LogicalMax = 0 +pp_data->cap[18]->Units = 0 +pp_data->cap[18]->UnitsExp = 0 + +pp_data->cap[19]->UsagePage = 0xFFA0 +pp_data->cap[19]->ReportID = 0x1B +pp_data->cap[19]->BitPosition = 3 +pp_data->cap[19]->BitSize = 1 +pp_data->cap[19]->ReportCount = 1 +pp_data->cap[19]->BytePosition = 0x0001 +pp_data->cap[19]->BitCount = 1 +pp_data->cap[19]->BitField = 0x22 +pp_data->cap[19]->NextBytePosition = 0x0002 +pp_data->cap[19]->LinkCollection = 0x0000 +pp_data->cap[19]->LinkUsagePage = 0xFFA0 +pp_data->cap[19]->LinkUsage = 0x0003 +pp_data->cap[19]->IsMultipleItemsForArray = 0 +pp_data->cap[19]->IsButtonCap = 1 +pp_data->cap[19]->IsPadding = 0 +pp_data->cap[19]->IsAbsolute = 1 +pp_data->cap[19]->IsRange = 0 +pp_data->cap[19]->IsAlias = 0 +pp_data->cap[19]->IsStringRange = 0 +pp_data->cap[19]->IsDesignatorRange = 0 +pp_data->cap[19]->Reserved1 = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[19]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[19]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[19]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[19]->NotRange.Usage = 0x00D8 +pp_data->cap[19]->NotRange.Reserved1 = 0x00D8 +pp_data->cap[19]->NotRange.StringIndex = 0 +pp_data->cap[19]->NotRange.Reserved2 = 0 +pp_data->cap[19]->NotRange.DesignatorIndex = 0 +pp_data->cap[19]->NotRange.Reserved3 = 0 +pp_data->cap[19]->NotRange.DataIndex = 3 +pp_data->cap[19]->NotRange.Reserved4 = 3 +pp_data->cap[19]->Button.LogicalMin = 0 +pp_data->cap[19]->Button.LogicalMax = 0 +pp_data->cap[19]->Units = 0 +pp_data->cap[19]->UnitsExp = 0 + +pp_data->cap[20]->UsagePage = 0xFFA0 +pp_data->cap[20]->ReportID = 0x1B +pp_data->cap[20]->BitPosition = 5 +pp_data->cap[20]->BitSize = 1 +pp_data->cap[20]->ReportCount = 1 +pp_data->cap[20]->BytePosition = 0x0002 +pp_data->cap[20]->BitCount = 1 +pp_data->cap[20]->BitField = 0x22 +pp_data->cap[20]->NextBytePosition = 0x0003 +pp_data->cap[20]->LinkCollection = 0x0000 +pp_data->cap[20]->LinkUsagePage = 0xFFA0 +pp_data->cap[20]->LinkUsage = 0x0003 +pp_data->cap[20]->IsMultipleItemsForArray = 0 +pp_data->cap[20]->IsButtonCap = 1 +pp_data->cap[20]->IsPadding = 0 +pp_data->cap[20]->IsAbsolute = 1 +pp_data->cap[20]->IsRange = 0 +pp_data->cap[20]->IsAlias = 0 +pp_data->cap[20]->IsStringRange = 0 +pp_data->cap[20]->IsDesignatorRange = 0 +pp_data->cap[20]->Reserved1 = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[20]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[20]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[20]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[20]->NotRange.Usage = 0x002A +pp_data->cap[20]->NotRange.Reserved1 = 0x002A +pp_data->cap[20]->NotRange.StringIndex = 0 +pp_data->cap[20]->NotRange.Reserved2 = 0 +pp_data->cap[20]->NotRange.DesignatorIndex = 0 +pp_data->cap[20]->NotRange.Reserved3 = 0 +pp_data->cap[20]->NotRange.DataIndex = 4 +pp_data->cap[20]->NotRange.Reserved4 = 4 +pp_data->cap[20]->Button.LogicalMin = 0 +pp_data->cap[20]->Button.LogicalMax = 0 +pp_data->cap[20]->Units = 0 +pp_data->cap[20]->UnitsExp = 0 + +pp_data->cap[21]->UsagePage = 0xFFA0 +pp_data->cap[21]->ReportID = 0x1B +pp_data->cap[21]->BitPosition = 4 +pp_data->cap[21]->BitSize = 1 +pp_data->cap[21]->ReportCount = 1 +pp_data->cap[21]->BytePosition = 0x0002 +pp_data->cap[21]->BitCount = 1 +pp_data->cap[21]->BitField = 0x22 +pp_data->cap[21]->NextBytePosition = 0x0003 +pp_data->cap[21]->LinkCollection = 0x0000 +pp_data->cap[21]->LinkUsagePage = 0xFFA0 +pp_data->cap[21]->LinkUsage = 0x0003 +pp_data->cap[21]->IsMultipleItemsForArray = 0 +pp_data->cap[21]->IsButtonCap = 1 +pp_data->cap[21]->IsPadding = 0 +pp_data->cap[21]->IsAbsolute = 1 +pp_data->cap[21]->IsRange = 0 +pp_data->cap[21]->IsAlias = 0 +pp_data->cap[21]->IsStringRange = 0 +pp_data->cap[21]->IsDesignatorRange = 0 +pp_data->cap[21]->Reserved1 = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[21]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[21]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[21]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[21]->NotRange.Usage = 0x0020 +pp_data->cap[21]->NotRange.Reserved1 = 0x0020 +pp_data->cap[21]->NotRange.StringIndex = 0 +pp_data->cap[21]->NotRange.Reserved2 = 0 +pp_data->cap[21]->NotRange.DesignatorIndex = 0 +pp_data->cap[21]->NotRange.Reserved3 = 0 +pp_data->cap[21]->NotRange.DataIndex = 5 +pp_data->cap[21]->NotRange.Reserved4 = 5 +pp_data->cap[21]->Button.LogicalMin = 0 +pp_data->cap[21]->Button.LogicalMax = 0 +pp_data->cap[21]->Units = 0 +pp_data->cap[21]->UnitsExp = 0 + +pp_data->cap[22]->UsagePage = 0xFFA0 +pp_data->cap[22]->ReportID = 0x1B +pp_data->cap[22]->BitPosition = 3 +pp_data->cap[22]->BitSize = 1 +pp_data->cap[22]->ReportCount = 1 +pp_data->cap[22]->BytePosition = 0x0002 +pp_data->cap[22]->BitCount = 1 +pp_data->cap[22]->BitField = 0x22 +pp_data->cap[22]->NextBytePosition = 0x0003 +pp_data->cap[22]->LinkCollection = 0x0000 +pp_data->cap[22]->LinkUsagePage = 0xFFA0 +pp_data->cap[22]->LinkUsage = 0x0003 +pp_data->cap[22]->IsMultipleItemsForArray = 0 +pp_data->cap[22]->IsButtonCap = 1 +pp_data->cap[22]->IsPadding = 0 +pp_data->cap[22]->IsAbsolute = 1 +pp_data->cap[22]->IsRange = 0 +pp_data->cap[22]->IsAlias = 0 +pp_data->cap[22]->IsStringRange = 0 +pp_data->cap[22]->IsDesignatorRange = 0 +pp_data->cap[22]->Reserved1 = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[22]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[22]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[22]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[22]->NotRange.Usage = 0x001E +pp_data->cap[22]->NotRange.Reserved1 = 0x001E +pp_data->cap[22]->NotRange.StringIndex = 0 +pp_data->cap[22]->NotRange.Reserved2 = 0 +pp_data->cap[22]->NotRange.DesignatorIndex = 0 +pp_data->cap[22]->NotRange.Reserved3 = 0 +pp_data->cap[22]->NotRange.DataIndex = 6 +pp_data->cap[22]->NotRange.Reserved4 = 6 +pp_data->cap[22]->Button.LogicalMin = 0 +pp_data->cap[22]->Button.LogicalMax = 0 +pp_data->cap[22]->Units = 0 +pp_data->cap[22]->UnitsExp = 0 + +pp_data->cap[23]->UsagePage = 0xFFA0 +pp_data->cap[23]->ReportID = 0x1B +pp_data->cap[23]->BitPosition = 2 +pp_data->cap[23]->BitSize = 1 +pp_data->cap[23]->ReportCount = 1 +pp_data->cap[23]->BytePosition = 0x0002 +pp_data->cap[23]->BitCount = 1 +pp_data->cap[23]->BitField = 0x22 +pp_data->cap[23]->NextBytePosition = 0x0003 +pp_data->cap[23]->LinkCollection = 0x0000 +pp_data->cap[23]->LinkUsagePage = 0xFFA0 +pp_data->cap[23]->LinkUsage = 0x0003 +pp_data->cap[23]->IsMultipleItemsForArray = 0 +pp_data->cap[23]->IsButtonCap = 1 +pp_data->cap[23]->IsPadding = 0 +pp_data->cap[23]->IsAbsolute = 1 +pp_data->cap[23]->IsRange = 0 +pp_data->cap[23]->IsAlias = 0 +pp_data->cap[23]->IsStringRange = 0 +pp_data->cap[23]->IsDesignatorRange = 0 +pp_data->cap[23]->Reserved1 = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[23]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[23]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[23]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[23]->NotRange.Usage = 0x0018 +pp_data->cap[23]->NotRange.Reserved1 = 0x0018 +pp_data->cap[23]->NotRange.StringIndex = 0 +pp_data->cap[23]->NotRange.Reserved2 = 0 +pp_data->cap[23]->NotRange.DesignatorIndex = 0 +pp_data->cap[23]->NotRange.Reserved3 = 0 +pp_data->cap[23]->NotRange.DataIndex = 7 +pp_data->cap[23]->NotRange.Reserved4 = 7 +pp_data->cap[23]->Button.LogicalMin = 0 +pp_data->cap[23]->Button.LogicalMax = 0 +pp_data->cap[23]->Units = 0 +pp_data->cap[23]->UnitsExp = 0 + +pp_data->cap[24]->UsagePage = 0xFFA0 +pp_data->cap[24]->ReportID = 0x1B +pp_data->cap[24]->BitPosition = 1 +pp_data->cap[24]->BitSize = 1 +pp_data->cap[24]->ReportCount = 1 +pp_data->cap[24]->BytePosition = 0x0002 +pp_data->cap[24]->BitCount = 1 +pp_data->cap[24]->BitField = 0x22 +pp_data->cap[24]->NextBytePosition = 0x0003 +pp_data->cap[24]->LinkCollection = 0x0000 +pp_data->cap[24]->LinkUsagePage = 0xFFA0 +pp_data->cap[24]->LinkUsage = 0x0003 +pp_data->cap[24]->IsMultipleItemsForArray = 0 +pp_data->cap[24]->IsButtonCap = 1 +pp_data->cap[24]->IsPadding = 0 +pp_data->cap[24]->IsAbsolute = 1 +pp_data->cap[24]->IsRange = 0 +pp_data->cap[24]->IsAlias = 0 +pp_data->cap[24]->IsStringRange = 0 +pp_data->cap[24]->IsDesignatorRange = 0 +pp_data->cap[24]->Reserved1 = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[24]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[24]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[24]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[24]->NotRange.Usage = 0x0017 +pp_data->cap[24]->NotRange.Reserved1 = 0x0017 +pp_data->cap[24]->NotRange.StringIndex = 0 +pp_data->cap[24]->NotRange.Reserved2 = 0 +pp_data->cap[24]->NotRange.DesignatorIndex = 0 +pp_data->cap[24]->NotRange.Reserved3 = 0 +pp_data->cap[24]->NotRange.DataIndex = 8 +pp_data->cap[24]->NotRange.Reserved4 = 8 +pp_data->cap[24]->Button.LogicalMin = 0 +pp_data->cap[24]->Button.LogicalMax = 0 +pp_data->cap[24]->Units = 0 +pp_data->cap[24]->UnitsExp = 0 + +pp_data->cap[25]->UsagePage = 0xFFA0 +pp_data->cap[25]->ReportID = 0x1B +pp_data->cap[25]->BitPosition = 0 +pp_data->cap[25]->BitSize = 1 +pp_data->cap[25]->ReportCount = 1 +pp_data->cap[25]->BytePosition = 0x0002 +pp_data->cap[25]->BitCount = 1 +pp_data->cap[25]->BitField = 0x22 +pp_data->cap[25]->NextBytePosition = 0x0003 +pp_data->cap[25]->LinkCollection = 0x0000 +pp_data->cap[25]->LinkUsagePage = 0xFFA0 +pp_data->cap[25]->LinkUsage = 0x0003 +pp_data->cap[25]->IsMultipleItemsForArray = 0 +pp_data->cap[25]->IsButtonCap = 1 +pp_data->cap[25]->IsPadding = 0 +pp_data->cap[25]->IsAbsolute = 1 +pp_data->cap[25]->IsRange = 0 +pp_data->cap[25]->IsAlias = 0 +pp_data->cap[25]->IsStringRange = 0 +pp_data->cap[25]->IsDesignatorRange = 0 +pp_data->cap[25]->Reserved1 = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[25]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[25]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[25]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[25]->NotRange.Usage = 0x0009 +pp_data->cap[25]->NotRange.Reserved1 = 0x0009 +pp_data->cap[25]->NotRange.StringIndex = 0 +pp_data->cap[25]->NotRange.Reserved2 = 0 +pp_data->cap[25]->NotRange.DesignatorIndex = 0 +pp_data->cap[25]->NotRange.Reserved3 = 0 +pp_data->cap[25]->NotRange.DataIndex = 9 +pp_data->cap[25]->NotRange.Reserved4 = 9 +pp_data->cap[25]->Button.LogicalMin = 0 +pp_data->cap[25]->Button.LogicalMax = 0 +pp_data->cap[25]->Units = 0 +pp_data->cap[25]->UnitsExp = 0 + +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0003 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFFA0 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/047F_C056_0003_FFA0_expected.rpt_desc b/windows/test/data/047F_C056_0003_FFA0_expected.rpt_desc new file mode 100644 index 000000000..ef059c401 --- /dev/null +++ b/windows/test/data/047F_C056_0003_FFA0_expected.rpt_desc @@ -0,0 +1,24 @@ +0x06, 0xA0, 0xFF, 0x09, 0x03, 0xA1, 0x01, 0x85, 0x03, 0x09, +0x30, 0x15, 0x00, 0x25, 0x01, 0x75, 0x08, 0x95, 0x20, 0x81, +0x02, 0x85, 0x14, 0x09, 0xB1, 0x09, 0xB2, 0x09, 0xB5, 0x09, +0xB7, 0x09, 0xB3, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, +0x05, 0x81, 0x06, 0x75, 0x03, 0x95, 0x01, 0x81, 0x03, 0x85, +0x15, 0x09, 0x8C, 0x15, 0x00, 0x27, 0xFF, 0xFF, 0x00, 0x00, +0x75, 0x10, 0x95, 0x01, 0x81, 0x22, 0x85, 0x1F, 0x09, 0x9C, +0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x81, 0x06, +0x75, 0x07, 0x95, 0x01, 0x81, 0x03, 0x85, 0x03, 0x09, 0x30, +0x15, 0x00, 0x25, 0x01, 0x75, 0x08, 0x95, 0x20, 0x91, 0x02, +0x85, 0x19, 0x09, 0x8D, 0x09, 0x8F, 0x09, 0x9E, 0x09, 0xDC, +0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x04, 0x91, 0x22, +0x09, 0xD2, 0x09, 0xD9, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, +0x95, 0x02, 0x91, 0x06, 0x75, 0x02, 0x95, 0x01, 0x91, 0x03, +0x85, 0x1A, 0x09, 0xB5, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, +0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, 0x91, 0x03, +0x85, 0x1B, 0x09, 0xCF, 0x09, 0xB5, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x02, 0xB1, 0x22, 0x09, 0xDE, 0x15, 0x00, +0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0xB1, 0x23, 0x09, 0xD8, +0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0xB1, 0x22, +0x75, 0x04, 0x95, 0x01, 0xB1, 0x03, 0x09, 0x09, 0x09, 0x17, +0x09, 0x18, 0x09, 0x1E, 0x09, 0x20, 0x09, 0x2A, 0x15, 0x00, +0x25, 0x01, 0x75, 0x01, 0x95, 0x06, 0xB1, 0x22, 0x75, 0x02, +0x95, 0x01, 0xB1, 0x03, 0xC0, \ No newline at end of file diff --git a/windows/test/data/047F_C056_0003_FFA0_real.rpt_desc b/windows/test/data/047F_C056_0003_FFA0_real.rpt_desc new file mode 100644 index 000000000..7532fd12f --- /dev/null +++ b/windows/test/data/047F_C056_0003_FFA0_real.rpt_desc @@ -0,0 +1,113 @@ +macOS USB Prober about 0x047F/0xC056 "Plantronics Blackwire 3220 Series" +06 A0 FF 09 03 A1 01 85 03 09 30 75 +08 95 20 91 02 85 03 09 30 75 08 95 20 81 02 85 +14 09 B1 09 B2 09 B5 09 B7 09 B3 15 00 25 01 75 +01 95 05 81 06 95 03 81 01 85 15 09 8C 15 00 27 +FF FF 00 00 75 10 95 01 81 22 85 19 09 8D 09 8F +09 9E 09 DC 15 00 25 01 75 01 95 04 91 22 09 D2 +09 D9 15 00 25 01 75 01 95 02 91 06 95 02 91 01 +85 1A 09 B5 15 00 25 01 75 01 95 01 91 22 95 07 +91 01 85 1B 09 CF 09 B5 75 01 95 02 B1 22 09 DE +75 01 95 01 B1 23 09 D8 95 01 B1 22 95 04 B1 01 +09 09 09 17 09 18 09 1E 09 20 09 2A 75 01 95 06 +B1 22 95 02 B1 01 85 1F 09 9C 75 01 95 01 81 06 +95 07 81 01 C0 + +Parser output: +0x06, 0xA0, 0xFF, // Usage Page (Vendor Defined 0xFFA0) +0x09, 0x03, // Usage (0x03) +0xA1, 0x01, // Collection (Application) +0x85, 0x03, // Report ID (3) +0x09, 0x30, // Usage (0x30) +0x75, 0x08, // Report Size (8) +0x95, 0x20, // Report Count (32) +0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x03, // Report ID (3) +0x09, 0x30, // Usage (0x30) +0x75, 0x08, // Report Size (8) +0x95, 0x20, // Report Count (32) +0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x85, 0x14, // Report ID (20) +0x09, 0xB1, // Usage (0xB1) +0x09, 0xB2, // Usage (0xB2) +0x09, 0xB5, // Usage (0xB5) +0x09, 0xB7, // Usage (0xB7) +0x09, 0xB3, // Usage (0xB3) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x75, 0x01, // Report Size (1) +0x95, 0x05, // Report Count (5) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x95, 0x03, // Report Count (3) +0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x85, 0x15, // Report ID (21) +0x09, 0x8C, // Usage (0x8C) +0x15, 0x00, // Logical Minimum (0) +0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534) +0x75, 0x10, // Report Size (16) +0x95, 0x01, // Report Count (1) +0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position) +0x85, 0x19, // Report ID (25) +0x09, 0x8D, // Usage (0x8D) +0x09, 0x8F, // Usage (0x8F) +0x09, 0x9E, // Usage (0x9E) +0x09, 0xDC, // Usage (0xDC) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x75, 0x01, // Report Size (1) +0x95, 0x04, // Report Count (4) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x09, 0xD2, // Usage (0xD2) +0x09, 0xD9, // Usage (0xD9) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x75, 0x01, // Report Size (1) +0x95, 0x02, // Report Count (2) +0x91, 0x06, // Output (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x95, 0x02, // Report Count (2) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x1A, // Report ID (26) +0x09, 0xB5, // Usage (0xB5) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x75, 0x01, // Report Size (1) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x1B, // Report ID (27) +0x09, 0xCF, // Usage (0xCF) +0x09, 0xB5, // Usage (0xB5) +0x75, 0x01, // Report Size (1) +0x95, 0x02, // Report Count (2) +0xB1, 0x22, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x09, 0xDE, // Usage (0xDE) +0x75, 0x01, // Report Size (1) +0x95, 0x01, // Report Count (1) +0xB1, 0x23, // Feature (Const,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x09, 0xD8, // Usage (0xD8) +0x95, 0x01, // Report Count (1) +0xB1, 0x22, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x04, // Report Count (4) +0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x09, 0x09, // Usage (0x09) +0x09, 0x17, // Usage (0x17) +0x09, 0x18, // Usage (0x18) +0x09, 0x1E, // Usage (0x1E) +0x09, 0x20, // Usage (0x20) +0x09, 0x2A, // Usage (0x2A) +0x75, 0x01, // Report Size (1) +0x95, 0x06, // Report Count (6) +0xB1, 0x22, // Feature (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x02, // Report Count (2) +0xB1, 0x01, // Feature (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x1F, // Report ID (31) +0x09, 0x9C, // Usage (0x9C) +0x75, 0x01, // Report Size (1) +0x95, 0x01, // Report Count (1) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x95, 0x07, // Report Count (7) +0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0xC0, // End Collection + +// 193 bytes diff --git a/windows/test/data/047F_C056_0005_000B.pp_data b/windows/test/data/047F_C056_0005_000B.pp_data new file mode 100644 index 000000000..583c317e7 --- /dev/null +++ b/windows/test/data/047F_C056_0005_000B.pp_data @@ -0,0 +1,461 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x047F +dev->product_id = 0xC056 +dev->manufacturer_string = "Plantronics" +dev->product_string = "Plantronics Blackwire 3220 Series" +dev->release_number = 0x0210 +dev->interface_number = 3 +dev->usage = 0x0005 +dev->usage_page = 0x000B +dev->path = "\\?\hid#vid_047f&pid_c056&mi_03&col02#f&39e6f119&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0005 +pp_data->UsagePage = 0x000B +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 3 +pp_data->caps_info[0]->NumberOfCaps = 3 +pp_data->caps_info[0]->ReportByteLength = 2 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 3 +pp_data->caps_info[1]->LastCap = 9 +pp_data->caps_info[1]->NumberOfCaps = 6 +pp_data->caps_info[1]->ReportByteLength = 2 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 9 +pp_data->caps_info[2]->LastCap = 9 +pp_data->caps_info[2]->NumberOfCaps = 0 +pp_data->caps_info[2]->ReportByteLength = 0 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x03A8 +pp_data->NumberLinkCollectionNodes = 1 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0x000B +pp_data->cap[0]->ReportID = 0x08 +pp_data->cap[0]->BitPosition = 0 +pp_data->cap[0]->BitSize = 1 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0001 +pp_data->cap[0]->BitCount = 1 +pp_data->cap[0]->BitField = 0x06 +pp_data->cap[0]->NextBytePosition = 0x0002 +pp_data->cap[0]->LinkCollection = 0x0000 +pp_data->cap[0]->LinkUsagePage = 0x000B +pp_data->cap[0]->LinkUsage = 0x0005 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 1 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 0 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x002F +pp_data->cap[0]->NotRange.Reserved1 = 0x002F +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->Button.LogicalMin = 0 +pp_data->cap[0]->Button.LogicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0x000B +pp_data->cap[1]->ReportID = 0x08 +pp_data->cap[1]->BitPosition = 2 +pp_data->cap[1]->BitSize = 1 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0001 +pp_data->cap[1]->BitCount = 1 +pp_data->cap[1]->BitField = 0x22 +pp_data->cap[1]->NextBytePosition = 0x0002 +pp_data->cap[1]->LinkCollection = 0x0000 +pp_data->cap[1]->LinkUsagePage = 0x000B +pp_data->cap[1]->LinkUsage = 0x0005 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 1 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0021 +pp_data->cap[1]->NotRange.Reserved1 = 0x0021 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->Button.LogicalMin = 0 +pp_data->cap[1]->Button.LogicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0x000B +pp_data->cap[2]->ReportID = 0x08 +pp_data->cap[2]->BitPosition = 1 +pp_data->cap[2]->BitSize = 1 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 1 +pp_data->cap[2]->BitField = 0x22 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0000 +pp_data->cap[2]->LinkUsagePage = 0x000B +pp_data->cap[2]->LinkUsage = 0x0005 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 1 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0020 +pp_data->cap[2]->NotRange.Reserved1 = 0x0020 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->Button.LogicalMin = 0 +pp_data->cap[2]->Button.LogicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[3]->UsagePage = 0x0008 +pp_data->cap[3]->ReportID = 0x09 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 1 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0001 +pp_data->cap[3]->BitCount = 1 +pp_data->cap[3]->BitField = 0x22 +pp_data->cap[3]->NextBytePosition = 0x0002 +pp_data->cap[3]->LinkCollection = 0x0000 +pp_data->cap[3]->LinkUsagePage = 0x000B +pp_data->cap[3]->LinkUsage = 0x0005 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 1 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 1 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0009 +pp_data->cap[3]->NotRange.Reserved1 = 0x0009 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 0 +pp_data->cap[3]->NotRange.Reserved4 = 0 +pp_data->cap[3]->Button.LogicalMin = 0 +pp_data->cap[3]->Button.LogicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0x0008 +pp_data->cap[4]->ReportID = 0x17 +pp_data->cap[4]->BitPosition = 0 +pp_data->cap[4]->BitSize = 1 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0001 +pp_data->cap[4]->BitCount = 1 +pp_data->cap[4]->BitField = 0x22 +pp_data->cap[4]->NextBytePosition = 0x0002 +pp_data->cap[4]->LinkCollection = 0x0000 +pp_data->cap[4]->LinkUsagePage = 0x000B +pp_data->cap[4]->LinkUsage = 0x0005 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 1 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 1 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0017 +pp_data->cap[4]->NotRange.Reserved1 = 0x0017 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 1 +pp_data->cap[4]->NotRange.Reserved4 = 1 +pp_data->cap[4]->Button.LogicalMin = 0 +pp_data->cap[4]->Button.LogicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +pp_data->cap[5]->UsagePage = 0x0008 +pp_data->cap[5]->ReportID = 0x18 +pp_data->cap[5]->BitPosition = 0 +pp_data->cap[5]->BitSize = 1 +pp_data->cap[5]->ReportCount = 1 +pp_data->cap[5]->BytePosition = 0x0001 +pp_data->cap[5]->BitCount = 1 +pp_data->cap[5]->BitField = 0x22 +pp_data->cap[5]->NextBytePosition = 0x0002 +pp_data->cap[5]->LinkCollection = 0x0000 +pp_data->cap[5]->LinkUsagePage = 0x000B +pp_data->cap[5]->LinkUsage = 0x0005 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 1 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 1 +pp_data->cap[5]->IsRange = 0 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->NotRange.Usage = 0x0018 +pp_data->cap[5]->NotRange.Reserved1 = 0x0018 +pp_data->cap[5]->NotRange.StringIndex = 0 +pp_data->cap[5]->NotRange.Reserved2 = 0 +pp_data->cap[5]->NotRange.DesignatorIndex = 0 +pp_data->cap[5]->NotRange.Reserved3 = 0 +pp_data->cap[5]->NotRange.DataIndex = 2 +pp_data->cap[5]->NotRange.Reserved4 = 2 +pp_data->cap[5]->Button.LogicalMin = 0 +pp_data->cap[5]->Button.LogicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0x0008 +pp_data->cap[6]->ReportID = 0x1E +pp_data->cap[6]->BitPosition = 0 +pp_data->cap[6]->BitSize = 1 +pp_data->cap[6]->ReportCount = 1 +pp_data->cap[6]->BytePosition = 0x0001 +pp_data->cap[6]->BitCount = 1 +pp_data->cap[6]->BitField = 0x22 +pp_data->cap[6]->NextBytePosition = 0x0002 +pp_data->cap[6]->LinkCollection = 0x0000 +pp_data->cap[6]->LinkUsagePage = 0x000B +pp_data->cap[6]->LinkUsage = 0x0005 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 1 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x001E +pp_data->cap[6]->NotRange.Reserved1 = 0x001E +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 3 +pp_data->cap[6]->NotRange.Reserved4 = 3 +pp_data->cap[6]->Button.LogicalMin = 0 +pp_data->cap[6]->Button.LogicalMax = 0 +pp_data->cap[6]->Units = 0 +pp_data->cap[6]->UnitsExp = 0 + +pp_data->cap[7]->UsagePage = 0x0008 +pp_data->cap[7]->ReportID = 0x20 +pp_data->cap[7]->BitPosition = 0 +pp_data->cap[7]->BitSize = 1 +pp_data->cap[7]->ReportCount = 1 +pp_data->cap[7]->BytePosition = 0x0001 +pp_data->cap[7]->BitCount = 1 +pp_data->cap[7]->BitField = 0x22 +pp_data->cap[7]->NextBytePosition = 0x0002 +pp_data->cap[7]->LinkCollection = 0x0000 +pp_data->cap[7]->LinkUsagePage = 0x000B +pp_data->cap[7]->LinkUsage = 0x0005 +pp_data->cap[7]->IsMultipleItemsForArray = 0 +pp_data->cap[7]->IsButtonCap = 1 +pp_data->cap[7]->IsPadding = 0 +pp_data->cap[7]->IsAbsolute = 1 +pp_data->cap[7]->IsRange = 0 +pp_data->cap[7]->IsAlias = 0 +pp_data->cap[7]->IsStringRange = 0 +pp_data->cap[7]->IsDesignatorRange = 0 +pp_data->cap[7]->Reserved1 = 0x000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[7]->NotRange.Usage = 0x0020 +pp_data->cap[7]->NotRange.Reserved1 = 0x0020 +pp_data->cap[7]->NotRange.StringIndex = 0 +pp_data->cap[7]->NotRange.Reserved2 = 0 +pp_data->cap[7]->NotRange.DesignatorIndex = 0 +pp_data->cap[7]->NotRange.Reserved3 = 0 +pp_data->cap[7]->NotRange.DataIndex = 4 +pp_data->cap[7]->NotRange.Reserved4 = 4 +pp_data->cap[7]->Button.LogicalMin = 0 +pp_data->cap[7]->Button.LogicalMax = 0 +pp_data->cap[7]->Units = 0 +pp_data->cap[7]->UnitsExp = 0 + +pp_data->cap[8]->UsagePage = 0x0008 +pp_data->cap[8]->ReportID = 0x2A +pp_data->cap[8]->BitPosition = 0 +pp_data->cap[8]->BitSize = 1 +pp_data->cap[8]->ReportCount = 1 +pp_data->cap[8]->BytePosition = 0x0001 +pp_data->cap[8]->BitCount = 1 +pp_data->cap[8]->BitField = 0x22 +pp_data->cap[8]->NextBytePosition = 0x0002 +pp_data->cap[8]->LinkCollection = 0x0000 +pp_data->cap[8]->LinkUsagePage = 0x000B +pp_data->cap[8]->LinkUsage = 0x0005 +pp_data->cap[8]->IsMultipleItemsForArray = 0 +pp_data->cap[8]->IsButtonCap = 1 +pp_data->cap[8]->IsPadding = 0 +pp_data->cap[8]->IsAbsolute = 1 +pp_data->cap[8]->IsRange = 0 +pp_data->cap[8]->IsAlias = 0 +pp_data->cap[8]->IsStringRange = 0 +pp_data->cap[8]->IsDesignatorRange = 0 +pp_data->cap[8]->Reserved1 = 0x000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[8]->NotRange.Usage = 0x002A +pp_data->cap[8]->NotRange.Reserved1 = 0x002A +pp_data->cap[8]->NotRange.StringIndex = 0 +pp_data->cap[8]->NotRange.Reserved2 = 0 +pp_data->cap[8]->NotRange.DesignatorIndex = 0 +pp_data->cap[8]->NotRange.Reserved3 = 0 +pp_data->cap[8]->NotRange.DataIndex = 5 +pp_data->cap[8]->NotRange.Reserved4 = 5 +pp_data->cap[8]->Button.LogicalMin = 0 +pp_data->cap[8]->Button.LogicalMax = 0 +pp_data->cap[8]->Units = 0 +pp_data->cap[8]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0005 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0x000B +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 0 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 diff --git a/windows/test/data/047F_C056_0005_000B_expected.rpt_desc b/windows/test/data/047F_C056_0005_000B_expected.rpt_desc new file mode 100644 index 000000000..40962ac65 --- /dev/null +++ b/windows/test/data/047F_C056_0005_000B_expected.rpt_desc @@ -0,0 +1,17 @@ +0x05, 0x0B, 0x09, 0x05, 0xA1, 0x01, 0x85, 0x08, 0x09, 0x2F, +0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x01, 0x81, 0x06, +0x09, 0x20, 0x09, 0x21, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, +0x95, 0x02, 0x81, 0x22, 0x75, 0x05, 0x95, 0x01, 0x81, 0x03, +0x85, 0x09, 0x05, 0x08, 0x09, 0x09, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, +0x91, 0x03, 0x85, 0x17, 0x09, 0x17, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, +0x91, 0x03, 0x85, 0x18, 0x09, 0x18, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, +0x91, 0x03, 0x85, 0x1E, 0x09, 0x1E, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, +0x91, 0x03, 0x85, 0x20, 0x09, 0x20, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, +0x91, 0x03, 0x85, 0x2A, 0x09, 0x2A, 0x15, 0x00, 0x25, 0x01, +0x75, 0x01, 0x95, 0x01, 0x91, 0x22, 0x75, 0x07, 0x95, 0x01, +0x91, 0x03, 0xC0, \ No newline at end of file diff --git a/windows/test/data/047F_C056_0005_000B_real.rpt_desc b/windows/test/data/047F_C056_0005_000B_real.rpt_desc new file mode 100644 index 000000000..2fe387ea3 --- /dev/null +++ b/windows/test/data/047F_C056_0005_000B_real.rpt_desc @@ -0,0 +1,68 @@ +macOS USB Prober about 0x047F/0xC056 "Plantronics Blackwire 3220 Series" +05 0B 09 05 A1 01 85 08 15 +00 25 01 09 2F 75 01 95 01 81 06 09 20 09 21 75 +01 95 02 81 22 95 05 81 01 05 08 85 09 09 09 95 +01 91 22 95 07 91 01 85 17 09 17 95 01 91 22 95 +07 91 01 85 18 09 18 95 01 91 22 95 07 91 01 85 +1E 09 1E 95 01 91 22 95 07 91 01 85 20 09 20 95 +01 91 22 95 07 91 01 85 2A 09 2A 95 01 91 22 95 +07 91 01 C0 + +Parser output: +0x05, 0x0B, // Usage Page (Telephony) +0x09, 0x05, // Usage (Headset) +0xA1, 0x01, // Collection (Application) +0x85, 0x08, // Report ID (8) +0x15, 0x00, // Logical Minimum (0) +0x25, 0x01, // Logical Maximum (1) +0x09, 0x2F, // Usage (Phone Mute) +0x75, 0x01, // Report Size (1) +0x95, 0x01, // Report Count (1) +0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) +0x09, 0x20, // Usage (Hook Switch) +0x09, 0x21, // Usage (Flash) +0x75, 0x01, // Report Size (1) +0x95, 0x02, // Report Count (2) +0x81, 0x22, // Input (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position) +0x95, 0x05, // Report Count (5) +0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) +0x05, 0x08, // Usage Page (LEDs) +0x85, 0x09, // Report ID (9) +0x09, 0x09, // Usage (Mute) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x17, // Report ID (23) +0x09, 0x17, // Usage (Off-Hook) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x18, // Report ID (24) +0x09, 0x18, // Usage (Ring) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x1E, // Report ID (30) +0x09, 0x1E, // Usage (Speaker) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x20, // Report ID (32) +0x09, 0x20, // Usage (Hold) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0x85, 0x2A, // Report ID (42) +0x09, 0x2A, // Usage (On-Line) +0x95, 0x01, // Report Count (1) +0x91, 0x22, // Output (Data,Var,Abs,No Wrap,Linear,No Preferred State,No Null Position,Non-volatile) +0x95, 0x07, // Report Count (7) +0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) +0xC0, // End Collection + +// 109 bytes diff --git a/windows/test/data/17CC_1130_0000_FF01.pp_data b/windows/test/data/17CC_1130_0000_FF01.pp_data new file mode 100644 index 000000000..acab8a6e7 --- /dev/null +++ b/windows/test/data/17CC_1130_0000_FF01.pp_data @@ -0,0 +1,11508 @@ +# HIDAPI device info struct: +dev->vendor_id = 0x17CC +dev->product_id = 0x1130 +dev->manufacturer_string = "Native Instruments" +dev->product_string = "Traktor Kontrol Z2" +dev->release_number = 0x0033 +dev->interface_number = 4 +dev->usage = 0x0000 +dev->usage_page = 0xFF01 +dev->path = "\\?\hid#vid_17cc&pid_1130&mi_04#9&11d406cd&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}" + +# Preparsed Data struct: +pp_data->MagicKey = 0x48696450204B4452 +pp_data->Usage = 0x0000 +pp_data->UsagePage = 0xFF01 +pp_data->Reserved = 0x00000000 +# Input caps_info struct: +pp_data->caps_info[0]->FirstCap = 0 +pp_data->caps_info[0]->LastCap = 86 +pp_data->caps_info[0]->NumberOfCaps = 87 +pp_data->caps_info[0]->ReportByteLength = 53 +# Output caps_info struct: +pp_data->caps_info[1]->FirstCap = 87 +pp_data->caps_info[1]->LastCap = 221 +pp_data->caps_info[1]->NumberOfCaps = 134 +pp_data->caps_info[1]->ReportByteLength = 95 +# Feature caps_info struct: +pp_data->caps_info[2]->FirstCap = 221 +pp_data->caps_info[2]->LastCap = 232 +pp_data->caps_info[2]->NumberOfCaps = 11 +pp_data->caps_info[2]->ReportByteLength = 33 +# LinkCollectionArray Offset & Size: +pp_data->FirstByteOfLinkCollectionArray = 0x5E40 +pp_data->NumberLinkCollectionNodes = 16 +# Input hid_pp_cap struct: +pp_data->cap[0]->UsagePage = 0xFF01 +pp_data->cap[0]->ReportID = 0x01 +pp_data->cap[0]->BitPosition = 4 +pp_data->cap[0]->BitSize = 4 +pp_data->cap[0]->ReportCount = 1 +pp_data->cap[0]->BytePosition = 0x0002 +pp_data->cap[0]->BitCount = 4 +pp_data->cap[0]->BitField = 0x02 +pp_data->cap[0]->NextBytePosition = 0x0003 +pp_data->cap[0]->LinkCollection = 0x0001 +pp_data->cap[0]->LinkUsagePage = 0xFF01 +pp_data->cap[0]->LinkUsage = 0x0001 +pp_data->cap[0]->IsMultipleItemsForArray = 0 +pp_data->cap[0]->IsButtonCap = 0 +pp_data->cap[0]->IsPadding = 0 +pp_data->cap[0]->IsAbsolute = 1 +pp_data->cap[0]->IsRange = 0 +pp_data->cap[0]->IsAlias = 0 +pp_data->cap[0]->IsStringRange = 0 +pp_data->cap[0]->IsDesignatorRange = 0 +pp_data->cap[0]->Reserved1 = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[0]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[0]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[0]->NotRange.Usage = 0x0003 +pp_data->cap[0]->NotRange.Reserved1 = 0x0003 +pp_data->cap[0]->NotRange.StringIndex = 0 +pp_data->cap[0]->NotRange.Reserved2 = 0 +pp_data->cap[0]->NotRange.DesignatorIndex = 0 +pp_data->cap[0]->NotRange.Reserved3 = 0 +pp_data->cap[0]->NotRange.DataIndex = 0 +pp_data->cap[0]->NotRange.Reserved4 = 0 +pp_data->cap[0]->NotButton.HasNull = 0 +pp_data->cap[0]->NotButton.Reserved4 = 0x000000 +pp_data->cap[0]->NotButton.LogicalMin = 0 +pp_data->cap[0]->NotButton.LogicalMax = 15 +pp_data->cap[0]->NotButton.PhysicalMin = 0 +pp_data->cap[0]->NotButton.PhysicalMax = 0 +pp_data->cap[0]->Units = 0 +pp_data->cap[0]->UnitsExp = 0 + +pp_data->cap[1]->UsagePage = 0xFF01 +pp_data->cap[1]->ReportID = 0x01 +pp_data->cap[1]->BitPosition = 0 +pp_data->cap[1]->BitSize = 4 +pp_data->cap[1]->ReportCount = 1 +pp_data->cap[1]->BytePosition = 0x0002 +pp_data->cap[1]->BitCount = 4 +pp_data->cap[1]->BitField = 0x02 +pp_data->cap[1]->NextBytePosition = 0x0003 +pp_data->cap[1]->LinkCollection = 0x0001 +pp_data->cap[1]->LinkUsagePage = 0xFF01 +pp_data->cap[1]->LinkUsage = 0x0001 +pp_data->cap[1]->IsMultipleItemsForArray = 0 +pp_data->cap[1]->IsButtonCap = 0 +pp_data->cap[1]->IsPadding = 0 +pp_data->cap[1]->IsAbsolute = 1 +pp_data->cap[1]->IsRange = 0 +pp_data->cap[1]->IsAlias = 0 +pp_data->cap[1]->IsStringRange = 0 +pp_data->cap[1]->IsDesignatorRange = 0 +pp_data->cap[1]->Reserved1 = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[1]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[1]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[1]->NotRange.Usage = 0x0003 +pp_data->cap[1]->NotRange.Reserved1 = 0x0003 +pp_data->cap[1]->NotRange.StringIndex = 0 +pp_data->cap[1]->NotRange.Reserved2 = 0 +pp_data->cap[1]->NotRange.DesignatorIndex = 0 +pp_data->cap[1]->NotRange.Reserved3 = 0 +pp_data->cap[1]->NotRange.DataIndex = 1 +pp_data->cap[1]->NotRange.Reserved4 = 1 +pp_data->cap[1]->NotButton.HasNull = 0 +pp_data->cap[1]->NotButton.Reserved4 = 0x000000 +pp_data->cap[1]->NotButton.LogicalMin = 0 +pp_data->cap[1]->NotButton.LogicalMax = 15 +pp_data->cap[1]->NotButton.PhysicalMin = 0 +pp_data->cap[1]->NotButton.PhysicalMax = 0 +pp_data->cap[1]->Units = 0 +pp_data->cap[1]->UnitsExp = 0 + +pp_data->cap[2]->UsagePage = 0xFF01 +pp_data->cap[2]->ReportID = 0x01 +pp_data->cap[2]->BitPosition = 4 +pp_data->cap[2]->BitSize = 4 +pp_data->cap[2]->ReportCount = 1 +pp_data->cap[2]->BytePosition = 0x0001 +pp_data->cap[2]->BitCount = 4 +pp_data->cap[2]->BitField = 0x02 +pp_data->cap[2]->NextBytePosition = 0x0002 +pp_data->cap[2]->LinkCollection = 0x0001 +pp_data->cap[2]->LinkUsagePage = 0xFF01 +pp_data->cap[2]->LinkUsage = 0x0001 +pp_data->cap[2]->IsMultipleItemsForArray = 0 +pp_data->cap[2]->IsButtonCap = 0 +pp_data->cap[2]->IsPadding = 0 +pp_data->cap[2]->IsAbsolute = 1 +pp_data->cap[2]->IsRange = 0 +pp_data->cap[2]->IsAlias = 0 +pp_data->cap[2]->IsStringRange = 0 +pp_data->cap[2]->IsDesignatorRange = 0 +pp_data->cap[2]->Reserved1 = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[2]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[2]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[2]->NotRange.Usage = 0x0003 +pp_data->cap[2]->NotRange.Reserved1 = 0x0003 +pp_data->cap[2]->NotRange.StringIndex = 0 +pp_data->cap[2]->NotRange.Reserved2 = 0 +pp_data->cap[2]->NotRange.DesignatorIndex = 0 +pp_data->cap[2]->NotRange.Reserved3 = 0 +pp_data->cap[2]->NotRange.DataIndex = 2 +pp_data->cap[2]->NotRange.Reserved4 = 2 +pp_data->cap[2]->NotButton.HasNull = 0 +pp_data->cap[2]->NotButton.Reserved4 = 0x000000 +pp_data->cap[2]->NotButton.LogicalMin = 0 +pp_data->cap[2]->NotButton.LogicalMax = 15 +pp_data->cap[2]->NotButton.PhysicalMin = 0 +pp_data->cap[2]->NotButton.PhysicalMax = 0 +pp_data->cap[2]->Units = 0 +pp_data->cap[2]->UnitsExp = 0 + +pp_data->cap[3]->UsagePage = 0xFF01 +pp_data->cap[3]->ReportID = 0x01 +pp_data->cap[3]->BitPosition = 0 +pp_data->cap[3]->BitSize = 4 +pp_data->cap[3]->ReportCount = 1 +pp_data->cap[3]->BytePosition = 0x0001 +pp_data->cap[3]->BitCount = 4 +pp_data->cap[3]->BitField = 0x02 +pp_data->cap[3]->NextBytePosition = 0x0002 +pp_data->cap[3]->LinkCollection = 0x0001 +pp_data->cap[3]->LinkUsagePage = 0xFF01 +pp_data->cap[3]->LinkUsage = 0x0001 +pp_data->cap[3]->IsMultipleItemsForArray = 0 +pp_data->cap[3]->IsButtonCap = 0 +pp_data->cap[3]->IsPadding = 0 +pp_data->cap[3]->IsAbsolute = 1 +pp_data->cap[3]->IsRange = 0 +pp_data->cap[3]->IsAlias = 0 +pp_data->cap[3]->IsStringRange = 0 +pp_data->cap[3]->IsDesignatorRange = 0 +pp_data->cap[3]->Reserved1 = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[3]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[3]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[3]->NotRange.Usage = 0x0003 +pp_data->cap[3]->NotRange.Reserved1 = 0x0003 +pp_data->cap[3]->NotRange.StringIndex = 0 +pp_data->cap[3]->NotRange.Reserved2 = 0 +pp_data->cap[3]->NotRange.DesignatorIndex = 0 +pp_data->cap[3]->NotRange.Reserved3 = 0 +pp_data->cap[3]->NotRange.DataIndex = 3 +pp_data->cap[3]->NotRange.Reserved4 = 3 +pp_data->cap[3]->NotButton.HasNull = 0 +pp_data->cap[3]->NotButton.Reserved4 = 0x000000 +pp_data->cap[3]->NotButton.LogicalMin = 0 +pp_data->cap[3]->NotButton.LogicalMax = 15 +pp_data->cap[3]->NotButton.PhysicalMin = 0 +pp_data->cap[3]->NotButton.PhysicalMax = 0 +pp_data->cap[3]->Units = 0 +pp_data->cap[3]->UnitsExp = 0 + +pp_data->cap[4]->UsagePage = 0xFF01 +pp_data->cap[4]->ReportID = 0x01 +pp_data->cap[4]->BitPosition = 7 +pp_data->cap[4]->BitSize = 1 +pp_data->cap[4]->ReportCount = 1 +pp_data->cap[4]->BytePosition = 0x0008 +pp_data->cap[4]->BitCount = 1 +pp_data->cap[4]->BitField = 0x02 +pp_data->cap[4]->NextBytePosition = 0x0009 +pp_data->cap[4]->LinkCollection = 0x0001 +pp_data->cap[4]->LinkUsagePage = 0xFF01 +pp_data->cap[4]->LinkUsage = 0x0001 +pp_data->cap[4]->IsMultipleItemsForArray = 0 +pp_data->cap[4]->IsButtonCap = 1 +pp_data->cap[4]->IsPadding = 0 +pp_data->cap[4]->IsAbsolute = 1 +pp_data->cap[4]->IsRange = 0 +pp_data->cap[4]->IsAlias = 0 +pp_data->cap[4]->IsStringRange = 0 +pp_data->cap[4]->IsDesignatorRange = 0 +pp_data->cap[4]->Reserved1 = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[4]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[4]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[4]->NotRange.Usage = 0x0002 +pp_data->cap[4]->NotRange.Reserved1 = 0x0002 +pp_data->cap[4]->NotRange.StringIndex = 0 +pp_data->cap[4]->NotRange.Reserved2 = 0 +pp_data->cap[4]->NotRange.DesignatorIndex = 0 +pp_data->cap[4]->NotRange.Reserved3 = 0 +pp_data->cap[4]->NotRange.DataIndex = 4 +pp_data->cap[4]->NotRange.Reserved4 = 4 +pp_data->cap[4]->Button.LogicalMin = 0 +pp_data->cap[4]->Button.LogicalMax = 0 +pp_data->cap[4]->Units = 0 +pp_data->cap[4]->UnitsExp = 0 + +pp_data->cap[5]->UsagePage = 0xFF01 +pp_data->cap[5]->ReportID = 0x01 +pp_data->cap[5]->BitPosition = 6 +pp_data->cap[5]->BitSize = 1 +pp_data->cap[5]->ReportCount = 1 +pp_data->cap[5]->BytePosition = 0x0008 +pp_data->cap[5]->BitCount = 1 +pp_data->cap[5]->BitField = 0x02 +pp_data->cap[5]->NextBytePosition = 0x0009 +pp_data->cap[5]->LinkCollection = 0x0001 +pp_data->cap[5]->LinkUsagePage = 0xFF01 +pp_data->cap[5]->LinkUsage = 0x0001 +pp_data->cap[5]->IsMultipleItemsForArray = 0 +pp_data->cap[5]->IsButtonCap = 1 +pp_data->cap[5]->IsPadding = 0 +pp_data->cap[5]->IsAbsolute = 1 +pp_data->cap[5]->IsRange = 0 +pp_data->cap[5]->IsAlias = 0 +pp_data->cap[5]->IsStringRange = 0 +pp_data->cap[5]->IsDesignatorRange = 0 +pp_data->cap[5]->Reserved1 = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[5]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[5]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[5]->NotRange.Usage = 0x0002 +pp_data->cap[5]->NotRange.Reserved1 = 0x0002 +pp_data->cap[5]->NotRange.StringIndex = 0 +pp_data->cap[5]->NotRange.Reserved2 = 0 +pp_data->cap[5]->NotRange.DesignatorIndex = 0 +pp_data->cap[5]->NotRange.Reserved3 = 0 +pp_data->cap[5]->NotRange.DataIndex = 5 +pp_data->cap[5]->NotRange.Reserved4 = 5 +pp_data->cap[5]->Button.LogicalMin = 0 +pp_data->cap[5]->Button.LogicalMax = 0 +pp_data->cap[5]->Units = 0 +pp_data->cap[5]->UnitsExp = 0 + +pp_data->cap[6]->UsagePage = 0xFF01 +pp_data->cap[6]->ReportID = 0x01 +pp_data->cap[6]->BitPosition = 5 +pp_data->cap[6]->BitSize = 1 +pp_data->cap[6]->ReportCount = 1 +pp_data->cap[6]->BytePosition = 0x0008 +pp_data->cap[6]->BitCount = 1 +pp_data->cap[6]->BitField = 0x02 +pp_data->cap[6]->NextBytePosition = 0x0009 +pp_data->cap[6]->LinkCollection = 0x0001 +pp_data->cap[6]->LinkUsagePage = 0xFF01 +pp_data->cap[6]->LinkUsage = 0x0001 +pp_data->cap[6]->IsMultipleItemsForArray = 0 +pp_data->cap[6]->IsButtonCap = 1 +pp_data->cap[6]->IsPadding = 0 +pp_data->cap[6]->IsAbsolute = 1 +pp_data->cap[6]->IsRange = 0 +pp_data->cap[6]->IsAlias = 0 +pp_data->cap[6]->IsStringRange = 0 +pp_data->cap[6]->IsDesignatorRange = 0 +pp_data->cap[6]->Reserved1 = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[6]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[6]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[6]->NotRange.Usage = 0x0002 +pp_data->cap[6]->NotRange.Reserved1 = 0x0002 +pp_data->cap[6]->NotRange.StringIndex = 0 +pp_data->cap[6]->NotRange.Reserved2 = 0 +pp_data->cap[6]->NotRange.DesignatorIndex = 0 +pp_data->cap[6]->NotRange.Reserved3 = 0 +pp_data->cap[6]->NotRange.DataIndex = 6 +pp_data->cap[6]->NotRange.Reserved4 = 6 +pp_data->cap[6]->Button.LogicalMin = 0 +pp_data->cap[6]->Button.LogicalMax = 0 +pp_data->cap[6]->Units = 0 +pp_data->cap[6]->UnitsExp = 0 + +pp_data->cap[7]->UsagePage = 0xFF01 +pp_data->cap[7]->ReportID = 0x01 +pp_data->cap[7]->BitPosition = 4 +pp_data->cap[7]->BitSize = 1 +pp_data->cap[7]->ReportCount = 1 +pp_data->cap[7]->BytePosition = 0x0008 +pp_data->cap[7]->BitCount = 1 +pp_data->cap[7]->BitField = 0x02 +pp_data->cap[7]->NextBytePosition = 0x0009 +pp_data->cap[7]->LinkCollection = 0x0001 +pp_data->cap[7]->LinkUsagePage = 0xFF01 +pp_data->cap[7]->LinkUsage = 0x0001 +pp_data->cap[7]->IsMultipleItemsForArray = 0 +pp_data->cap[7]->IsButtonCap = 1 +pp_data->cap[7]->IsPadding = 0 +pp_data->cap[7]->IsAbsolute = 1 +pp_data->cap[7]->IsRange = 0 +pp_data->cap[7]->IsAlias = 0 +pp_data->cap[7]->IsStringRange = 0 +pp_data->cap[7]->IsDesignatorRange = 0 +pp_data->cap[7]->Reserved1 = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[7]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[7]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[7]->NotRange.Usage = 0x0002 +pp_data->cap[7]->NotRange.Reserved1 = 0x0002 +pp_data->cap[7]->NotRange.StringIndex = 0 +pp_data->cap[7]->NotRange.Reserved2 = 0 +pp_data->cap[7]->NotRange.DesignatorIndex = 0 +pp_data->cap[7]->NotRange.Reserved3 = 0 +pp_data->cap[7]->NotRange.DataIndex = 7 +pp_data->cap[7]->NotRange.Reserved4 = 7 +pp_data->cap[7]->Button.LogicalMin = 0 +pp_data->cap[7]->Button.LogicalMax = 0 +pp_data->cap[7]->Units = 0 +pp_data->cap[7]->UnitsExp = 0 + +pp_data->cap[8]->UsagePage = 0xFF01 +pp_data->cap[8]->ReportID = 0x01 +pp_data->cap[8]->BitPosition = 3 +pp_data->cap[8]->BitSize = 1 +pp_data->cap[8]->ReportCount = 1 +pp_data->cap[8]->BytePosition = 0x0008 +pp_data->cap[8]->BitCount = 1 +pp_data->cap[8]->BitField = 0x02 +pp_data->cap[8]->NextBytePosition = 0x0009 +pp_data->cap[8]->LinkCollection = 0x0001 +pp_data->cap[8]->LinkUsagePage = 0xFF01 +pp_data->cap[8]->LinkUsage = 0x0001 +pp_data->cap[8]->IsMultipleItemsForArray = 0 +pp_data->cap[8]->IsButtonCap = 1 +pp_data->cap[8]->IsPadding = 0 +pp_data->cap[8]->IsAbsolute = 1 +pp_data->cap[8]->IsRange = 0 +pp_data->cap[8]->IsAlias = 0 +pp_data->cap[8]->IsStringRange = 0 +pp_data->cap[8]->IsDesignatorRange = 0 +pp_data->cap[8]->Reserved1 = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[8]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[8]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[8]->NotRange.Usage = 0x0002 +pp_data->cap[8]->NotRange.Reserved1 = 0x0002 +pp_data->cap[8]->NotRange.StringIndex = 0 +pp_data->cap[8]->NotRange.Reserved2 = 0 +pp_data->cap[8]->NotRange.DesignatorIndex = 0 +pp_data->cap[8]->NotRange.Reserved3 = 0 +pp_data->cap[8]->NotRange.DataIndex = 8 +pp_data->cap[8]->NotRange.Reserved4 = 8 +pp_data->cap[8]->Button.LogicalMin = 0 +pp_data->cap[8]->Button.LogicalMax = 0 +pp_data->cap[8]->Units = 0 +pp_data->cap[8]->UnitsExp = 0 + +pp_data->cap[9]->UsagePage = 0xFF01 +pp_data->cap[9]->ReportID = 0x01 +pp_data->cap[9]->BitPosition = 2 +pp_data->cap[9]->BitSize = 1 +pp_data->cap[9]->ReportCount = 1 +pp_data->cap[9]->BytePosition = 0x0008 +pp_data->cap[9]->BitCount = 1 +pp_data->cap[9]->BitField = 0x02 +pp_data->cap[9]->NextBytePosition = 0x0009 +pp_data->cap[9]->LinkCollection = 0x0001 +pp_data->cap[9]->LinkUsagePage = 0xFF01 +pp_data->cap[9]->LinkUsage = 0x0001 +pp_data->cap[9]->IsMultipleItemsForArray = 0 +pp_data->cap[9]->IsButtonCap = 1 +pp_data->cap[9]->IsPadding = 0 +pp_data->cap[9]->IsAbsolute = 1 +pp_data->cap[9]->IsRange = 0 +pp_data->cap[9]->IsAlias = 0 +pp_data->cap[9]->IsStringRange = 0 +pp_data->cap[9]->IsDesignatorRange = 0 +pp_data->cap[9]->Reserved1 = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[9]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[9]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[9]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[9]->NotRange.Usage = 0x0002 +pp_data->cap[9]->NotRange.Reserved1 = 0x0002 +pp_data->cap[9]->NotRange.StringIndex = 0 +pp_data->cap[9]->NotRange.Reserved2 = 0 +pp_data->cap[9]->NotRange.DesignatorIndex = 0 +pp_data->cap[9]->NotRange.Reserved3 = 0 +pp_data->cap[9]->NotRange.DataIndex = 9 +pp_data->cap[9]->NotRange.Reserved4 = 9 +pp_data->cap[9]->Button.LogicalMin = 0 +pp_data->cap[9]->Button.LogicalMax = 0 +pp_data->cap[9]->Units = 0 +pp_data->cap[9]->UnitsExp = 0 + +pp_data->cap[10]->UsagePage = 0xFF01 +pp_data->cap[10]->ReportID = 0x01 +pp_data->cap[10]->BitPosition = 1 +pp_data->cap[10]->BitSize = 1 +pp_data->cap[10]->ReportCount = 1 +pp_data->cap[10]->BytePosition = 0x0008 +pp_data->cap[10]->BitCount = 1 +pp_data->cap[10]->BitField = 0x02 +pp_data->cap[10]->NextBytePosition = 0x0009 +pp_data->cap[10]->LinkCollection = 0x0001 +pp_data->cap[10]->LinkUsagePage = 0xFF01 +pp_data->cap[10]->LinkUsage = 0x0001 +pp_data->cap[10]->IsMultipleItemsForArray = 0 +pp_data->cap[10]->IsButtonCap = 1 +pp_data->cap[10]->IsPadding = 0 +pp_data->cap[10]->IsAbsolute = 1 +pp_data->cap[10]->IsRange = 0 +pp_data->cap[10]->IsAlias = 0 +pp_data->cap[10]->IsStringRange = 0 +pp_data->cap[10]->IsDesignatorRange = 0 +pp_data->cap[10]->Reserved1 = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[10]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[10]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[10]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[10]->NotRange.Usage = 0x0002 +pp_data->cap[10]->NotRange.Reserved1 = 0x0002 +pp_data->cap[10]->NotRange.StringIndex = 0 +pp_data->cap[10]->NotRange.Reserved2 = 0 +pp_data->cap[10]->NotRange.DesignatorIndex = 0 +pp_data->cap[10]->NotRange.Reserved3 = 0 +pp_data->cap[10]->NotRange.DataIndex = 10 +pp_data->cap[10]->NotRange.Reserved4 = 10 +pp_data->cap[10]->Button.LogicalMin = 0 +pp_data->cap[10]->Button.LogicalMax = 0 +pp_data->cap[10]->Units = 0 +pp_data->cap[10]->UnitsExp = 0 + +pp_data->cap[11]->UsagePage = 0xFF01 +pp_data->cap[11]->ReportID = 0x01 +pp_data->cap[11]->BitPosition = 0 +pp_data->cap[11]->BitSize = 1 +pp_data->cap[11]->ReportCount = 1 +pp_data->cap[11]->BytePosition = 0x0008 +pp_data->cap[11]->BitCount = 1 +pp_data->cap[11]->BitField = 0x02 +pp_data->cap[11]->NextBytePosition = 0x0009 +pp_data->cap[11]->LinkCollection = 0x0001 +pp_data->cap[11]->LinkUsagePage = 0xFF01 +pp_data->cap[11]->LinkUsage = 0x0001 +pp_data->cap[11]->IsMultipleItemsForArray = 0 +pp_data->cap[11]->IsButtonCap = 1 +pp_data->cap[11]->IsPadding = 0 +pp_data->cap[11]->IsAbsolute = 1 +pp_data->cap[11]->IsRange = 0 +pp_data->cap[11]->IsAlias = 0 +pp_data->cap[11]->IsStringRange = 0 +pp_data->cap[11]->IsDesignatorRange = 0 +pp_data->cap[11]->Reserved1 = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[11]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[11]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[11]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[11]->NotRange.Usage = 0x0002 +pp_data->cap[11]->NotRange.Reserved1 = 0x0002 +pp_data->cap[11]->NotRange.StringIndex = 0 +pp_data->cap[11]->NotRange.Reserved2 = 0 +pp_data->cap[11]->NotRange.DesignatorIndex = 0 +pp_data->cap[11]->NotRange.Reserved3 = 0 +pp_data->cap[11]->NotRange.DataIndex = 11 +pp_data->cap[11]->NotRange.Reserved4 = 11 +pp_data->cap[11]->Button.LogicalMin = 0 +pp_data->cap[11]->Button.LogicalMax = 0 +pp_data->cap[11]->Units = 0 +pp_data->cap[11]->UnitsExp = 0 + +pp_data->cap[12]->UsagePage = 0xFF01 +pp_data->cap[12]->ReportID = 0x01 +pp_data->cap[12]->BitPosition = 7 +pp_data->cap[12]->BitSize = 1 +pp_data->cap[12]->ReportCount = 1 +pp_data->cap[12]->BytePosition = 0x0007 +pp_data->cap[12]->BitCount = 1 +pp_data->cap[12]->BitField = 0x02 +pp_data->cap[12]->NextBytePosition = 0x0008 +pp_data->cap[12]->LinkCollection = 0x0001 +pp_data->cap[12]->LinkUsagePage = 0xFF01 +pp_data->cap[12]->LinkUsage = 0x0001 +pp_data->cap[12]->IsMultipleItemsForArray = 0 +pp_data->cap[12]->IsButtonCap = 1 +pp_data->cap[12]->IsPadding = 0 +pp_data->cap[12]->IsAbsolute = 1 +pp_data->cap[12]->IsRange = 0 +pp_data->cap[12]->IsAlias = 0 +pp_data->cap[12]->IsStringRange = 0 +pp_data->cap[12]->IsDesignatorRange = 0 +pp_data->cap[12]->Reserved1 = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[12]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[12]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[12]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[12]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[12]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[12]->NotRange.Usage = 0x0002 +pp_data->cap[12]->NotRange.Reserved1 = 0x0002 +pp_data->cap[12]->NotRange.StringIndex = 0 +pp_data->cap[12]->NotRange.Reserved2 = 0 +pp_data->cap[12]->NotRange.DesignatorIndex = 0 +pp_data->cap[12]->NotRange.Reserved3 = 0 +pp_data->cap[12]->NotRange.DataIndex = 12 +pp_data->cap[12]->NotRange.Reserved4 = 12 +pp_data->cap[12]->Button.LogicalMin = 0 +pp_data->cap[12]->Button.LogicalMax = 0 +pp_data->cap[12]->Units = 0 +pp_data->cap[12]->UnitsExp = 0 + +pp_data->cap[13]->UsagePage = 0xFF01 +pp_data->cap[13]->ReportID = 0x01 +pp_data->cap[13]->BitPosition = 6 +pp_data->cap[13]->BitSize = 1 +pp_data->cap[13]->ReportCount = 1 +pp_data->cap[13]->BytePosition = 0x0007 +pp_data->cap[13]->BitCount = 1 +pp_data->cap[13]->BitField = 0x02 +pp_data->cap[13]->NextBytePosition = 0x0008 +pp_data->cap[13]->LinkCollection = 0x0001 +pp_data->cap[13]->LinkUsagePage = 0xFF01 +pp_data->cap[13]->LinkUsage = 0x0001 +pp_data->cap[13]->IsMultipleItemsForArray = 0 +pp_data->cap[13]->IsButtonCap = 1 +pp_data->cap[13]->IsPadding = 0 +pp_data->cap[13]->IsAbsolute = 1 +pp_data->cap[13]->IsRange = 0 +pp_data->cap[13]->IsAlias = 0 +pp_data->cap[13]->IsStringRange = 0 +pp_data->cap[13]->IsDesignatorRange = 0 +pp_data->cap[13]->Reserved1 = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[13]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[13]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[13]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[13]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[13]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[13]->NotRange.Usage = 0x0002 +pp_data->cap[13]->NotRange.Reserved1 = 0x0002 +pp_data->cap[13]->NotRange.StringIndex = 0 +pp_data->cap[13]->NotRange.Reserved2 = 0 +pp_data->cap[13]->NotRange.DesignatorIndex = 0 +pp_data->cap[13]->NotRange.Reserved3 = 0 +pp_data->cap[13]->NotRange.DataIndex = 13 +pp_data->cap[13]->NotRange.Reserved4 = 13 +pp_data->cap[13]->Button.LogicalMin = 0 +pp_data->cap[13]->Button.LogicalMax = 0 +pp_data->cap[13]->Units = 0 +pp_data->cap[13]->UnitsExp = 0 + +pp_data->cap[14]->UsagePage = 0xFF01 +pp_data->cap[14]->ReportID = 0x01 +pp_data->cap[14]->BitPosition = 5 +pp_data->cap[14]->BitSize = 1 +pp_data->cap[14]->ReportCount = 1 +pp_data->cap[14]->BytePosition = 0x0007 +pp_data->cap[14]->BitCount = 1 +pp_data->cap[14]->BitField = 0x02 +pp_data->cap[14]->NextBytePosition = 0x0008 +pp_data->cap[14]->LinkCollection = 0x0001 +pp_data->cap[14]->LinkUsagePage = 0xFF01 +pp_data->cap[14]->LinkUsage = 0x0001 +pp_data->cap[14]->IsMultipleItemsForArray = 0 +pp_data->cap[14]->IsButtonCap = 1 +pp_data->cap[14]->IsPadding = 0 +pp_data->cap[14]->IsAbsolute = 1 +pp_data->cap[14]->IsRange = 0 +pp_data->cap[14]->IsAlias = 0 +pp_data->cap[14]->IsStringRange = 0 +pp_data->cap[14]->IsDesignatorRange = 0 +pp_data->cap[14]->Reserved1 = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[14]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[14]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[14]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[14]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[14]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[14]->NotRange.Usage = 0x0002 +pp_data->cap[14]->NotRange.Reserved1 = 0x0002 +pp_data->cap[14]->NotRange.StringIndex = 0 +pp_data->cap[14]->NotRange.Reserved2 = 0 +pp_data->cap[14]->NotRange.DesignatorIndex = 0 +pp_data->cap[14]->NotRange.Reserved3 = 0 +pp_data->cap[14]->NotRange.DataIndex = 14 +pp_data->cap[14]->NotRange.Reserved4 = 14 +pp_data->cap[14]->Button.LogicalMin = 0 +pp_data->cap[14]->Button.LogicalMax = 0 +pp_data->cap[14]->Units = 0 +pp_data->cap[14]->UnitsExp = 0 + +pp_data->cap[15]->UsagePage = 0xFF01 +pp_data->cap[15]->ReportID = 0x01 +pp_data->cap[15]->BitPosition = 4 +pp_data->cap[15]->BitSize = 1 +pp_data->cap[15]->ReportCount = 1 +pp_data->cap[15]->BytePosition = 0x0007 +pp_data->cap[15]->BitCount = 1 +pp_data->cap[15]->BitField = 0x02 +pp_data->cap[15]->NextBytePosition = 0x0008 +pp_data->cap[15]->LinkCollection = 0x0001 +pp_data->cap[15]->LinkUsagePage = 0xFF01 +pp_data->cap[15]->LinkUsage = 0x0001 +pp_data->cap[15]->IsMultipleItemsForArray = 0 +pp_data->cap[15]->IsButtonCap = 1 +pp_data->cap[15]->IsPadding = 0 +pp_data->cap[15]->IsAbsolute = 1 +pp_data->cap[15]->IsRange = 0 +pp_data->cap[15]->IsAlias = 0 +pp_data->cap[15]->IsStringRange = 0 +pp_data->cap[15]->IsDesignatorRange = 0 +pp_data->cap[15]->Reserved1 = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[15]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[15]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[15]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[15]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[15]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[15]->NotRange.Usage = 0x0002 +pp_data->cap[15]->NotRange.Reserved1 = 0x0002 +pp_data->cap[15]->NotRange.StringIndex = 0 +pp_data->cap[15]->NotRange.Reserved2 = 0 +pp_data->cap[15]->NotRange.DesignatorIndex = 0 +pp_data->cap[15]->NotRange.Reserved3 = 0 +pp_data->cap[15]->NotRange.DataIndex = 15 +pp_data->cap[15]->NotRange.Reserved4 = 15 +pp_data->cap[15]->Button.LogicalMin = 0 +pp_data->cap[15]->Button.LogicalMax = 0 +pp_data->cap[15]->Units = 0 +pp_data->cap[15]->UnitsExp = 0 + +pp_data->cap[16]->UsagePage = 0xFF01 +pp_data->cap[16]->ReportID = 0x01 +pp_data->cap[16]->BitPosition = 3 +pp_data->cap[16]->BitSize = 1 +pp_data->cap[16]->ReportCount = 1 +pp_data->cap[16]->BytePosition = 0x0007 +pp_data->cap[16]->BitCount = 1 +pp_data->cap[16]->BitField = 0x02 +pp_data->cap[16]->NextBytePosition = 0x0008 +pp_data->cap[16]->LinkCollection = 0x0001 +pp_data->cap[16]->LinkUsagePage = 0xFF01 +pp_data->cap[16]->LinkUsage = 0x0001 +pp_data->cap[16]->IsMultipleItemsForArray = 0 +pp_data->cap[16]->IsButtonCap = 1 +pp_data->cap[16]->IsPadding = 0 +pp_data->cap[16]->IsAbsolute = 1 +pp_data->cap[16]->IsRange = 0 +pp_data->cap[16]->IsAlias = 0 +pp_data->cap[16]->IsStringRange = 0 +pp_data->cap[16]->IsDesignatorRange = 0 +pp_data->cap[16]->Reserved1 = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[16]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[16]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[16]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[16]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[16]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[16]->NotRange.Usage = 0x0002 +pp_data->cap[16]->NotRange.Reserved1 = 0x0002 +pp_data->cap[16]->NotRange.StringIndex = 0 +pp_data->cap[16]->NotRange.Reserved2 = 0 +pp_data->cap[16]->NotRange.DesignatorIndex = 0 +pp_data->cap[16]->NotRange.Reserved3 = 0 +pp_data->cap[16]->NotRange.DataIndex = 16 +pp_data->cap[16]->NotRange.Reserved4 = 16 +pp_data->cap[16]->Button.LogicalMin = 0 +pp_data->cap[16]->Button.LogicalMax = 0 +pp_data->cap[16]->Units = 0 +pp_data->cap[16]->UnitsExp = 0 + +pp_data->cap[17]->UsagePage = 0xFF01 +pp_data->cap[17]->ReportID = 0x01 +pp_data->cap[17]->BitPosition = 2 +pp_data->cap[17]->BitSize = 1 +pp_data->cap[17]->ReportCount = 1 +pp_data->cap[17]->BytePosition = 0x0007 +pp_data->cap[17]->BitCount = 1 +pp_data->cap[17]->BitField = 0x02 +pp_data->cap[17]->NextBytePosition = 0x0008 +pp_data->cap[17]->LinkCollection = 0x0001 +pp_data->cap[17]->LinkUsagePage = 0xFF01 +pp_data->cap[17]->LinkUsage = 0x0001 +pp_data->cap[17]->IsMultipleItemsForArray = 0 +pp_data->cap[17]->IsButtonCap = 1 +pp_data->cap[17]->IsPadding = 0 +pp_data->cap[17]->IsAbsolute = 1 +pp_data->cap[17]->IsRange = 0 +pp_data->cap[17]->IsAlias = 0 +pp_data->cap[17]->IsStringRange = 0 +pp_data->cap[17]->IsDesignatorRange = 0 +pp_data->cap[17]->Reserved1 = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[17]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[17]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[17]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[17]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[17]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[17]->NotRange.Usage = 0x0002 +pp_data->cap[17]->NotRange.Reserved1 = 0x0002 +pp_data->cap[17]->NotRange.StringIndex = 0 +pp_data->cap[17]->NotRange.Reserved2 = 0 +pp_data->cap[17]->NotRange.DesignatorIndex = 0 +pp_data->cap[17]->NotRange.Reserved3 = 0 +pp_data->cap[17]->NotRange.DataIndex = 17 +pp_data->cap[17]->NotRange.Reserved4 = 17 +pp_data->cap[17]->Button.LogicalMin = 0 +pp_data->cap[17]->Button.LogicalMax = 0 +pp_data->cap[17]->Units = 0 +pp_data->cap[17]->UnitsExp = 0 + +pp_data->cap[18]->UsagePage = 0xFF01 +pp_data->cap[18]->ReportID = 0x01 +pp_data->cap[18]->BitPosition = 1 +pp_data->cap[18]->BitSize = 1 +pp_data->cap[18]->ReportCount = 1 +pp_data->cap[18]->BytePosition = 0x0007 +pp_data->cap[18]->BitCount = 1 +pp_data->cap[18]->BitField = 0x02 +pp_data->cap[18]->NextBytePosition = 0x0008 +pp_data->cap[18]->LinkCollection = 0x0001 +pp_data->cap[18]->LinkUsagePage = 0xFF01 +pp_data->cap[18]->LinkUsage = 0x0001 +pp_data->cap[18]->IsMultipleItemsForArray = 0 +pp_data->cap[18]->IsButtonCap = 1 +pp_data->cap[18]->IsPadding = 0 +pp_data->cap[18]->IsAbsolute = 1 +pp_data->cap[18]->IsRange = 0 +pp_data->cap[18]->IsAlias = 0 +pp_data->cap[18]->IsStringRange = 0 +pp_data->cap[18]->IsDesignatorRange = 0 +pp_data->cap[18]->Reserved1 = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[18]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[18]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[18]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[18]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[18]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[18]->NotRange.Usage = 0x0002 +pp_data->cap[18]->NotRange.Reserved1 = 0x0002 +pp_data->cap[18]->NotRange.StringIndex = 0 +pp_data->cap[18]->NotRange.Reserved2 = 0 +pp_data->cap[18]->NotRange.DesignatorIndex = 0 +pp_data->cap[18]->NotRange.Reserved3 = 0 +pp_data->cap[18]->NotRange.DataIndex = 18 +pp_data->cap[18]->NotRange.Reserved4 = 18 +pp_data->cap[18]->Button.LogicalMin = 0 +pp_data->cap[18]->Button.LogicalMax = 0 +pp_data->cap[18]->Units = 0 +pp_data->cap[18]->UnitsExp = 0 + +pp_data->cap[19]->UsagePage = 0xFF01 +pp_data->cap[19]->ReportID = 0x01 +pp_data->cap[19]->BitPosition = 0 +pp_data->cap[19]->BitSize = 1 +pp_data->cap[19]->ReportCount = 1 +pp_data->cap[19]->BytePosition = 0x0007 +pp_data->cap[19]->BitCount = 1 +pp_data->cap[19]->BitField = 0x02 +pp_data->cap[19]->NextBytePosition = 0x0008 +pp_data->cap[19]->LinkCollection = 0x0001 +pp_data->cap[19]->LinkUsagePage = 0xFF01 +pp_data->cap[19]->LinkUsage = 0x0001 +pp_data->cap[19]->IsMultipleItemsForArray = 0 +pp_data->cap[19]->IsButtonCap = 1 +pp_data->cap[19]->IsPadding = 0 +pp_data->cap[19]->IsAbsolute = 1 +pp_data->cap[19]->IsRange = 0 +pp_data->cap[19]->IsAlias = 0 +pp_data->cap[19]->IsStringRange = 0 +pp_data->cap[19]->IsDesignatorRange = 0 +pp_data->cap[19]->Reserved1 = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[19]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[19]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[19]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[19]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[19]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[19]->NotRange.Usage = 0x0002 +pp_data->cap[19]->NotRange.Reserved1 = 0x0002 +pp_data->cap[19]->NotRange.StringIndex = 0 +pp_data->cap[19]->NotRange.Reserved2 = 0 +pp_data->cap[19]->NotRange.DesignatorIndex = 0 +pp_data->cap[19]->NotRange.Reserved3 = 0 +pp_data->cap[19]->NotRange.DataIndex = 19 +pp_data->cap[19]->NotRange.Reserved4 = 19 +pp_data->cap[19]->Button.LogicalMin = 0 +pp_data->cap[19]->Button.LogicalMax = 0 +pp_data->cap[19]->Units = 0 +pp_data->cap[19]->UnitsExp = 0 + +pp_data->cap[20]->UsagePage = 0xFF01 +pp_data->cap[20]->ReportID = 0x01 +pp_data->cap[20]->BitPosition = 7 +pp_data->cap[20]->BitSize = 1 +pp_data->cap[20]->ReportCount = 1 +pp_data->cap[20]->BytePosition = 0x0006 +pp_data->cap[20]->BitCount = 1 +pp_data->cap[20]->BitField = 0x02 +pp_data->cap[20]->NextBytePosition = 0x0007 +pp_data->cap[20]->LinkCollection = 0x0001 +pp_data->cap[20]->LinkUsagePage = 0xFF01 +pp_data->cap[20]->LinkUsage = 0x0001 +pp_data->cap[20]->IsMultipleItemsForArray = 0 +pp_data->cap[20]->IsButtonCap = 1 +pp_data->cap[20]->IsPadding = 0 +pp_data->cap[20]->IsAbsolute = 1 +pp_data->cap[20]->IsRange = 0 +pp_data->cap[20]->IsAlias = 0 +pp_data->cap[20]->IsStringRange = 0 +pp_data->cap[20]->IsDesignatorRange = 0 +pp_data->cap[20]->Reserved1 = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[20]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[20]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[20]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[20]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[20]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[20]->NotRange.Usage = 0x0002 +pp_data->cap[20]->NotRange.Reserved1 = 0x0002 +pp_data->cap[20]->NotRange.StringIndex = 0 +pp_data->cap[20]->NotRange.Reserved2 = 0 +pp_data->cap[20]->NotRange.DesignatorIndex = 0 +pp_data->cap[20]->NotRange.Reserved3 = 0 +pp_data->cap[20]->NotRange.DataIndex = 20 +pp_data->cap[20]->NotRange.Reserved4 = 20 +pp_data->cap[20]->Button.LogicalMin = 0 +pp_data->cap[20]->Button.LogicalMax = 0 +pp_data->cap[20]->Units = 0 +pp_data->cap[20]->UnitsExp = 0 + +pp_data->cap[21]->UsagePage = 0xFF01 +pp_data->cap[21]->ReportID = 0x01 +pp_data->cap[21]->BitPosition = 6 +pp_data->cap[21]->BitSize = 1 +pp_data->cap[21]->ReportCount = 1 +pp_data->cap[21]->BytePosition = 0x0006 +pp_data->cap[21]->BitCount = 1 +pp_data->cap[21]->BitField = 0x02 +pp_data->cap[21]->NextBytePosition = 0x0007 +pp_data->cap[21]->LinkCollection = 0x0001 +pp_data->cap[21]->LinkUsagePage = 0xFF01 +pp_data->cap[21]->LinkUsage = 0x0001 +pp_data->cap[21]->IsMultipleItemsForArray = 0 +pp_data->cap[21]->IsButtonCap = 1 +pp_data->cap[21]->IsPadding = 0 +pp_data->cap[21]->IsAbsolute = 1 +pp_data->cap[21]->IsRange = 0 +pp_data->cap[21]->IsAlias = 0 +pp_data->cap[21]->IsStringRange = 0 +pp_data->cap[21]->IsDesignatorRange = 0 +pp_data->cap[21]->Reserved1 = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[21]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[21]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[21]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[21]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[21]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[21]->NotRange.Usage = 0x0002 +pp_data->cap[21]->NotRange.Reserved1 = 0x0002 +pp_data->cap[21]->NotRange.StringIndex = 0 +pp_data->cap[21]->NotRange.Reserved2 = 0 +pp_data->cap[21]->NotRange.DesignatorIndex = 0 +pp_data->cap[21]->NotRange.Reserved3 = 0 +pp_data->cap[21]->NotRange.DataIndex = 21 +pp_data->cap[21]->NotRange.Reserved4 = 21 +pp_data->cap[21]->Button.LogicalMin = 0 +pp_data->cap[21]->Button.LogicalMax = 0 +pp_data->cap[21]->Units = 0 +pp_data->cap[21]->UnitsExp = 0 + +pp_data->cap[22]->UsagePage = 0xFF01 +pp_data->cap[22]->ReportID = 0x01 +pp_data->cap[22]->BitPosition = 5 +pp_data->cap[22]->BitSize = 1 +pp_data->cap[22]->ReportCount = 1 +pp_data->cap[22]->BytePosition = 0x0006 +pp_data->cap[22]->BitCount = 1 +pp_data->cap[22]->BitField = 0x02 +pp_data->cap[22]->NextBytePosition = 0x0007 +pp_data->cap[22]->LinkCollection = 0x0001 +pp_data->cap[22]->LinkUsagePage = 0xFF01 +pp_data->cap[22]->LinkUsage = 0x0001 +pp_data->cap[22]->IsMultipleItemsForArray = 0 +pp_data->cap[22]->IsButtonCap = 1 +pp_data->cap[22]->IsPadding = 0 +pp_data->cap[22]->IsAbsolute = 1 +pp_data->cap[22]->IsRange = 0 +pp_data->cap[22]->IsAlias = 0 +pp_data->cap[22]->IsStringRange = 0 +pp_data->cap[22]->IsDesignatorRange = 0 +pp_data->cap[22]->Reserved1 = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[22]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[22]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[22]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[22]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[22]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[22]->NotRange.Usage = 0x0002 +pp_data->cap[22]->NotRange.Reserved1 = 0x0002 +pp_data->cap[22]->NotRange.StringIndex = 0 +pp_data->cap[22]->NotRange.Reserved2 = 0 +pp_data->cap[22]->NotRange.DesignatorIndex = 0 +pp_data->cap[22]->NotRange.Reserved3 = 0 +pp_data->cap[22]->NotRange.DataIndex = 22 +pp_data->cap[22]->NotRange.Reserved4 = 22 +pp_data->cap[22]->Button.LogicalMin = 0 +pp_data->cap[22]->Button.LogicalMax = 0 +pp_data->cap[22]->Units = 0 +pp_data->cap[22]->UnitsExp = 0 + +pp_data->cap[23]->UsagePage = 0xFF01 +pp_data->cap[23]->ReportID = 0x01 +pp_data->cap[23]->BitPosition = 4 +pp_data->cap[23]->BitSize = 1 +pp_data->cap[23]->ReportCount = 1 +pp_data->cap[23]->BytePosition = 0x0006 +pp_data->cap[23]->BitCount = 1 +pp_data->cap[23]->BitField = 0x02 +pp_data->cap[23]->NextBytePosition = 0x0007 +pp_data->cap[23]->LinkCollection = 0x0001 +pp_data->cap[23]->LinkUsagePage = 0xFF01 +pp_data->cap[23]->LinkUsage = 0x0001 +pp_data->cap[23]->IsMultipleItemsForArray = 0 +pp_data->cap[23]->IsButtonCap = 1 +pp_data->cap[23]->IsPadding = 0 +pp_data->cap[23]->IsAbsolute = 1 +pp_data->cap[23]->IsRange = 0 +pp_data->cap[23]->IsAlias = 0 +pp_data->cap[23]->IsStringRange = 0 +pp_data->cap[23]->IsDesignatorRange = 0 +pp_data->cap[23]->Reserved1 = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[23]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[23]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[23]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[23]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[23]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[23]->NotRange.Usage = 0x0002 +pp_data->cap[23]->NotRange.Reserved1 = 0x0002 +pp_data->cap[23]->NotRange.StringIndex = 0 +pp_data->cap[23]->NotRange.Reserved2 = 0 +pp_data->cap[23]->NotRange.DesignatorIndex = 0 +pp_data->cap[23]->NotRange.Reserved3 = 0 +pp_data->cap[23]->NotRange.DataIndex = 23 +pp_data->cap[23]->NotRange.Reserved4 = 23 +pp_data->cap[23]->Button.LogicalMin = 0 +pp_data->cap[23]->Button.LogicalMax = 0 +pp_data->cap[23]->Units = 0 +pp_data->cap[23]->UnitsExp = 0 + +pp_data->cap[24]->UsagePage = 0xFF01 +pp_data->cap[24]->ReportID = 0x01 +pp_data->cap[24]->BitPosition = 3 +pp_data->cap[24]->BitSize = 1 +pp_data->cap[24]->ReportCount = 1 +pp_data->cap[24]->BytePosition = 0x0006 +pp_data->cap[24]->BitCount = 1 +pp_data->cap[24]->BitField = 0x02 +pp_data->cap[24]->NextBytePosition = 0x0007 +pp_data->cap[24]->LinkCollection = 0x0001 +pp_data->cap[24]->LinkUsagePage = 0xFF01 +pp_data->cap[24]->LinkUsage = 0x0001 +pp_data->cap[24]->IsMultipleItemsForArray = 0 +pp_data->cap[24]->IsButtonCap = 1 +pp_data->cap[24]->IsPadding = 0 +pp_data->cap[24]->IsAbsolute = 1 +pp_data->cap[24]->IsRange = 0 +pp_data->cap[24]->IsAlias = 0 +pp_data->cap[24]->IsStringRange = 0 +pp_data->cap[24]->IsDesignatorRange = 0 +pp_data->cap[24]->Reserved1 = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[24]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[24]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[24]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[24]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[24]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[24]->NotRange.Usage = 0x0002 +pp_data->cap[24]->NotRange.Reserved1 = 0x0002 +pp_data->cap[24]->NotRange.StringIndex = 0 +pp_data->cap[24]->NotRange.Reserved2 = 0 +pp_data->cap[24]->NotRange.DesignatorIndex = 0 +pp_data->cap[24]->NotRange.Reserved3 = 0 +pp_data->cap[24]->NotRange.DataIndex = 24 +pp_data->cap[24]->NotRange.Reserved4 = 24 +pp_data->cap[24]->Button.LogicalMin = 0 +pp_data->cap[24]->Button.LogicalMax = 0 +pp_data->cap[24]->Units = 0 +pp_data->cap[24]->UnitsExp = 0 + +pp_data->cap[25]->UsagePage = 0xFF01 +pp_data->cap[25]->ReportID = 0x01 +pp_data->cap[25]->BitPosition = 2 +pp_data->cap[25]->BitSize = 1 +pp_data->cap[25]->ReportCount = 1 +pp_data->cap[25]->BytePosition = 0x0006 +pp_data->cap[25]->BitCount = 1 +pp_data->cap[25]->BitField = 0x02 +pp_data->cap[25]->NextBytePosition = 0x0007 +pp_data->cap[25]->LinkCollection = 0x0001 +pp_data->cap[25]->LinkUsagePage = 0xFF01 +pp_data->cap[25]->LinkUsage = 0x0001 +pp_data->cap[25]->IsMultipleItemsForArray = 0 +pp_data->cap[25]->IsButtonCap = 1 +pp_data->cap[25]->IsPadding = 0 +pp_data->cap[25]->IsAbsolute = 1 +pp_data->cap[25]->IsRange = 0 +pp_data->cap[25]->IsAlias = 0 +pp_data->cap[25]->IsStringRange = 0 +pp_data->cap[25]->IsDesignatorRange = 0 +pp_data->cap[25]->Reserved1 = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[25]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[25]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[25]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[25]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[25]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[25]->NotRange.Usage = 0x0002 +pp_data->cap[25]->NotRange.Reserved1 = 0x0002 +pp_data->cap[25]->NotRange.StringIndex = 0 +pp_data->cap[25]->NotRange.Reserved2 = 0 +pp_data->cap[25]->NotRange.DesignatorIndex = 0 +pp_data->cap[25]->NotRange.Reserved3 = 0 +pp_data->cap[25]->NotRange.DataIndex = 25 +pp_data->cap[25]->NotRange.Reserved4 = 25 +pp_data->cap[25]->Button.LogicalMin = 0 +pp_data->cap[25]->Button.LogicalMax = 0 +pp_data->cap[25]->Units = 0 +pp_data->cap[25]->UnitsExp = 0 + +pp_data->cap[26]->UsagePage = 0xFF01 +pp_data->cap[26]->ReportID = 0x01 +pp_data->cap[26]->BitPosition = 1 +pp_data->cap[26]->BitSize = 1 +pp_data->cap[26]->ReportCount = 1 +pp_data->cap[26]->BytePosition = 0x0006 +pp_data->cap[26]->BitCount = 1 +pp_data->cap[26]->BitField = 0x02 +pp_data->cap[26]->NextBytePosition = 0x0007 +pp_data->cap[26]->LinkCollection = 0x0001 +pp_data->cap[26]->LinkUsagePage = 0xFF01 +pp_data->cap[26]->LinkUsage = 0x0001 +pp_data->cap[26]->IsMultipleItemsForArray = 0 +pp_data->cap[26]->IsButtonCap = 1 +pp_data->cap[26]->IsPadding = 0 +pp_data->cap[26]->IsAbsolute = 1 +pp_data->cap[26]->IsRange = 0 +pp_data->cap[26]->IsAlias = 0 +pp_data->cap[26]->IsStringRange = 0 +pp_data->cap[26]->IsDesignatorRange = 0 +pp_data->cap[26]->Reserved1 = 0x000000 +pp_data->cap[26]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[26]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[26]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[26]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[26]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[26]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[26]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[26]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[26]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[26]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[26]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[26]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[26]->NotRange.Usage = 0x0002 +pp_data->cap[26]->NotRange.Reserved1 = 0x0002 +pp_data->cap[26]->NotRange.StringIndex = 0 +pp_data->cap[26]->NotRange.Reserved2 = 0 +pp_data->cap[26]->NotRange.DesignatorIndex = 0 +pp_data->cap[26]->NotRange.Reserved3 = 0 +pp_data->cap[26]->NotRange.DataIndex = 26 +pp_data->cap[26]->NotRange.Reserved4 = 26 +pp_data->cap[26]->Button.LogicalMin = 0 +pp_data->cap[26]->Button.LogicalMax = 0 +pp_data->cap[26]->Units = 0 +pp_data->cap[26]->UnitsExp = 0 + +pp_data->cap[27]->UsagePage = 0xFF01 +pp_data->cap[27]->ReportID = 0x01 +pp_data->cap[27]->BitPosition = 0 +pp_data->cap[27]->BitSize = 1 +pp_data->cap[27]->ReportCount = 1 +pp_data->cap[27]->BytePosition = 0x0006 +pp_data->cap[27]->BitCount = 1 +pp_data->cap[27]->BitField = 0x02 +pp_data->cap[27]->NextBytePosition = 0x0007 +pp_data->cap[27]->LinkCollection = 0x0001 +pp_data->cap[27]->LinkUsagePage = 0xFF01 +pp_data->cap[27]->LinkUsage = 0x0001 +pp_data->cap[27]->IsMultipleItemsForArray = 0 +pp_data->cap[27]->IsButtonCap = 1 +pp_data->cap[27]->IsPadding = 0 +pp_data->cap[27]->IsAbsolute = 1 +pp_data->cap[27]->IsRange = 0 +pp_data->cap[27]->IsAlias = 0 +pp_data->cap[27]->IsStringRange = 0 +pp_data->cap[27]->IsDesignatorRange = 0 +pp_data->cap[27]->Reserved1 = 0x000000 +pp_data->cap[27]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[27]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[27]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[27]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[27]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[27]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[27]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[27]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[27]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[27]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[27]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[27]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[27]->NotRange.Usage = 0x0002 +pp_data->cap[27]->NotRange.Reserved1 = 0x0002 +pp_data->cap[27]->NotRange.StringIndex = 0 +pp_data->cap[27]->NotRange.Reserved2 = 0 +pp_data->cap[27]->NotRange.DesignatorIndex = 0 +pp_data->cap[27]->NotRange.Reserved3 = 0 +pp_data->cap[27]->NotRange.DataIndex = 27 +pp_data->cap[27]->NotRange.Reserved4 = 27 +pp_data->cap[27]->Button.LogicalMin = 0 +pp_data->cap[27]->Button.LogicalMax = 0 +pp_data->cap[27]->Units = 0 +pp_data->cap[27]->UnitsExp = 0 + +pp_data->cap[28]->UsagePage = 0xFF01 +pp_data->cap[28]->ReportID = 0x01 +pp_data->cap[28]->BitPosition = 7 +pp_data->cap[28]->BitSize = 1 +pp_data->cap[28]->ReportCount = 1 +pp_data->cap[28]->BytePosition = 0x0005 +pp_data->cap[28]->BitCount = 1 +pp_data->cap[28]->BitField = 0x02 +pp_data->cap[28]->NextBytePosition = 0x0006 +pp_data->cap[28]->LinkCollection = 0x0001 +pp_data->cap[28]->LinkUsagePage = 0xFF01 +pp_data->cap[28]->LinkUsage = 0x0001 +pp_data->cap[28]->IsMultipleItemsForArray = 0 +pp_data->cap[28]->IsButtonCap = 1 +pp_data->cap[28]->IsPadding = 0 +pp_data->cap[28]->IsAbsolute = 1 +pp_data->cap[28]->IsRange = 0 +pp_data->cap[28]->IsAlias = 0 +pp_data->cap[28]->IsStringRange = 0 +pp_data->cap[28]->IsDesignatorRange = 0 +pp_data->cap[28]->Reserved1 = 0x000000 +pp_data->cap[28]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[28]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[28]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[28]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[28]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[28]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[28]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[28]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[28]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[28]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[28]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[28]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[28]->NotRange.Usage = 0x0002 +pp_data->cap[28]->NotRange.Reserved1 = 0x0002 +pp_data->cap[28]->NotRange.StringIndex = 0 +pp_data->cap[28]->NotRange.Reserved2 = 0 +pp_data->cap[28]->NotRange.DesignatorIndex = 0 +pp_data->cap[28]->NotRange.Reserved3 = 0 +pp_data->cap[28]->NotRange.DataIndex = 28 +pp_data->cap[28]->NotRange.Reserved4 = 28 +pp_data->cap[28]->Button.LogicalMin = 0 +pp_data->cap[28]->Button.LogicalMax = 0 +pp_data->cap[28]->Units = 0 +pp_data->cap[28]->UnitsExp = 0 + +pp_data->cap[29]->UsagePage = 0xFF01 +pp_data->cap[29]->ReportID = 0x01 +pp_data->cap[29]->BitPosition = 6 +pp_data->cap[29]->BitSize = 1 +pp_data->cap[29]->ReportCount = 1 +pp_data->cap[29]->BytePosition = 0x0005 +pp_data->cap[29]->BitCount = 1 +pp_data->cap[29]->BitField = 0x02 +pp_data->cap[29]->NextBytePosition = 0x0006 +pp_data->cap[29]->LinkCollection = 0x0001 +pp_data->cap[29]->LinkUsagePage = 0xFF01 +pp_data->cap[29]->LinkUsage = 0x0001 +pp_data->cap[29]->IsMultipleItemsForArray = 0 +pp_data->cap[29]->IsButtonCap = 1 +pp_data->cap[29]->IsPadding = 0 +pp_data->cap[29]->IsAbsolute = 1 +pp_data->cap[29]->IsRange = 0 +pp_data->cap[29]->IsAlias = 0 +pp_data->cap[29]->IsStringRange = 0 +pp_data->cap[29]->IsDesignatorRange = 0 +pp_data->cap[29]->Reserved1 = 0x000000 +pp_data->cap[29]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[29]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[29]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[29]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[29]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[29]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[29]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[29]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[29]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[29]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[29]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[29]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[29]->NotRange.Usage = 0x0002 +pp_data->cap[29]->NotRange.Reserved1 = 0x0002 +pp_data->cap[29]->NotRange.StringIndex = 0 +pp_data->cap[29]->NotRange.Reserved2 = 0 +pp_data->cap[29]->NotRange.DesignatorIndex = 0 +pp_data->cap[29]->NotRange.Reserved3 = 0 +pp_data->cap[29]->NotRange.DataIndex = 29 +pp_data->cap[29]->NotRange.Reserved4 = 29 +pp_data->cap[29]->Button.LogicalMin = 0 +pp_data->cap[29]->Button.LogicalMax = 0 +pp_data->cap[29]->Units = 0 +pp_data->cap[29]->UnitsExp = 0 + +pp_data->cap[30]->UsagePage = 0xFF01 +pp_data->cap[30]->ReportID = 0x01 +pp_data->cap[30]->BitPosition = 5 +pp_data->cap[30]->BitSize = 1 +pp_data->cap[30]->ReportCount = 1 +pp_data->cap[30]->BytePosition = 0x0005 +pp_data->cap[30]->BitCount = 1 +pp_data->cap[30]->BitField = 0x02 +pp_data->cap[30]->NextBytePosition = 0x0006 +pp_data->cap[30]->LinkCollection = 0x0001 +pp_data->cap[30]->LinkUsagePage = 0xFF01 +pp_data->cap[30]->LinkUsage = 0x0001 +pp_data->cap[30]->IsMultipleItemsForArray = 0 +pp_data->cap[30]->IsButtonCap = 1 +pp_data->cap[30]->IsPadding = 0 +pp_data->cap[30]->IsAbsolute = 1 +pp_data->cap[30]->IsRange = 0 +pp_data->cap[30]->IsAlias = 0 +pp_data->cap[30]->IsStringRange = 0 +pp_data->cap[30]->IsDesignatorRange = 0 +pp_data->cap[30]->Reserved1 = 0x000000 +pp_data->cap[30]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[30]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[30]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[30]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[30]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[30]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[30]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[30]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[30]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[30]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[30]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[30]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[30]->NotRange.Usage = 0x0002 +pp_data->cap[30]->NotRange.Reserved1 = 0x0002 +pp_data->cap[30]->NotRange.StringIndex = 0 +pp_data->cap[30]->NotRange.Reserved2 = 0 +pp_data->cap[30]->NotRange.DesignatorIndex = 0 +pp_data->cap[30]->NotRange.Reserved3 = 0 +pp_data->cap[30]->NotRange.DataIndex = 30 +pp_data->cap[30]->NotRange.Reserved4 = 30 +pp_data->cap[30]->Button.LogicalMin = 0 +pp_data->cap[30]->Button.LogicalMax = 0 +pp_data->cap[30]->Units = 0 +pp_data->cap[30]->UnitsExp = 0 + +pp_data->cap[31]->UsagePage = 0xFF01 +pp_data->cap[31]->ReportID = 0x01 +pp_data->cap[31]->BitPosition = 4 +pp_data->cap[31]->BitSize = 1 +pp_data->cap[31]->ReportCount = 1 +pp_data->cap[31]->BytePosition = 0x0005 +pp_data->cap[31]->BitCount = 1 +pp_data->cap[31]->BitField = 0x02 +pp_data->cap[31]->NextBytePosition = 0x0006 +pp_data->cap[31]->LinkCollection = 0x0001 +pp_data->cap[31]->LinkUsagePage = 0xFF01 +pp_data->cap[31]->LinkUsage = 0x0001 +pp_data->cap[31]->IsMultipleItemsForArray = 0 +pp_data->cap[31]->IsButtonCap = 1 +pp_data->cap[31]->IsPadding = 0 +pp_data->cap[31]->IsAbsolute = 1 +pp_data->cap[31]->IsRange = 0 +pp_data->cap[31]->IsAlias = 0 +pp_data->cap[31]->IsStringRange = 0 +pp_data->cap[31]->IsDesignatorRange = 0 +pp_data->cap[31]->Reserved1 = 0x000000 +pp_data->cap[31]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[31]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[31]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[31]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[31]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[31]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[31]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[31]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[31]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[31]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[31]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[31]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[31]->NotRange.Usage = 0x0002 +pp_data->cap[31]->NotRange.Reserved1 = 0x0002 +pp_data->cap[31]->NotRange.StringIndex = 0 +pp_data->cap[31]->NotRange.Reserved2 = 0 +pp_data->cap[31]->NotRange.DesignatorIndex = 0 +pp_data->cap[31]->NotRange.Reserved3 = 0 +pp_data->cap[31]->NotRange.DataIndex = 31 +pp_data->cap[31]->NotRange.Reserved4 = 31 +pp_data->cap[31]->Button.LogicalMin = 0 +pp_data->cap[31]->Button.LogicalMax = 0 +pp_data->cap[31]->Units = 0 +pp_data->cap[31]->UnitsExp = 0 + +pp_data->cap[32]->UsagePage = 0xFF01 +pp_data->cap[32]->ReportID = 0x01 +pp_data->cap[32]->BitPosition = 3 +pp_data->cap[32]->BitSize = 1 +pp_data->cap[32]->ReportCount = 1 +pp_data->cap[32]->BytePosition = 0x0005 +pp_data->cap[32]->BitCount = 1 +pp_data->cap[32]->BitField = 0x02 +pp_data->cap[32]->NextBytePosition = 0x0006 +pp_data->cap[32]->LinkCollection = 0x0001 +pp_data->cap[32]->LinkUsagePage = 0xFF01 +pp_data->cap[32]->LinkUsage = 0x0001 +pp_data->cap[32]->IsMultipleItemsForArray = 0 +pp_data->cap[32]->IsButtonCap = 1 +pp_data->cap[32]->IsPadding = 0 +pp_data->cap[32]->IsAbsolute = 1 +pp_data->cap[32]->IsRange = 0 +pp_data->cap[32]->IsAlias = 0 +pp_data->cap[32]->IsStringRange = 0 +pp_data->cap[32]->IsDesignatorRange = 0 +pp_data->cap[32]->Reserved1 = 0x000000 +pp_data->cap[32]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[32]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[32]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[32]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[32]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[32]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[32]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[32]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[32]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[32]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[32]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[32]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[32]->NotRange.Usage = 0x0002 +pp_data->cap[32]->NotRange.Reserved1 = 0x0002 +pp_data->cap[32]->NotRange.StringIndex = 0 +pp_data->cap[32]->NotRange.Reserved2 = 0 +pp_data->cap[32]->NotRange.DesignatorIndex = 0 +pp_data->cap[32]->NotRange.Reserved3 = 0 +pp_data->cap[32]->NotRange.DataIndex = 32 +pp_data->cap[32]->NotRange.Reserved4 = 32 +pp_data->cap[32]->Button.LogicalMin = 0 +pp_data->cap[32]->Button.LogicalMax = 0 +pp_data->cap[32]->Units = 0 +pp_data->cap[32]->UnitsExp = 0 + +pp_data->cap[33]->UsagePage = 0xFF01 +pp_data->cap[33]->ReportID = 0x01 +pp_data->cap[33]->BitPosition = 2 +pp_data->cap[33]->BitSize = 1 +pp_data->cap[33]->ReportCount = 1 +pp_data->cap[33]->BytePosition = 0x0005 +pp_data->cap[33]->BitCount = 1 +pp_data->cap[33]->BitField = 0x02 +pp_data->cap[33]->NextBytePosition = 0x0006 +pp_data->cap[33]->LinkCollection = 0x0001 +pp_data->cap[33]->LinkUsagePage = 0xFF01 +pp_data->cap[33]->LinkUsage = 0x0001 +pp_data->cap[33]->IsMultipleItemsForArray = 0 +pp_data->cap[33]->IsButtonCap = 1 +pp_data->cap[33]->IsPadding = 0 +pp_data->cap[33]->IsAbsolute = 1 +pp_data->cap[33]->IsRange = 0 +pp_data->cap[33]->IsAlias = 0 +pp_data->cap[33]->IsStringRange = 0 +pp_data->cap[33]->IsDesignatorRange = 0 +pp_data->cap[33]->Reserved1 = 0x000000 +pp_data->cap[33]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[33]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[33]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[33]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[33]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[33]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[33]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[33]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[33]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[33]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[33]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[33]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[33]->NotRange.Usage = 0x0002 +pp_data->cap[33]->NotRange.Reserved1 = 0x0002 +pp_data->cap[33]->NotRange.StringIndex = 0 +pp_data->cap[33]->NotRange.Reserved2 = 0 +pp_data->cap[33]->NotRange.DesignatorIndex = 0 +pp_data->cap[33]->NotRange.Reserved3 = 0 +pp_data->cap[33]->NotRange.DataIndex = 33 +pp_data->cap[33]->NotRange.Reserved4 = 33 +pp_data->cap[33]->Button.LogicalMin = 0 +pp_data->cap[33]->Button.LogicalMax = 0 +pp_data->cap[33]->Units = 0 +pp_data->cap[33]->UnitsExp = 0 + +pp_data->cap[34]->UsagePage = 0xFF01 +pp_data->cap[34]->ReportID = 0x01 +pp_data->cap[34]->BitPosition = 1 +pp_data->cap[34]->BitSize = 1 +pp_data->cap[34]->ReportCount = 1 +pp_data->cap[34]->BytePosition = 0x0005 +pp_data->cap[34]->BitCount = 1 +pp_data->cap[34]->BitField = 0x02 +pp_data->cap[34]->NextBytePosition = 0x0006 +pp_data->cap[34]->LinkCollection = 0x0001 +pp_data->cap[34]->LinkUsagePage = 0xFF01 +pp_data->cap[34]->LinkUsage = 0x0001 +pp_data->cap[34]->IsMultipleItemsForArray = 0 +pp_data->cap[34]->IsButtonCap = 1 +pp_data->cap[34]->IsPadding = 0 +pp_data->cap[34]->IsAbsolute = 1 +pp_data->cap[34]->IsRange = 0 +pp_data->cap[34]->IsAlias = 0 +pp_data->cap[34]->IsStringRange = 0 +pp_data->cap[34]->IsDesignatorRange = 0 +pp_data->cap[34]->Reserved1 = 0x000000 +pp_data->cap[34]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[34]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[34]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[34]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[34]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[34]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[34]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[34]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[34]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[34]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[34]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[34]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[34]->NotRange.Usage = 0x0002 +pp_data->cap[34]->NotRange.Reserved1 = 0x0002 +pp_data->cap[34]->NotRange.StringIndex = 0 +pp_data->cap[34]->NotRange.Reserved2 = 0 +pp_data->cap[34]->NotRange.DesignatorIndex = 0 +pp_data->cap[34]->NotRange.Reserved3 = 0 +pp_data->cap[34]->NotRange.DataIndex = 34 +pp_data->cap[34]->NotRange.Reserved4 = 34 +pp_data->cap[34]->Button.LogicalMin = 0 +pp_data->cap[34]->Button.LogicalMax = 0 +pp_data->cap[34]->Units = 0 +pp_data->cap[34]->UnitsExp = 0 + +pp_data->cap[35]->UsagePage = 0xFF01 +pp_data->cap[35]->ReportID = 0x01 +pp_data->cap[35]->BitPosition = 0 +pp_data->cap[35]->BitSize = 1 +pp_data->cap[35]->ReportCount = 1 +pp_data->cap[35]->BytePosition = 0x0005 +pp_data->cap[35]->BitCount = 1 +pp_data->cap[35]->BitField = 0x02 +pp_data->cap[35]->NextBytePosition = 0x0006 +pp_data->cap[35]->LinkCollection = 0x0001 +pp_data->cap[35]->LinkUsagePage = 0xFF01 +pp_data->cap[35]->LinkUsage = 0x0001 +pp_data->cap[35]->IsMultipleItemsForArray = 0 +pp_data->cap[35]->IsButtonCap = 1 +pp_data->cap[35]->IsPadding = 0 +pp_data->cap[35]->IsAbsolute = 1 +pp_data->cap[35]->IsRange = 0 +pp_data->cap[35]->IsAlias = 0 +pp_data->cap[35]->IsStringRange = 0 +pp_data->cap[35]->IsDesignatorRange = 0 +pp_data->cap[35]->Reserved1 = 0x000000 +pp_data->cap[35]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[35]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[35]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[35]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[35]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[35]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[35]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[35]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[35]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[35]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[35]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[35]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[35]->NotRange.Usage = 0x0002 +pp_data->cap[35]->NotRange.Reserved1 = 0x0002 +pp_data->cap[35]->NotRange.StringIndex = 0 +pp_data->cap[35]->NotRange.Reserved2 = 0 +pp_data->cap[35]->NotRange.DesignatorIndex = 0 +pp_data->cap[35]->NotRange.Reserved3 = 0 +pp_data->cap[35]->NotRange.DataIndex = 35 +pp_data->cap[35]->NotRange.Reserved4 = 35 +pp_data->cap[35]->Button.LogicalMin = 0 +pp_data->cap[35]->Button.LogicalMax = 0 +pp_data->cap[35]->Units = 0 +pp_data->cap[35]->UnitsExp = 0 + +pp_data->cap[36]->UsagePage = 0xFF01 +pp_data->cap[36]->ReportID = 0x01 +pp_data->cap[36]->BitPosition = 7 +pp_data->cap[36]->BitSize = 1 +pp_data->cap[36]->ReportCount = 1 +pp_data->cap[36]->BytePosition = 0x0004 +pp_data->cap[36]->BitCount = 1 +pp_data->cap[36]->BitField = 0x02 +pp_data->cap[36]->NextBytePosition = 0x0005 +pp_data->cap[36]->LinkCollection = 0x0001 +pp_data->cap[36]->LinkUsagePage = 0xFF01 +pp_data->cap[36]->LinkUsage = 0x0001 +pp_data->cap[36]->IsMultipleItemsForArray = 0 +pp_data->cap[36]->IsButtonCap = 1 +pp_data->cap[36]->IsPadding = 0 +pp_data->cap[36]->IsAbsolute = 1 +pp_data->cap[36]->IsRange = 0 +pp_data->cap[36]->IsAlias = 0 +pp_data->cap[36]->IsStringRange = 0 +pp_data->cap[36]->IsDesignatorRange = 0 +pp_data->cap[36]->Reserved1 = 0x000000 +pp_data->cap[36]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[36]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[36]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[36]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[36]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[36]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[36]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[36]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[36]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[36]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[36]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[36]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[36]->NotRange.Usage = 0x0002 +pp_data->cap[36]->NotRange.Reserved1 = 0x0002 +pp_data->cap[36]->NotRange.StringIndex = 0 +pp_data->cap[36]->NotRange.Reserved2 = 0 +pp_data->cap[36]->NotRange.DesignatorIndex = 0 +pp_data->cap[36]->NotRange.Reserved3 = 0 +pp_data->cap[36]->NotRange.DataIndex = 36 +pp_data->cap[36]->NotRange.Reserved4 = 36 +pp_data->cap[36]->Button.LogicalMin = 0 +pp_data->cap[36]->Button.LogicalMax = 0 +pp_data->cap[36]->Units = 0 +pp_data->cap[36]->UnitsExp = 0 + +pp_data->cap[37]->UsagePage = 0xFF01 +pp_data->cap[37]->ReportID = 0x01 +pp_data->cap[37]->BitPosition = 6 +pp_data->cap[37]->BitSize = 1 +pp_data->cap[37]->ReportCount = 1 +pp_data->cap[37]->BytePosition = 0x0004 +pp_data->cap[37]->BitCount = 1 +pp_data->cap[37]->BitField = 0x02 +pp_data->cap[37]->NextBytePosition = 0x0005 +pp_data->cap[37]->LinkCollection = 0x0001 +pp_data->cap[37]->LinkUsagePage = 0xFF01 +pp_data->cap[37]->LinkUsage = 0x0001 +pp_data->cap[37]->IsMultipleItemsForArray = 0 +pp_data->cap[37]->IsButtonCap = 1 +pp_data->cap[37]->IsPadding = 0 +pp_data->cap[37]->IsAbsolute = 1 +pp_data->cap[37]->IsRange = 0 +pp_data->cap[37]->IsAlias = 0 +pp_data->cap[37]->IsStringRange = 0 +pp_data->cap[37]->IsDesignatorRange = 0 +pp_data->cap[37]->Reserved1 = 0x000000 +pp_data->cap[37]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[37]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[37]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[37]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[37]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[37]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[37]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[37]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[37]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[37]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[37]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[37]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[37]->NotRange.Usage = 0x0002 +pp_data->cap[37]->NotRange.Reserved1 = 0x0002 +pp_data->cap[37]->NotRange.StringIndex = 0 +pp_data->cap[37]->NotRange.Reserved2 = 0 +pp_data->cap[37]->NotRange.DesignatorIndex = 0 +pp_data->cap[37]->NotRange.Reserved3 = 0 +pp_data->cap[37]->NotRange.DataIndex = 37 +pp_data->cap[37]->NotRange.Reserved4 = 37 +pp_data->cap[37]->Button.LogicalMin = 0 +pp_data->cap[37]->Button.LogicalMax = 0 +pp_data->cap[37]->Units = 0 +pp_data->cap[37]->UnitsExp = 0 + +pp_data->cap[38]->UsagePage = 0xFF01 +pp_data->cap[38]->ReportID = 0x01 +pp_data->cap[38]->BitPosition = 5 +pp_data->cap[38]->BitSize = 1 +pp_data->cap[38]->ReportCount = 1 +pp_data->cap[38]->BytePosition = 0x0004 +pp_data->cap[38]->BitCount = 1 +pp_data->cap[38]->BitField = 0x02 +pp_data->cap[38]->NextBytePosition = 0x0005 +pp_data->cap[38]->LinkCollection = 0x0001 +pp_data->cap[38]->LinkUsagePage = 0xFF01 +pp_data->cap[38]->LinkUsage = 0x0001 +pp_data->cap[38]->IsMultipleItemsForArray = 0 +pp_data->cap[38]->IsButtonCap = 1 +pp_data->cap[38]->IsPadding = 0 +pp_data->cap[38]->IsAbsolute = 1 +pp_data->cap[38]->IsRange = 0 +pp_data->cap[38]->IsAlias = 0 +pp_data->cap[38]->IsStringRange = 0 +pp_data->cap[38]->IsDesignatorRange = 0 +pp_data->cap[38]->Reserved1 = 0x000000 +pp_data->cap[38]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[38]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[38]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[38]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[38]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[38]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[38]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[38]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[38]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[38]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[38]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[38]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[38]->NotRange.Usage = 0x0002 +pp_data->cap[38]->NotRange.Reserved1 = 0x0002 +pp_data->cap[38]->NotRange.StringIndex = 0 +pp_data->cap[38]->NotRange.Reserved2 = 0 +pp_data->cap[38]->NotRange.DesignatorIndex = 0 +pp_data->cap[38]->NotRange.Reserved3 = 0 +pp_data->cap[38]->NotRange.DataIndex = 38 +pp_data->cap[38]->NotRange.Reserved4 = 38 +pp_data->cap[38]->Button.LogicalMin = 0 +pp_data->cap[38]->Button.LogicalMax = 0 +pp_data->cap[38]->Units = 0 +pp_data->cap[38]->UnitsExp = 0 + +pp_data->cap[39]->UsagePage = 0xFF01 +pp_data->cap[39]->ReportID = 0x01 +pp_data->cap[39]->BitPosition = 4 +pp_data->cap[39]->BitSize = 1 +pp_data->cap[39]->ReportCount = 1 +pp_data->cap[39]->BytePosition = 0x0004 +pp_data->cap[39]->BitCount = 1 +pp_data->cap[39]->BitField = 0x02 +pp_data->cap[39]->NextBytePosition = 0x0005 +pp_data->cap[39]->LinkCollection = 0x0001 +pp_data->cap[39]->LinkUsagePage = 0xFF01 +pp_data->cap[39]->LinkUsage = 0x0001 +pp_data->cap[39]->IsMultipleItemsForArray = 0 +pp_data->cap[39]->IsButtonCap = 1 +pp_data->cap[39]->IsPadding = 0 +pp_data->cap[39]->IsAbsolute = 1 +pp_data->cap[39]->IsRange = 0 +pp_data->cap[39]->IsAlias = 0 +pp_data->cap[39]->IsStringRange = 0 +pp_data->cap[39]->IsDesignatorRange = 0 +pp_data->cap[39]->Reserved1 = 0x000000 +pp_data->cap[39]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[39]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[39]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[39]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[39]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[39]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[39]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[39]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[39]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[39]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[39]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[39]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[39]->NotRange.Usage = 0x0002 +pp_data->cap[39]->NotRange.Reserved1 = 0x0002 +pp_data->cap[39]->NotRange.StringIndex = 0 +pp_data->cap[39]->NotRange.Reserved2 = 0 +pp_data->cap[39]->NotRange.DesignatorIndex = 0 +pp_data->cap[39]->NotRange.Reserved3 = 0 +pp_data->cap[39]->NotRange.DataIndex = 39 +pp_data->cap[39]->NotRange.Reserved4 = 39 +pp_data->cap[39]->Button.LogicalMin = 0 +pp_data->cap[39]->Button.LogicalMax = 0 +pp_data->cap[39]->Units = 0 +pp_data->cap[39]->UnitsExp = 0 + +pp_data->cap[40]->UsagePage = 0xFF01 +pp_data->cap[40]->ReportID = 0x01 +pp_data->cap[40]->BitPosition = 3 +pp_data->cap[40]->BitSize = 1 +pp_data->cap[40]->ReportCount = 1 +pp_data->cap[40]->BytePosition = 0x0004 +pp_data->cap[40]->BitCount = 1 +pp_data->cap[40]->BitField = 0x02 +pp_data->cap[40]->NextBytePosition = 0x0005 +pp_data->cap[40]->LinkCollection = 0x0001 +pp_data->cap[40]->LinkUsagePage = 0xFF01 +pp_data->cap[40]->LinkUsage = 0x0001 +pp_data->cap[40]->IsMultipleItemsForArray = 0 +pp_data->cap[40]->IsButtonCap = 1 +pp_data->cap[40]->IsPadding = 0 +pp_data->cap[40]->IsAbsolute = 1 +pp_data->cap[40]->IsRange = 0 +pp_data->cap[40]->IsAlias = 0 +pp_data->cap[40]->IsStringRange = 0 +pp_data->cap[40]->IsDesignatorRange = 0 +pp_data->cap[40]->Reserved1 = 0x000000 +pp_data->cap[40]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[40]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[40]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[40]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[40]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[40]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[40]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[40]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[40]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[40]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[40]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[40]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[40]->NotRange.Usage = 0x0002 +pp_data->cap[40]->NotRange.Reserved1 = 0x0002 +pp_data->cap[40]->NotRange.StringIndex = 0 +pp_data->cap[40]->NotRange.Reserved2 = 0 +pp_data->cap[40]->NotRange.DesignatorIndex = 0 +pp_data->cap[40]->NotRange.Reserved3 = 0 +pp_data->cap[40]->NotRange.DataIndex = 40 +pp_data->cap[40]->NotRange.Reserved4 = 40 +pp_data->cap[40]->Button.LogicalMin = 0 +pp_data->cap[40]->Button.LogicalMax = 0 +pp_data->cap[40]->Units = 0 +pp_data->cap[40]->UnitsExp = 0 + +pp_data->cap[41]->UsagePage = 0xFF01 +pp_data->cap[41]->ReportID = 0x01 +pp_data->cap[41]->BitPosition = 2 +pp_data->cap[41]->BitSize = 1 +pp_data->cap[41]->ReportCount = 1 +pp_data->cap[41]->BytePosition = 0x0004 +pp_data->cap[41]->BitCount = 1 +pp_data->cap[41]->BitField = 0x02 +pp_data->cap[41]->NextBytePosition = 0x0005 +pp_data->cap[41]->LinkCollection = 0x0001 +pp_data->cap[41]->LinkUsagePage = 0xFF01 +pp_data->cap[41]->LinkUsage = 0x0001 +pp_data->cap[41]->IsMultipleItemsForArray = 0 +pp_data->cap[41]->IsButtonCap = 1 +pp_data->cap[41]->IsPadding = 0 +pp_data->cap[41]->IsAbsolute = 1 +pp_data->cap[41]->IsRange = 0 +pp_data->cap[41]->IsAlias = 0 +pp_data->cap[41]->IsStringRange = 0 +pp_data->cap[41]->IsDesignatorRange = 0 +pp_data->cap[41]->Reserved1 = 0x000000 +pp_data->cap[41]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[41]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[41]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[41]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[41]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[41]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[41]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[41]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[41]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[41]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[41]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[41]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[41]->NotRange.Usage = 0x0002 +pp_data->cap[41]->NotRange.Reserved1 = 0x0002 +pp_data->cap[41]->NotRange.StringIndex = 0 +pp_data->cap[41]->NotRange.Reserved2 = 0 +pp_data->cap[41]->NotRange.DesignatorIndex = 0 +pp_data->cap[41]->NotRange.Reserved3 = 0 +pp_data->cap[41]->NotRange.DataIndex = 41 +pp_data->cap[41]->NotRange.Reserved4 = 41 +pp_data->cap[41]->Button.LogicalMin = 0 +pp_data->cap[41]->Button.LogicalMax = 0 +pp_data->cap[41]->Units = 0 +pp_data->cap[41]->UnitsExp = 0 + +pp_data->cap[42]->UsagePage = 0xFF01 +pp_data->cap[42]->ReportID = 0x01 +pp_data->cap[42]->BitPosition = 1 +pp_data->cap[42]->BitSize = 1 +pp_data->cap[42]->ReportCount = 1 +pp_data->cap[42]->BytePosition = 0x0004 +pp_data->cap[42]->BitCount = 1 +pp_data->cap[42]->BitField = 0x02 +pp_data->cap[42]->NextBytePosition = 0x0005 +pp_data->cap[42]->LinkCollection = 0x0001 +pp_data->cap[42]->LinkUsagePage = 0xFF01 +pp_data->cap[42]->LinkUsage = 0x0001 +pp_data->cap[42]->IsMultipleItemsForArray = 0 +pp_data->cap[42]->IsButtonCap = 1 +pp_data->cap[42]->IsPadding = 0 +pp_data->cap[42]->IsAbsolute = 1 +pp_data->cap[42]->IsRange = 0 +pp_data->cap[42]->IsAlias = 0 +pp_data->cap[42]->IsStringRange = 0 +pp_data->cap[42]->IsDesignatorRange = 0 +pp_data->cap[42]->Reserved1 = 0x000000 +pp_data->cap[42]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[42]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[42]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[42]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[42]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[42]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[42]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[42]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[42]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[42]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[42]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[42]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[42]->NotRange.Usage = 0x0002 +pp_data->cap[42]->NotRange.Reserved1 = 0x0002 +pp_data->cap[42]->NotRange.StringIndex = 0 +pp_data->cap[42]->NotRange.Reserved2 = 0 +pp_data->cap[42]->NotRange.DesignatorIndex = 0 +pp_data->cap[42]->NotRange.Reserved3 = 0 +pp_data->cap[42]->NotRange.DataIndex = 42 +pp_data->cap[42]->NotRange.Reserved4 = 42 +pp_data->cap[42]->Button.LogicalMin = 0 +pp_data->cap[42]->Button.LogicalMax = 0 +pp_data->cap[42]->Units = 0 +pp_data->cap[42]->UnitsExp = 0 + +pp_data->cap[43]->UsagePage = 0xFF01 +pp_data->cap[43]->ReportID = 0x01 +pp_data->cap[43]->BitPosition = 0 +pp_data->cap[43]->BitSize = 1 +pp_data->cap[43]->ReportCount = 1 +pp_data->cap[43]->BytePosition = 0x0004 +pp_data->cap[43]->BitCount = 1 +pp_data->cap[43]->BitField = 0x02 +pp_data->cap[43]->NextBytePosition = 0x0005 +pp_data->cap[43]->LinkCollection = 0x0001 +pp_data->cap[43]->LinkUsagePage = 0xFF01 +pp_data->cap[43]->LinkUsage = 0x0001 +pp_data->cap[43]->IsMultipleItemsForArray = 0 +pp_data->cap[43]->IsButtonCap = 1 +pp_data->cap[43]->IsPadding = 0 +pp_data->cap[43]->IsAbsolute = 1 +pp_data->cap[43]->IsRange = 0 +pp_data->cap[43]->IsAlias = 0 +pp_data->cap[43]->IsStringRange = 0 +pp_data->cap[43]->IsDesignatorRange = 0 +pp_data->cap[43]->Reserved1 = 0x000000 +pp_data->cap[43]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[43]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[43]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[43]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[43]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[43]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[43]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[43]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[43]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[43]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[43]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[43]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[43]->NotRange.Usage = 0x0002 +pp_data->cap[43]->NotRange.Reserved1 = 0x0002 +pp_data->cap[43]->NotRange.StringIndex = 0 +pp_data->cap[43]->NotRange.Reserved2 = 0 +pp_data->cap[43]->NotRange.DesignatorIndex = 0 +pp_data->cap[43]->NotRange.Reserved3 = 0 +pp_data->cap[43]->NotRange.DataIndex = 43 +pp_data->cap[43]->NotRange.Reserved4 = 43 +pp_data->cap[43]->Button.LogicalMin = 0 +pp_data->cap[43]->Button.LogicalMax = 0 +pp_data->cap[43]->Units = 0 +pp_data->cap[43]->UnitsExp = 0 + +pp_data->cap[44]->UsagePage = 0xFF01 +pp_data->cap[44]->ReportID = 0x01 +pp_data->cap[44]->BitPosition = 7 +pp_data->cap[44]->BitSize = 1 +pp_data->cap[44]->ReportCount = 1 +pp_data->cap[44]->BytePosition = 0x0003 +pp_data->cap[44]->BitCount = 1 +pp_data->cap[44]->BitField = 0x02 +pp_data->cap[44]->NextBytePosition = 0x0004 +pp_data->cap[44]->LinkCollection = 0x0001 +pp_data->cap[44]->LinkUsagePage = 0xFF01 +pp_data->cap[44]->LinkUsage = 0x0001 +pp_data->cap[44]->IsMultipleItemsForArray = 0 +pp_data->cap[44]->IsButtonCap = 1 +pp_data->cap[44]->IsPadding = 0 +pp_data->cap[44]->IsAbsolute = 1 +pp_data->cap[44]->IsRange = 0 +pp_data->cap[44]->IsAlias = 0 +pp_data->cap[44]->IsStringRange = 0 +pp_data->cap[44]->IsDesignatorRange = 0 +pp_data->cap[44]->Reserved1 = 0x000000 +pp_data->cap[44]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[44]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[44]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[44]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[44]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[44]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[44]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[44]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[44]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[44]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[44]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[44]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[44]->NotRange.Usage = 0x0002 +pp_data->cap[44]->NotRange.Reserved1 = 0x0002 +pp_data->cap[44]->NotRange.StringIndex = 0 +pp_data->cap[44]->NotRange.Reserved2 = 0 +pp_data->cap[44]->NotRange.DesignatorIndex = 0 +pp_data->cap[44]->NotRange.Reserved3 = 0 +pp_data->cap[44]->NotRange.DataIndex = 44 +pp_data->cap[44]->NotRange.Reserved4 = 44 +pp_data->cap[44]->Button.LogicalMin = 0 +pp_data->cap[44]->Button.LogicalMax = 0 +pp_data->cap[44]->Units = 0 +pp_data->cap[44]->UnitsExp = 0 + +pp_data->cap[45]->UsagePage = 0xFF01 +pp_data->cap[45]->ReportID = 0x01 +pp_data->cap[45]->BitPosition = 6 +pp_data->cap[45]->BitSize = 1 +pp_data->cap[45]->ReportCount = 1 +pp_data->cap[45]->BytePosition = 0x0003 +pp_data->cap[45]->BitCount = 1 +pp_data->cap[45]->BitField = 0x02 +pp_data->cap[45]->NextBytePosition = 0x0004 +pp_data->cap[45]->LinkCollection = 0x0001 +pp_data->cap[45]->LinkUsagePage = 0xFF01 +pp_data->cap[45]->LinkUsage = 0x0001 +pp_data->cap[45]->IsMultipleItemsForArray = 0 +pp_data->cap[45]->IsButtonCap = 1 +pp_data->cap[45]->IsPadding = 0 +pp_data->cap[45]->IsAbsolute = 1 +pp_data->cap[45]->IsRange = 0 +pp_data->cap[45]->IsAlias = 0 +pp_data->cap[45]->IsStringRange = 0 +pp_data->cap[45]->IsDesignatorRange = 0 +pp_data->cap[45]->Reserved1 = 0x000000 +pp_data->cap[45]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[45]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[45]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[45]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[45]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[45]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[45]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[45]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[45]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[45]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[45]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[45]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[45]->NotRange.Usage = 0x0002 +pp_data->cap[45]->NotRange.Reserved1 = 0x0002 +pp_data->cap[45]->NotRange.StringIndex = 0 +pp_data->cap[45]->NotRange.Reserved2 = 0 +pp_data->cap[45]->NotRange.DesignatorIndex = 0 +pp_data->cap[45]->NotRange.Reserved3 = 0 +pp_data->cap[45]->NotRange.DataIndex = 45 +pp_data->cap[45]->NotRange.Reserved4 = 45 +pp_data->cap[45]->Button.LogicalMin = 0 +pp_data->cap[45]->Button.LogicalMax = 0 +pp_data->cap[45]->Units = 0 +pp_data->cap[45]->UnitsExp = 0 + +pp_data->cap[46]->UsagePage = 0xFF01 +pp_data->cap[46]->ReportID = 0x01 +pp_data->cap[46]->BitPosition = 5 +pp_data->cap[46]->BitSize = 1 +pp_data->cap[46]->ReportCount = 1 +pp_data->cap[46]->BytePosition = 0x0003 +pp_data->cap[46]->BitCount = 1 +pp_data->cap[46]->BitField = 0x02 +pp_data->cap[46]->NextBytePosition = 0x0004 +pp_data->cap[46]->LinkCollection = 0x0001 +pp_data->cap[46]->LinkUsagePage = 0xFF01 +pp_data->cap[46]->LinkUsage = 0x0001 +pp_data->cap[46]->IsMultipleItemsForArray = 0 +pp_data->cap[46]->IsButtonCap = 1 +pp_data->cap[46]->IsPadding = 0 +pp_data->cap[46]->IsAbsolute = 1 +pp_data->cap[46]->IsRange = 0 +pp_data->cap[46]->IsAlias = 0 +pp_data->cap[46]->IsStringRange = 0 +pp_data->cap[46]->IsDesignatorRange = 0 +pp_data->cap[46]->Reserved1 = 0x000000 +pp_data->cap[46]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[46]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[46]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[46]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[46]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[46]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[46]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[46]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[46]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[46]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[46]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[46]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[46]->NotRange.Usage = 0x0002 +pp_data->cap[46]->NotRange.Reserved1 = 0x0002 +pp_data->cap[46]->NotRange.StringIndex = 0 +pp_data->cap[46]->NotRange.Reserved2 = 0 +pp_data->cap[46]->NotRange.DesignatorIndex = 0 +pp_data->cap[46]->NotRange.Reserved3 = 0 +pp_data->cap[46]->NotRange.DataIndex = 46 +pp_data->cap[46]->NotRange.Reserved4 = 46 +pp_data->cap[46]->Button.LogicalMin = 0 +pp_data->cap[46]->Button.LogicalMax = 0 +pp_data->cap[46]->Units = 0 +pp_data->cap[46]->UnitsExp = 0 + +pp_data->cap[47]->UsagePage = 0xFF01 +pp_data->cap[47]->ReportID = 0x01 +pp_data->cap[47]->BitPosition = 4 +pp_data->cap[47]->BitSize = 1 +pp_data->cap[47]->ReportCount = 1 +pp_data->cap[47]->BytePosition = 0x0003 +pp_data->cap[47]->BitCount = 1 +pp_data->cap[47]->BitField = 0x02 +pp_data->cap[47]->NextBytePosition = 0x0004 +pp_data->cap[47]->LinkCollection = 0x0001 +pp_data->cap[47]->LinkUsagePage = 0xFF01 +pp_data->cap[47]->LinkUsage = 0x0001 +pp_data->cap[47]->IsMultipleItemsForArray = 0 +pp_data->cap[47]->IsButtonCap = 1 +pp_data->cap[47]->IsPadding = 0 +pp_data->cap[47]->IsAbsolute = 1 +pp_data->cap[47]->IsRange = 0 +pp_data->cap[47]->IsAlias = 0 +pp_data->cap[47]->IsStringRange = 0 +pp_data->cap[47]->IsDesignatorRange = 0 +pp_data->cap[47]->Reserved1 = 0x000000 +pp_data->cap[47]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[47]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[47]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[47]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[47]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[47]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[47]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[47]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[47]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[47]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[47]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[47]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[47]->NotRange.Usage = 0x0002 +pp_data->cap[47]->NotRange.Reserved1 = 0x0002 +pp_data->cap[47]->NotRange.StringIndex = 0 +pp_data->cap[47]->NotRange.Reserved2 = 0 +pp_data->cap[47]->NotRange.DesignatorIndex = 0 +pp_data->cap[47]->NotRange.Reserved3 = 0 +pp_data->cap[47]->NotRange.DataIndex = 47 +pp_data->cap[47]->NotRange.Reserved4 = 47 +pp_data->cap[47]->Button.LogicalMin = 0 +pp_data->cap[47]->Button.LogicalMax = 0 +pp_data->cap[47]->Units = 0 +pp_data->cap[47]->UnitsExp = 0 + +pp_data->cap[48]->UsagePage = 0xFF01 +pp_data->cap[48]->ReportID = 0x01 +pp_data->cap[48]->BitPosition = 3 +pp_data->cap[48]->BitSize = 1 +pp_data->cap[48]->ReportCount = 1 +pp_data->cap[48]->BytePosition = 0x0003 +pp_data->cap[48]->BitCount = 1 +pp_data->cap[48]->BitField = 0x02 +pp_data->cap[48]->NextBytePosition = 0x0004 +pp_data->cap[48]->LinkCollection = 0x0001 +pp_data->cap[48]->LinkUsagePage = 0xFF01 +pp_data->cap[48]->LinkUsage = 0x0001 +pp_data->cap[48]->IsMultipleItemsForArray = 0 +pp_data->cap[48]->IsButtonCap = 1 +pp_data->cap[48]->IsPadding = 0 +pp_data->cap[48]->IsAbsolute = 1 +pp_data->cap[48]->IsRange = 0 +pp_data->cap[48]->IsAlias = 0 +pp_data->cap[48]->IsStringRange = 0 +pp_data->cap[48]->IsDesignatorRange = 0 +pp_data->cap[48]->Reserved1 = 0x000000 +pp_data->cap[48]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[48]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[48]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[48]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[48]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[48]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[48]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[48]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[48]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[48]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[48]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[48]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[48]->NotRange.Usage = 0x0002 +pp_data->cap[48]->NotRange.Reserved1 = 0x0002 +pp_data->cap[48]->NotRange.StringIndex = 0 +pp_data->cap[48]->NotRange.Reserved2 = 0 +pp_data->cap[48]->NotRange.DesignatorIndex = 0 +pp_data->cap[48]->NotRange.Reserved3 = 0 +pp_data->cap[48]->NotRange.DataIndex = 48 +pp_data->cap[48]->NotRange.Reserved4 = 48 +pp_data->cap[48]->Button.LogicalMin = 0 +pp_data->cap[48]->Button.LogicalMax = 0 +pp_data->cap[48]->Units = 0 +pp_data->cap[48]->UnitsExp = 0 + +pp_data->cap[49]->UsagePage = 0xFF01 +pp_data->cap[49]->ReportID = 0x01 +pp_data->cap[49]->BitPosition = 2 +pp_data->cap[49]->BitSize = 1 +pp_data->cap[49]->ReportCount = 1 +pp_data->cap[49]->BytePosition = 0x0003 +pp_data->cap[49]->BitCount = 1 +pp_data->cap[49]->BitField = 0x02 +pp_data->cap[49]->NextBytePosition = 0x0004 +pp_data->cap[49]->LinkCollection = 0x0001 +pp_data->cap[49]->LinkUsagePage = 0xFF01 +pp_data->cap[49]->LinkUsage = 0x0001 +pp_data->cap[49]->IsMultipleItemsForArray = 0 +pp_data->cap[49]->IsButtonCap = 1 +pp_data->cap[49]->IsPadding = 0 +pp_data->cap[49]->IsAbsolute = 1 +pp_data->cap[49]->IsRange = 0 +pp_data->cap[49]->IsAlias = 0 +pp_data->cap[49]->IsStringRange = 0 +pp_data->cap[49]->IsDesignatorRange = 0 +pp_data->cap[49]->Reserved1 = 0x000000 +pp_data->cap[49]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[49]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[49]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[49]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[49]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[49]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[49]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[49]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[49]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[49]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[49]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[49]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[49]->NotRange.Usage = 0x0002 +pp_data->cap[49]->NotRange.Reserved1 = 0x0002 +pp_data->cap[49]->NotRange.StringIndex = 0 +pp_data->cap[49]->NotRange.Reserved2 = 0 +pp_data->cap[49]->NotRange.DesignatorIndex = 0 +pp_data->cap[49]->NotRange.Reserved3 = 0 +pp_data->cap[49]->NotRange.DataIndex = 49 +pp_data->cap[49]->NotRange.Reserved4 = 49 +pp_data->cap[49]->Button.LogicalMin = 0 +pp_data->cap[49]->Button.LogicalMax = 0 +pp_data->cap[49]->Units = 0 +pp_data->cap[49]->UnitsExp = 0 + +pp_data->cap[50]->UsagePage = 0xFF01 +pp_data->cap[50]->ReportID = 0x01 +pp_data->cap[50]->BitPosition = 1 +pp_data->cap[50]->BitSize = 1 +pp_data->cap[50]->ReportCount = 1 +pp_data->cap[50]->BytePosition = 0x0003 +pp_data->cap[50]->BitCount = 1 +pp_data->cap[50]->BitField = 0x02 +pp_data->cap[50]->NextBytePosition = 0x0004 +pp_data->cap[50]->LinkCollection = 0x0001 +pp_data->cap[50]->LinkUsagePage = 0xFF01 +pp_data->cap[50]->LinkUsage = 0x0001 +pp_data->cap[50]->IsMultipleItemsForArray = 0 +pp_data->cap[50]->IsButtonCap = 1 +pp_data->cap[50]->IsPadding = 0 +pp_data->cap[50]->IsAbsolute = 1 +pp_data->cap[50]->IsRange = 0 +pp_data->cap[50]->IsAlias = 0 +pp_data->cap[50]->IsStringRange = 0 +pp_data->cap[50]->IsDesignatorRange = 0 +pp_data->cap[50]->Reserved1 = 0x000000 +pp_data->cap[50]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[50]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[50]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[50]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[50]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[50]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[50]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[50]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[50]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[50]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[50]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[50]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[50]->NotRange.Usage = 0x0002 +pp_data->cap[50]->NotRange.Reserved1 = 0x0002 +pp_data->cap[50]->NotRange.StringIndex = 0 +pp_data->cap[50]->NotRange.Reserved2 = 0 +pp_data->cap[50]->NotRange.DesignatorIndex = 0 +pp_data->cap[50]->NotRange.Reserved3 = 0 +pp_data->cap[50]->NotRange.DataIndex = 50 +pp_data->cap[50]->NotRange.Reserved4 = 50 +pp_data->cap[50]->Button.LogicalMin = 0 +pp_data->cap[50]->Button.LogicalMax = 0 +pp_data->cap[50]->Units = 0 +pp_data->cap[50]->UnitsExp = 0 + +pp_data->cap[51]->UsagePage = 0xFF01 +pp_data->cap[51]->ReportID = 0x01 +pp_data->cap[51]->BitPosition = 0 +pp_data->cap[51]->BitSize = 1 +pp_data->cap[51]->ReportCount = 1 +pp_data->cap[51]->BytePosition = 0x0003 +pp_data->cap[51]->BitCount = 1 +pp_data->cap[51]->BitField = 0x02 +pp_data->cap[51]->NextBytePosition = 0x0004 +pp_data->cap[51]->LinkCollection = 0x0001 +pp_data->cap[51]->LinkUsagePage = 0xFF01 +pp_data->cap[51]->LinkUsage = 0x0001 +pp_data->cap[51]->IsMultipleItemsForArray = 0 +pp_data->cap[51]->IsButtonCap = 1 +pp_data->cap[51]->IsPadding = 0 +pp_data->cap[51]->IsAbsolute = 1 +pp_data->cap[51]->IsRange = 0 +pp_data->cap[51]->IsAlias = 0 +pp_data->cap[51]->IsStringRange = 0 +pp_data->cap[51]->IsDesignatorRange = 0 +pp_data->cap[51]->Reserved1 = 0x000000 +pp_data->cap[51]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[51]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[51]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[51]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[51]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[51]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[51]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[51]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[51]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[51]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[51]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[51]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[51]->NotRange.Usage = 0x0002 +pp_data->cap[51]->NotRange.Reserved1 = 0x0002 +pp_data->cap[51]->NotRange.StringIndex = 0 +pp_data->cap[51]->NotRange.Reserved2 = 0 +pp_data->cap[51]->NotRange.DesignatorIndex = 0 +pp_data->cap[51]->NotRange.Reserved3 = 0 +pp_data->cap[51]->NotRange.DataIndex = 51 +pp_data->cap[51]->NotRange.Reserved4 = 51 +pp_data->cap[51]->Button.LogicalMin = 0 +pp_data->cap[51]->Button.LogicalMax = 0 +pp_data->cap[51]->Units = 0 +pp_data->cap[51]->UnitsExp = 0 + +pp_data->cap[52]->UsagePage = 0xFF01 +pp_data->cap[52]->ReportID = 0x01 +pp_data->cap[52]->BitPosition = 7 +pp_data->cap[52]->BitSize = 1 +pp_data->cap[52]->ReportCount = 1 +pp_data->cap[52]->BytePosition = 0x0009 +pp_data->cap[52]->BitCount = 1 +pp_data->cap[52]->BitField = 0x02 +pp_data->cap[52]->NextBytePosition = 0x000A +pp_data->cap[52]->LinkCollection = 0x0001 +pp_data->cap[52]->LinkUsagePage = 0xFF01 +pp_data->cap[52]->LinkUsage = 0x0001 +pp_data->cap[52]->IsMultipleItemsForArray = 0 +pp_data->cap[52]->IsButtonCap = 1 +pp_data->cap[52]->IsPadding = 0 +pp_data->cap[52]->IsAbsolute = 1 +pp_data->cap[52]->IsRange = 0 +pp_data->cap[52]->IsAlias = 0 +pp_data->cap[52]->IsStringRange = 0 +pp_data->cap[52]->IsDesignatorRange = 0 +pp_data->cap[52]->Reserved1 = 0x000000 +pp_data->cap[52]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[52]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[52]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[52]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[52]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[52]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[52]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[52]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[52]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[52]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[52]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[52]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[52]->NotRange.Usage = 0x000B +pp_data->cap[52]->NotRange.Reserved1 = 0x000B +pp_data->cap[52]->NotRange.StringIndex = 0 +pp_data->cap[52]->NotRange.Reserved2 = 0 +pp_data->cap[52]->NotRange.DesignatorIndex = 0 +pp_data->cap[52]->NotRange.Reserved3 = 0 +pp_data->cap[52]->NotRange.DataIndex = 52 +pp_data->cap[52]->NotRange.Reserved4 = 52 +pp_data->cap[52]->Button.LogicalMin = 0 +pp_data->cap[52]->Button.LogicalMax = 0 +pp_data->cap[52]->Units = 0 +pp_data->cap[52]->UnitsExp = 0 + +pp_data->cap[53]->UsagePage = 0xFF01 +pp_data->cap[53]->ReportID = 0x01 +pp_data->cap[53]->BitPosition = 6 +pp_data->cap[53]->BitSize = 1 +pp_data->cap[53]->ReportCount = 1 +pp_data->cap[53]->BytePosition = 0x0009 +pp_data->cap[53]->BitCount = 1 +pp_data->cap[53]->BitField = 0x02 +pp_data->cap[53]->NextBytePosition = 0x000A +pp_data->cap[53]->LinkCollection = 0x0001 +pp_data->cap[53]->LinkUsagePage = 0xFF01 +pp_data->cap[53]->LinkUsage = 0x0001 +pp_data->cap[53]->IsMultipleItemsForArray = 0 +pp_data->cap[53]->IsButtonCap = 1 +pp_data->cap[53]->IsPadding = 0 +pp_data->cap[53]->IsAbsolute = 1 +pp_data->cap[53]->IsRange = 0 +pp_data->cap[53]->IsAlias = 0 +pp_data->cap[53]->IsStringRange = 0 +pp_data->cap[53]->IsDesignatorRange = 0 +pp_data->cap[53]->Reserved1 = 0x000000 +pp_data->cap[53]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[53]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[53]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[53]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[53]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[53]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[53]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[53]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[53]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[53]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[53]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[53]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[53]->NotRange.Usage = 0x000B +pp_data->cap[53]->NotRange.Reserved1 = 0x000B +pp_data->cap[53]->NotRange.StringIndex = 0 +pp_data->cap[53]->NotRange.Reserved2 = 0 +pp_data->cap[53]->NotRange.DesignatorIndex = 0 +pp_data->cap[53]->NotRange.Reserved3 = 0 +pp_data->cap[53]->NotRange.DataIndex = 53 +pp_data->cap[53]->NotRange.Reserved4 = 53 +pp_data->cap[53]->Button.LogicalMin = 0 +pp_data->cap[53]->Button.LogicalMax = 0 +pp_data->cap[53]->Units = 0 +pp_data->cap[53]->UnitsExp = 0 + +pp_data->cap[54]->UsagePage = 0xFF01 +pp_data->cap[54]->ReportID = 0x01 +pp_data->cap[54]->BitPosition = 5 +pp_data->cap[54]->BitSize = 1 +pp_data->cap[54]->ReportCount = 1 +pp_data->cap[54]->BytePosition = 0x0009 +pp_data->cap[54]->BitCount = 1 +pp_data->cap[54]->BitField = 0x02 +pp_data->cap[54]->NextBytePosition = 0x000A +pp_data->cap[54]->LinkCollection = 0x0001 +pp_data->cap[54]->LinkUsagePage = 0xFF01 +pp_data->cap[54]->LinkUsage = 0x0001 +pp_data->cap[54]->IsMultipleItemsForArray = 0 +pp_data->cap[54]->IsButtonCap = 1 +pp_data->cap[54]->IsPadding = 0 +pp_data->cap[54]->IsAbsolute = 1 +pp_data->cap[54]->IsRange = 0 +pp_data->cap[54]->IsAlias = 0 +pp_data->cap[54]->IsStringRange = 0 +pp_data->cap[54]->IsDesignatorRange = 0 +pp_data->cap[54]->Reserved1 = 0x000000 +pp_data->cap[54]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[54]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[54]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[54]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[54]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[54]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[54]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[54]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[54]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[54]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[54]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[54]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[54]->NotRange.Usage = 0x000B +pp_data->cap[54]->NotRange.Reserved1 = 0x000B +pp_data->cap[54]->NotRange.StringIndex = 0 +pp_data->cap[54]->NotRange.Reserved2 = 0 +pp_data->cap[54]->NotRange.DesignatorIndex = 0 +pp_data->cap[54]->NotRange.Reserved3 = 0 +pp_data->cap[54]->NotRange.DataIndex = 54 +pp_data->cap[54]->NotRange.Reserved4 = 54 +pp_data->cap[54]->Button.LogicalMin = 0 +pp_data->cap[54]->Button.LogicalMax = 0 +pp_data->cap[54]->Units = 0 +pp_data->cap[54]->UnitsExp = 0 + +pp_data->cap[55]->UsagePage = 0xFF01 +pp_data->cap[55]->ReportID = 0x01 +pp_data->cap[55]->BitPosition = 4 +pp_data->cap[55]->BitSize = 1 +pp_data->cap[55]->ReportCount = 1 +pp_data->cap[55]->BytePosition = 0x0009 +pp_data->cap[55]->BitCount = 1 +pp_data->cap[55]->BitField = 0x02 +pp_data->cap[55]->NextBytePosition = 0x000A +pp_data->cap[55]->LinkCollection = 0x0001 +pp_data->cap[55]->LinkUsagePage = 0xFF01 +pp_data->cap[55]->LinkUsage = 0x0001 +pp_data->cap[55]->IsMultipleItemsForArray = 0 +pp_data->cap[55]->IsButtonCap = 1 +pp_data->cap[55]->IsPadding = 0 +pp_data->cap[55]->IsAbsolute = 1 +pp_data->cap[55]->IsRange = 0 +pp_data->cap[55]->IsAlias = 0 +pp_data->cap[55]->IsStringRange = 0 +pp_data->cap[55]->IsDesignatorRange = 0 +pp_data->cap[55]->Reserved1 = 0x000000 +pp_data->cap[55]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[55]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[55]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[55]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[55]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[55]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[55]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[55]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[55]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[55]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[55]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[55]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[55]->NotRange.Usage = 0x000B +pp_data->cap[55]->NotRange.Reserved1 = 0x000B +pp_data->cap[55]->NotRange.StringIndex = 0 +pp_data->cap[55]->NotRange.Reserved2 = 0 +pp_data->cap[55]->NotRange.DesignatorIndex = 0 +pp_data->cap[55]->NotRange.Reserved3 = 0 +pp_data->cap[55]->NotRange.DataIndex = 55 +pp_data->cap[55]->NotRange.Reserved4 = 55 +pp_data->cap[55]->Button.LogicalMin = 0 +pp_data->cap[55]->Button.LogicalMax = 0 +pp_data->cap[55]->Units = 0 +pp_data->cap[55]->UnitsExp = 0 + +pp_data->cap[56]->UsagePage = 0xFF01 +pp_data->cap[56]->ReportID = 0x01 +pp_data->cap[56]->BitPosition = 3 +pp_data->cap[56]->BitSize = 1 +pp_data->cap[56]->ReportCount = 1 +pp_data->cap[56]->BytePosition = 0x0009 +pp_data->cap[56]->BitCount = 1 +pp_data->cap[56]->BitField = 0x02 +pp_data->cap[56]->NextBytePosition = 0x000A +pp_data->cap[56]->LinkCollection = 0x0001 +pp_data->cap[56]->LinkUsagePage = 0xFF01 +pp_data->cap[56]->LinkUsage = 0x0001 +pp_data->cap[56]->IsMultipleItemsForArray = 0 +pp_data->cap[56]->IsButtonCap = 1 +pp_data->cap[56]->IsPadding = 0 +pp_data->cap[56]->IsAbsolute = 1 +pp_data->cap[56]->IsRange = 0 +pp_data->cap[56]->IsAlias = 0 +pp_data->cap[56]->IsStringRange = 0 +pp_data->cap[56]->IsDesignatorRange = 0 +pp_data->cap[56]->Reserved1 = 0x000000 +pp_data->cap[56]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[56]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[56]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[56]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[56]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[56]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[56]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[56]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[56]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[56]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[56]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[56]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[56]->NotRange.Usage = 0x000B +pp_data->cap[56]->NotRange.Reserved1 = 0x000B +pp_data->cap[56]->NotRange.StringIndex = 0 +pp_data->cap[56]->NotRange.Reserved2 = 0 +pp_data->cap[56]->NotRange.DesignatorIndex = 0 +pp_data->cap[56]->NotRange.Reserved3 = 0 +pp_data->cap[56]->NotRange.DataIndex = 56 +pp_data->cap[56]->NotRange.Reserved4 = 56 +pp_data->cap[56]->Button.LogicalMin = 0 +pp_data->cap[56]->Button.LogicalMax = 0 +pp_data->cap[56]->Units = 0 +pp_data->cap[56]->UnitsExp = 0 + +pp_data->cap[57]->UsagePage = 0xFF01 +pp_data->cap[57]->ReportID = 0x01 +pp_data->cap[57]->BitPosition = 2 +pp_data->cap[57]->BitSize = 1 +pp_data->cap[57]->ReportCount = 1 +pp_data->cap[57]->BytePosition = 0x0009 +pp_data->cap[57]->BitCount = 1 +pp_data->cap[57]->BitField = 0x02 +pp_data->cap[57]->NextBytePosition = 0x000A +pp_data->cap[57]->LinkCollection = 0x0001 +pp_data->cap[57]->LinkUsagePage = 0xFF01 +pp_data->cap[57]->LinkUsage = 0x0001 +pp_data->cap[57]->IsMultipleItemsForArray = 0 +pp_data->cap[57]->IsButtonCap = 1 +pp_data->cap[57]->IsPadding = 0 +pp_data->cap[57]->IsAbsolute = 1 +pp_data->cap[57]->IsRange = 0 +pp_data->cap[57]->IsAlias = 0 +pp_data->cap[57]->IsStringRange = 0 +pp_data->cap[57]->IsDesignatorRange = 0 +pp_data->cap[57]->Reserved1 = 0x000000 +pp_data->cap[57]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[57]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[57]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[57]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[57]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[57]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[57]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[57]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[57]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[57]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[57]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[57]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[57]->NotRange.Usage = 0x000B +pp_data->cap[57]->NotRange.Reserved1 = 0x000B +pp_data->cap[57]->NotRange.StringIndex = 0 +pp_data->cap[57]->NotRange.Reserved2 = 0 +pp_data->cap[57]->NotRange.DesignatorIndex = 0 +pp_data->cap[57]->NotRange.Reserved3 = 0 +pp_data->cap[57]->NotRange.DataIndex = 57 +pp_data->cap[57]->NotRange.Reserved4 = 57 +pp_data->cap[57]->Button.LogicalMin = 0 +pp_data->cap[57]->Button.LogicalMax = 0 +pp_data->cap[57]->Units = 0 +pp_data->cap[57]->UnitsExp = 0 + +pp_data->cap[58]->UsagePage = 0xFF01 +pp_data->cap[58]->ReportID = 0x01 +pp_data->cap[58]->BitPosition = 1 +pp_data->cap[58]->BitSize = 1 +pp_data->cap[58]->ReportCount = 1 +pp_data->cap[58]->BytePosition = 0x0009 +pp_data->cap[58]->BitCount = 1 +pp_data->cap[58]->BitField = 0x02 +pp_data->cap[58]->NextBytePosition = 0x000A +pp_data->cap[58]->LinkCollection = 0x0001 +pp_data->cap[58]->LinkUsagePage = 0xFF01 +pp_data->cap[58]->LinkUsage = 0x0001 +pp_data->cap[58]->IsMultipleItemsForArray = 0 +pp_data->cap[58]->IsButtonCap = 1 +pp_data->cap[58]->IsPadding = 0 +pp_data->cap[58]->IsAbsolute = 1 +pp_data->cap[58]->IsRange = 0 +pp_data->cap[58]->IsAlias = 0 +pp_data->cap[58]->IsStringRange = 0 +pp_data->cap[58]->IsDesignatorRange = 0 +pp_data->cap[58]->Reserved1 = 0x000000 +pp_data->cap[58]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[58]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[58]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[58]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[58]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[58]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[58]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[58]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[58]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[58]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[58]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[58]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[58]->NotRange.Usage = 0x000B +pp_data->cap[58]->NotRange.Reserved1 = 0x000B +pp_data->cap[58]->NotRange.StringIndex = 0 +pp_data->cap[58]->NotRange.Reserved2 = 0 +pp_data->cap[58]->NotRange.DesignatorIndex = 0 +pp_data->cap[58]->NotRange.Reserved3 = 0 +pp_data->cap[58]->NotRange.DataIndex = 58 +pp_data->cap[58]->NotRange.Reserved4 = 58 +pp_data->cap[58]->Button.LogicalMin = 0 +pp_data->cap[58]->Button.LogicalMax = 0 +pp_data->cap[58]->Units = 0 +pp_data->cap[58]->UnitsExp = 0 + +pp_data->cap[59]->UsagePage = 0xFF01 +pp_data->cap[59]->ReportID = 0x01 +pp_data->cap[59]->BitPosition = 0 +pp_data->cap[59]->BitSize = 1 +pp_data->cap[59]->ReportCount = 1 +pp_data->cap[59]->BytePosition = 0x0009 +pp_data->cap[59]->BitCount = 1 +pp_data->cap[59]->BitField = 0x02 +pp_data->cap[59]->NextBytePosition = 0x000A +pp_data->cap[59]->LinkCollection = 0x0001 +pp_data->cap[59]->LinkUsagePage = 0xFF01 +pp_data->cap[59]->LinkUsage = 0x0001 +pp_data->cap[59]->IsMultipleItemsForArray = 0 +pp_data->cap[59]->IsButtonCap = 1 +pp_data->cap[59]->IsPadding = 0 +pp_data->cap[59]->IsAbsolute = 1 +pp_data->cap[59]->IsRange = 0 +pp_data->cap[59]->IsAlias = 0 +pp_data->cap[59]->IsStringRange = 0 +pp_data->cap[59]->IsDesignatorRange = 0 +pp_data->cap[59]->Reserved1 = 0x000000 +pp_data->cap[59]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[59]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[59]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[59]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[59]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[59]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[59]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[59]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[59]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[59]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[59]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[59]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[59]->NotRange.Usage = 0x000B +pp_data->cap[59]->NotRange.Reserved1 = 0x000B +pp_data->cap[59]->NotRange.StringIndex = 0 +pp_data->cap[59]->NotRange.Reserved2 = 0 +pp_data->cap[59]->NotRange.DesignatorIndex = 0 +pp_data->cap[59]->NotRange.Reserved3 = 0 +pp_data->cap[59]->NotRange.DataIndex = 59 +pp_data->cap[59]->NotRange.Reserved4 = 59 +pp_data->cap[59]->Button.LogicalMin = 0 +pp_data->cap[59]->Button.LogicalMax = 0 +pp_data->cap[59]->Units = 0 +pp_data->cap[59]->UnitsExp = 0 + +pp_data->cap[60]->UsagePage = 0xFF01 +pp_data->cap[60]->ReportID = 0x02 +pp_data->cap[60]->BitPosition = 0 +pp_data->cap[60]->BitSize = 16 +pp_data->cap[60]->ReportCount = 1 +pp_data->cap[60]->BytePosition = 0x0033 +pp_data->cap[60]->BitCount = 16 +pp_data->cap[60]->BitField = 0x02 +pp_data->cap[60]->NextBytePosition = 0x0035 +pp_data->cap[60]->LinkCollection = 0x0002 +pp_data->cap[60]->LinkUsagePage = 0xFF01 +pp_data->cap[60]->LinkUsage = 0x0002 +pp_data->cap[60]->IsMultipleItemsForArray = 0 +pp_data->cap[60]->IsButtonCap = 0 +pp_data->cap[60]->IsPadding = 0 +pp_data->cap[60]->IsAbsolute = 1 +pp_data->cap[60]->IsRange = 0 +pp_data->cap[60]->IsAlias = 0 +pp_data->cap[60]->IsStringRange = 0 +pp_data->cap[60]->IsDesignatorRange = 0 +pp_data->cap[60]->Reserved1 = 0x000000 +pp_data->cap[60]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[60]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[60]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[60]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[60]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[60]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[60]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[60]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[60]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[60]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[60]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[60]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[60]->NotRange.Usage = 0x0004 +pp_data->cap[60]->NotRange.Reserved1 = 0x0004 +pp_data->cap[60]->NotRange.StringIndex = 0 +pp_data->cap[60]->NotRange.Reserved2 = 0 +pp_data->cap[60]->NotRange.DesignatorIndex = 0 +pp_data->cap[60]->NotRange.Reserved3 = 0 +pp_data->cap[60]->NotRange.DataIndex = 60 +pp_data->cap[60]->NotRange.Reserved4 = 60 +pp_data->cap[60]->NotButton.HasNull = 0 +pp_data->cap[60]->NotButton.Reserved4 = 0x000000 +pp_data->cap[60]->NotButton.LogicalMin = 0 +pp_data->cap[60]->NotButton.LogicalMax = 4095 +pp_data->cap[60]->NotButton.PhysicalMin = 0 +pp_data->cap[60]->NotButton.PhysicalMax = 0 +pp_data->cap[60]->Units = 0 +pp_data->cap[60]->UnitsExp = 0 + +pp_data->cap[61]->UsagePage = 0xFF01 +pp_data->cap[61]->ReportID = 0x02 +pp_data->cap[61]->BitPosition = 0 +pp_data->cap[61]->BitSize = 16 +pp_data->cap[61]->ReportCount = 1 +pp_data->cap[61]->BytePosition = 0x0031 +pp_data->cap[61]->BitCount = 16 +pp_data->cap[61]->BitField = 0x02 +pp_data->cap[61]->NextBytePosition = 0x0033 +pp_data->cap[61]->LinkCollection = 0x0002 +pp_data->cap[61]->LinkUsagePage = 0xFF01 +pp_data->cap[61]->LinkUsage = 0x0002 +pp_data->cap[61]->IsMultipleItemsForArray = 0 +pp_data->cap[61]->IsButtonCap = 0 +pp_data->cap[61]->IsPadding = 0 +pp_data->cap[61]->IsAbsolute = 1 +pp_data->cap[61]->IsRange = 0 +pp_data->cap[61]->IsAlias = 0 +pp_data->cap[61]->IsStringRange = 0 +pp_data->cap[61]->IsDesignatorRange = 0 +pp_data->cap[61]->Reserved1 = 0x000000 +pp_data->cap[61]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[61]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[61]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[61]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[61]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[61]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[61]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[61]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[61]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[61]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[61]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[61]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[61]->NotRange.Usage = 0x0004 +pp_data->cap[61]->NotRange.Reserved1 = 0x0004 +pp_data->cap[61]->NotRange.StringIndex = 0 +pp_data->cap[61]->NotRange.Reserved2 = 0 +pp_data->cap[61]->NotRange.DesignatorIndex = 0 +pp_data->cap[61]->NotRange.Reserved3 = 0 +pp_data->cap[61]->NotRange.DataIndex = 61 +pp_data->cap[61]->NotRange.Reserved4 = 61 +pp_data->cap[61]->NotButton.HasNull = 0 +pp_data->cap[61]->NotButton.Reserved4 = 0x000000 +pp_data->cap[61]->NotButton.LogicalMin = 0 +pp_data->cap[61]->NotButton.LogicalMax = 4095 +pp_data->cap[61]->NotButton.PhysicalMin = 0 +pp_data->cap[61]->NotButton.PhysicalMax = 0 +pp_data->cap[61]->Units = 0 +pp_data->cap[61]->UnitsExp = 0 + +pp_data->cap[62]->UsagePage = 0xFF01 +pp_data->cap[62]->ReportID = 0x02 +pp_data->cap[62]->BitPosition = 0 +pp_data->cap[62]->BitSize = 16 +pp_data->cap[62]->ReportCount = 1 +pp_data->cap[62]->BytePosition = 0x002F +pp_data->cap[62]->BitCount = 16 +pp_data->cap[62]->BitField = 0x02 +pp_data->cap[62]->NextBytePosition = 0x0031 +pp_data->cap[62]->LinkCollection = 0x0002 +pp_data->cap[62]->LinkUsagePage = 0xFF01 +pp_data->cap[62]->LinkUsage = 0x0002 +pp_data->cap[62]->IsMultipleItemsForArray = 0 +pp_data->cap[62]->IsButtonCap = 0 +pp_data->cap[62]->IsPadding = 0 +pp_data->cap[62]->IsAbsolute = 1 +pp_data->cap[62]->IsRange = 0 +pp_data->cap[62]->IsAlias = 0 +pp_data->cap[62]->IsStringRange = 0 +pp_data->cap[62]->IsDesignatorRange = 0 +pp_data->cap[62]->Reserved1 = 0x000000 +pp_data->cap[62]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[62]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[62]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[62]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[62]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[62]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[62]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[62]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[62]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[62]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[62]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[62]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[62]->NotRange.Usage = 0x0004 +pp_data->cap[62]->NotRange.Reserved1 = 0x0004 +pp_data->cap[62]->NotRange.StringIndex = 0 +pp_data->cap[62]->NotRange.Reserved2 = 0 +pp_data->cap[62]->NotRange.DesignatorIndex = 0 +pp_data->cap[62]->NotRange.Reserved3 = 0 +pp_data->cap[62]->NotRange.DataIndex = 62 +pp_data->cap[62]->NotRange.Reserved4 = 62 +pp_data->cap[62]->NotButton.HasNull = 0 +pp_data->cap[62]->NotButton.Reserved4 = 0x000000 +pp_data->cap[62]->NotButton.LogicalMin = 0 +pp_data->cap[62]->NotButton.LogicalMax = 4095 +pp_data->cap[62]->NotButton.PhysicalMin = 0 +pp_data->cap[62]->NotButton.PhysicalMax = 0 +pp_data->cap[62]->Units = 0 +pp_data->cap[62]->UnitsExp = 0 + +pp_data->cap[63]->UsagePage = 0xFF01 +pp_data->cap[63]->ReportID = 0x02 +pp_data->cap[63]->BitPosition = 0 +pp_data->cap[63]->BitSize = 16 +pp_data->cap[63]->ReportCount = 1 +pp_data->cap[63]->BytePosition = 0x002D +pp_data->cap[63]->BitCount = 16 +pp_data->cap[63]->BitField = 0x02 +pp_data->cap[63]->NextBytePosition = 0x002F +pp_data->cap[63]->LinkCollection = 0x0002 +pp_data->cap[63]->LinkUsagePage = 0xFF01 +pp_data->cap[63]->LinkUsage = 0x0002 +pp_data->cap[63]->IsMultipleItemsForArray = 0 +pp_data->cap[63]->IsButtonCap = 0 +pp_data->cap[63]->IsPadding = 0 +pp_data->cap[63]->IsAbsolute = 1 +pp_data->cap[63]->IsRange = 0 +pp_data->cap[63]->IsAlias = 0 +pp_data->cap[63]->IsStringRange = 0 +pp_data->cap[63]->IsDesignatorRange = 0 +pp_data->cap[63]->Reserved1 = 0x000000 +pp_data->cap[63]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[63]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[63]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[63]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[63]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[63]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[63]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[63]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[63]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[63]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[63]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[63]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[63]->NotRange.Usage = 0x0004 +pp_data->cap[63]->NotRange.Reserved1 = 0x0004 +pp_data->cap[63]->NotRange.StringIndex = 0 +pp_data->cap[63]->NotRange.Reserved2 = 0 +pp_data->cap[63]->NotRange.DesignatorIndex = 0 +pp_data->cap[63]->NotRange.Reserved3 = 0 +pp_data->cap[63]->NotRange.DataIndex = 63 +pp_data->cap[63]->NotRange.Reserved4 = 63 +pp_data->cap[63]->NotButton.HasNull = 0 +pp_data->cap[63]->NotButton.Reserved4 = 0x000000 +pp_data->cap[63]->NotButton.LogicalMin = 0 +pp_data->cap[63]->NotButton.LogicalMax = 4095 +pp_data->cap[63]->NotButton.PhysicalMin = 0 +pp_data->cap[63]->NotButton.PhysicalMax = 0 +pp_data->cap[63]->Units = 0 +pp_data->cap[63]->UnitsExp = 0 + +pp_data->cap[64]->UsagePage = 0xFF01 +pp_data->cap[64]->ReportID = 0x02 +pp_data->cap[64]->BitPosition = 0 +pp_data->cap[64]->BitSize = 16 +pp_data->cap[64]->ReportCount = 1 +pp_data->cap[64]->BytePosition = 0x002B +pp_data->cap[64]->BitCount = 16 +pp_data->cap[64]->BitField = 0x02 +pp_data->cap[64]->NextBytePosition = 0x002D +pp_data->cap[64]->LinkCollection = 0x0002 +pp_data->cap[64]->LinkUsagePage = 0xFF01 +pp_data->cap[64]->LinkUsage = 0x0002 +pp_data->cap[64]->IsMultipleItemsForArray = 0 +pp_data->cap[64]->IsButtonCap = 0 +pp_data->cap[64]->IsPadding = 0 +pp_data->cap[64]->IsAbsolute = 1 +pp_data->cap[64]->IsRange = 0 +pp_data->cap[64]->IsAlias = 0 +pp_data->cap[64]->IsStringRange = 0 +pp_data->cap[64]->IsDesignatorRange = 0 +pp_data->cap[64]->Reserved1 = 0x000000 +pp_data->cap[64]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[64]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[64]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[64]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[64]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[64]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[64]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[64]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[64]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[64]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[64]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[64]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[64]->NotRange.Usage = 0x0004 +pp_data->cap[64]->NotRange.Reserved1 = 0x0004 +pp_data->cap[64]->NotRange.StringIndex = 0 +pp_data->cap[64]->NotRange.Reserved2 = 0 +pp_data->cap[64]->NotRange.DesignatorIndex = 0 +pp_data->cap[64]->NotRange.Reserved3 = 0 +pp_data->cap[64]->NotRange.DataIndex = 64 +pp_data->cap[64]->NotRange.Reserved4 = 64 +pp_data->cap[64]->NotButton.HasNull = 0 +pp_data->cap[64]->NotButton.Reserved4 = 0x000000 +pp_data->cap[64]->NotButton.LogicalMin = 0 +pp_data->cap[64]->NotButton.LogicalMax = 4095 +pp_data->cap[64]->NotButton.PhysicalMin = 0 +pp_data->cap[64]->NotButton.PhysicalMax = 0 +pp_data->cap[64]->Units = 0 +pp_data->cap[64]->UnitsExp = 0 + +pp_data->cap[65]->UsagePage = 0xFF01 +pp_data->cap[65]->ReportID = 0x02 +pp_data->cap[65]->BitPosition = 0 +pp_data->cap[65]->BitSize = 16 +pp_data->cap[65]->ReportCount = 1 +pp_data->cap[65]->BytePosition = 0x0029 +pp_data->cap[65]->BitCount = 16 +pp_data->cap[65]->BitField = 0x02 +pp_data->cap[65]->NextBytePosition = 0x002B +pp_data->cap[65]->LinkCollection = 0x0002 +pp_data->cap[65]->LinkUsagePage = 0xFF01 +pp_data->cap[65]->LinkUsage = 0x0002 +pp_data->cap[65]->IsMultipleItemsForArray = 0 +pp_data->cap[65]->IsButtonCap = 0 +pp_data->cap[65]->IsPadding = 0 +pp_data->cap[65]->IsAbsolute = 1 +pp_data->cap[65]->IsRange = 0 +pp_data->cap[65]->IsAlias = 0 +pp_data->cap[65]->IsStringRange = 0 +pp_data->cap[65]->IsDesignatorRange = 0 +pp_data->cap[65]->Reserved1 = 0x000000 +pp_data->cap[65]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[65]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[65]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[65]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[65]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[65]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[65]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[65]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[65]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[65]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[65]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[65]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[65]->NotRange.Usage = 0x0004 +pp_data->cap[65]->NotRange.Reserved1 = 0x0004 +pp_data->cap[65]->NotRange.StringIndex = 0 +pp_data->cap[65]->NotRange.Reserved2 = 0 +pp_data->cap[65]->NotRange.DesignatorIndex = 0 +pp_data->cap[65]->NotRange.Reserved3 = 0 +pp_data->cap[65]->NotRange.DataIndex = 65 +pp_data->cap[65]->NotRange.Reserved4 = 65 +pp_data->cap[65]->NotButton.HasNull = 0 +pp_data->cap[65]->NotButton.Reserved4 = 0x000000 +pp_data->cap[65]->NotButton.LogicalMin = 0 +pp_data->cap[65]->NotButton.LogicalMax = 4095 +pp_data->cap[65]->NotButton.PhysicalMin = 0 +pp_data->cap[65]->NotButton.PhysicalMax = 0 +pp_data->cap[65]->Units = 0 +pp_data->cap[65]->UnitsExp = 0 + +pp_data->cap[66]->UsagePage = 0xFF01 +pp_data->cap[66]->ReportID = 0x02 +pp_data->cap[66]->BitPosition = 0 +pp_data->cap[66]->BitSize = 16 +pp_data->cap[66]->ReportCount = 1 +pp_data->cap[66]->BytePosition = 0x0027 +pp_data->cap[66]->BitCount = 16 +pp_data->cap[66]->BitField = 0x02 +pp_data->cap[66]->NextBytePosition = 0x0029 +pp_data->cap[66]->LinkCollection = 0x0002 +pp_data->cap[66]->LinkUsagePage = 0xFF01 +pp_data->cap[66]->LinkUsage = 0x0002 +pp_data->cap[66]->IsMultipleItemsForArray = 0 +pp_data->cap[66]->IsButtonCap = 0 +pp_data->cap[66]->IsPadding = 0 +pp_data->cap[66]->IsAbsolute = 1 +pp_data->cap[66]->IsRange = 0 +pp_data->cap[66]->IsAlias = 0 +pp_data->cap[66]->IsStringRange = 0 +pp_data->cap[66]->IsDesignatorRange = 0 +pp_data->cap[66]->Reserved1 = 0x000000 +pp_data->cap[66]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[66]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[66]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[66]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[66]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[66]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[66]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[66]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[66]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[66]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[66]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[66]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[66]->NotRange.Usage = 0x0004 +pp_data->cap[66]->NotRange.Reserved1 = 0x0004 +pp_data->cap[66]->NotRange.StringIndex = 0 +pp_data->cap[66]->NotRange.Reserved2 = 0 +pp_data->cap[66]->NotRange.DesignatorIndex = 0 +pp_data->cap[66]->NotRange.Reserved3 = 0 +pp_data->cap[66]->NotRange.DataIndex = 66 +pp_data->cap[66]->NotRange.Reserved4 = 66 +pp_data->cap[66]->NotButton.HasNull = 0 +pp_data->cap[66]->NotButton.Reserved4 = 0x000000 +pp_data->cap[66]->NotButton.LogicalMin = 0 +pp_data->cap[66]->NotButton.LogicalMax = 4095 +pp_data->cap[66]->NotButton.PhysicalMin = 0 +pp_data->cap[66]->NotButton.PhysicalMax = 0 +pp_data->cap[66]->Units = 0 +pp_data->cap[66]->UnitsExp = 0 + +pp_data->cap[67]->UsagePage = 0xFF01 +pp_data->cap[67]->ReportID = 0x02 +pp_data->cap[67]->BitPosition = 0 +pp_data->cap[67]->BitSize = 16 +pp_data->cap[67]->ReportCount = 1 +pp_data->cap[67]->BytePosition = 0x0025 +pp_data->cap[67]->BitCount = 16 +pp_data->cap[67]->BitField = 0x02 +pp_data->cap[67]->NextBytePosition = 0x0027 +pp_data->cap[67]->LinkCollection = 0x0002 +pp_data->cap[67]->LinkUsagePage = 0xFF01 +pp_data->cap[67]->LinkUsage = 0x0002 +pp_data->cap[67]->IsMultipleItemsForArray = 0 +pp_data->cap[67]->IsButtonCap = 0 +pp_data->cap[67]->IsPadding = 0 +pp_data->cap[67]->IsAbsolute = 1 +pp_data->cap[67]->IsRange = 0 +pp_data->cap[67]->IsAlias = 0 +pp_data->cap[67]->IsStringRange = 0 +pp_data->cap[67]->IsDesignatorRange = 0 +pp_data->cap[67]->Reserved1 = 0x000000 +pp_data->cap[67]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[67]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[67]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[67]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[67]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[67]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[67]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[67]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[67]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[67]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[67]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[67]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[67]->NotRange.Usage = 0x0004 +pp_data->cap[67]->NotRange.Reserved1 = 0x0004 +pp_data->cap[67]->NotRange.StringIndex = 0 +pp_data->cap[67]->NotRange.Reserved2 = 0 +pp_data->cap[67]->NotRange.DesignatorIndex = 0 +pp_data->cap[67]->NotRange.Reserved3 = 0 +pp_data->cap[67]->NotRange.DataIndex = 67 +pp_data->cap[67]->NotRange.Reserved4 = 67 +pp_data->cap[67]->NotButton.HasNull = 0 +pp_data->cap[67]->NotButton.Reserved4 = 0x000000 +pp_data->cap[67]->NotButton.LogicalMin = 0 +pp_data->cap[67]->NotButton.LogicalMax = 4095 +pp_data->cap[67]->NotButton.PhysicalMin = 0 +pp_data->cap[67]->NotButton.PhysicalMax = 0 +pp_data->cap[67]->Units = 0 +pp_data->cap[67]->UnitsExp = 0 + +pp_data->cap[68]->UsagePage = 0xFF01 +pp_data->cap[68]->ReportID = 0x02 +pp_data->cap[68]->BitPosition = 0 +pp_data->cap[68]->BitSize = 16 +pp_data->cap[68]->ReportCount = 1 +pp_data->cap[68]->BytePosition = 0x0023 +pp_data->cap[68]->BitCount = 16 +pp_data->cap[68]->BitField = 0x02 +pp_data->cap[68]->NextBytePosition = 0x0025 +pp_data->cap[68]->LinkCollection = 0x0002 +pp_data->cap[68]->LinkUsagePage = 0xFF01 +pp_data->cap[68]->LinkUsage = 0x0002 +pp_data->cap[68]->IsMultipleItemsForArray = 0 +pp_data->cap[68]->IsButtonCap = 0 +pp_data->cap[68]->IsPadding = 0 +pp_data->cap[68]->IsAbsolute = 1 +pp_data->cap[68]->IsRange = 0 +pp_data->cap[68]->IsAlias = 0 +pp_data->cap[68]->IsStringRange = 0 +pp_data->cap[68]->IsDesignatorRange = 0 +pp_data->cap[68]->Reserved1 = 0x000000 +pp_data->cap[68]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[68]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[68]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[68]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[68]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[68]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[68]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[68]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[68]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[68]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[68]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[68]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[68]->NotRange.Usage = 0x0004 +pp_data->cap[68]->NotRange.Reserved1 = 0x0004 +pp_data->cap[68]->NotRange.StringIndex = 0 +pp_data->cap[68]->NotRange.Reserved2 = 0 +pp_data->cap[68]->NotRange.DesignatorIndex = 0 +pp_data->cap[68]->NotRange.Reserved3 = 0 +pp_data->cap[68]->NotRange.DataIndex = 68 +pp_data->cap[68]->NotRange.Reserved4 = 68 +pp_data->cap[68]->NotButton.HasNull = 0 +pp_data->cap[68]->NotButton.Reserved4 = 0x000000 +pp_data->cap[68]->NotButton.LogicalMin = 0 +pp_data->cap[68]->NotButton.LogicalMax = 4095 +pp_data->cap[68]->NotButton.PhysicalMin = 0 +pp_data->cap[68]->NotButton.PhysicalMax = 0 +pp_data->cap[68]->Units = 0 +pp_data->cap[68]->UnitsExp = 0 + +pp_data->cap[69]->UsagePage = 0xFF01 +pp_data->cap[69]->ReportID = 0x02 +pp_data->cap[69]->BitPosition = 0 +pp_data->cap[69]->BitSize = 16 +pp_data->cap[69]->ReportCount = 1 +pp_data->cap[69]->BytePosition = 0x0021 +pp_data->cap[69]->BitCount = 16 +pp_data->cap[69]->BitField = 0x02 +pp_data->cap[69]->NextBytePosition = 0x0023 +pp_data->cap[69]->LinkCollection = 0x0002 +pp_data->cap[69]->LinkUsagePage = 0xFF01 +pp_data->cap[69]->LinkUsage = 0x0002 +pp_data->cap[69]->IsMultipleItemsForArray = 0 +pp_data->cap[69]->IsButtonCap = 0 +pp_data->cap[69]->IsPadding = 0 +pp_data->cap[69]->IsAbsolute = 1 +pp_data->cap[69]->IsRange = 0 +pp_data->cap[69]->IsAlias = 0 +pp_data->cap[69]->IsStringRange = 0 +pp_data->cap[69]->IsDesignatorRange = 0 +pp_data->cap[69]->Reserved1 = 0x000000 +pp_data->cap[69]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[69]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[69]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[69]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[69]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[69]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[69]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[69]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[69]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[69]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[69]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[69]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[69]->NotRange.Usage = 0x0004 +pp_data->cap[69]->NotRange.Reserved1 = 0x0004 +pp_data->cap[69]->NotRange.StringIndex = 0 +pp_data->cap[69]->NotRange.Reserved2 = 0 +pp_data->cap[69]->NotRange.DesignatorIndex = 0 +pp_data->cap[69]->NotRange.Reserved3 = 0 +pp_data->cap[69]->NotRange.DataIndex = 69 +pp_data->cap[69]->NotRange.Reserved4 = 69 +pp_data->cap[69]->NotButton.HasNull = 0 +pp_data->cap[69]->NotButton.Reserved4 = 0x000000 +pp_data->cap[69]->NotButton.LogicalMin = 0 +pp_data->cap[69]->NotButton.LogicalMax = 4095 +pp_data->cap[69]->NotButton.PhysicalMin = 0 +pp_data->cap[69]->NotButton.PhysicalMax = 0 +pp_data->cap[69]->Units = 0 +pp_data->cap[69]->UnitsExp = 0 + +pp_data->cap[70]->UsagePage = 0xFF01 +pp_data->cap[70]->ReportID = 0x02 +pp_data->cap[70]->BitPosition = 0 +pp_data->cap[70]->BitSize = 16 +pp_data->cap[70]->ReportCount = 1 +pp_data->cap[70]->BytePosition = 0x001F +pp_data->cap[70]->BitCount = 16 +pp_data->cap[70]->BitField = 0x02 +pp_data->cap[70]->NextBytePosition = 0x0021 +pp_data->cap[70]->LinkCollection = 0x0002 +pp_data->cap[70]->LinkUsagePage = 0xFF01 +pp_data->cap[70]->LinkUsage = 0x0002 +pp_data->cap[70]->IsMultipleItemsForArray = 0 +pp_data->cap[70]->IsButtonCap = 0 +pp_data->cap[70]->IsPadding = 0 +pp_data->cap[70]->IsAbsolute = 1 +pp_data->cap[70]->IsRange = 0 +pp_data->cap[70]->IsAlias = 0 +pp_data->cap[70]->IsStringRange = 0 +pp_data->cap[70]->IsDesignatorRange = 0 +pp_data->cap[70]->Reserved1 = 0x000000 +pp_data->cap[70]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[70]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[70]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[70]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[70]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[70]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[70]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[70]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[70]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[70]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[70]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[70]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[70]->NotRange.Usage = 0x0004 +pp_data->cap[70]->NotRange.Reserved1 = 0x0004 +pp_data->cap[70]->NotRange.StringIndex = 0 +pp_data->cap[70]->NotRange.Reserved2 = 0 +pp_data->cap[70]->NotRange.DesignatorIndex = 0 +pp_data->cap[70]->NotRange.Reserved3 = 0 +pp_data->cap[70]->NotRange.DataIndex = 70 +pp_data->cap[70]->NotRange.Reserved4 = 70 +pp_data->cap[70]->NotButton.HasNull = 0 +pp_data->cap[70]->NotButton.Reserved4 = 0x000000 +pp_data->cap[70]->NotButton.LogicalMin = 0 +pp_data->cap[70]->NotButton.LogicalMax = 4095 +pp_data->cap[70]->NotButton.PhysicalMin = 0 +pp_data->cap[70]->NotButton.PhysicalMax = 0 +pp_data->cap[70]->Units = 0 +pp_data->cap[70]->UnitsExp = 0 + +pp_data->cap[71]->UsagePage = 0xFF01 +pp_data->cap[71]->ReportID = 0x02 +pp_data->cap[71]->BitPosition = 0 +pp_data->cap[71]->BitSize = 16 +pp_data->cap[71]->ReportCount = 1 +pp_data->cap[71]->BytePosition = 0x001D +pp_data->cap[71]->BitCount = 16 +pp_data->cap[71]->BitField = 0x02 +pp_data->cap[71]->NextBytePosition = 0x001F +pp_data->cap[71]->LinkCollection = 0x0002 +pp_data->cap[71]->LinkUsagePage = 0xFF01 +pp_data->cap[71]->LinkUsage = 0x0002 +pp_data->cap[71]->IsMultipleItemsForArray = 0 +pp_data->cap[71]->IsButtonCap = 0 +pp_data->cap[71]->IsPadding = 0 +pp_data->cap[71]->IsAbsolute = 1 +pp_data->cap[71]->IsRange = 0 +pp_data->cap[71]->IsAlias = 0 +pp_data->cap[71]->IsStringRange = 0 +pp_data->cap[71]->IsDesignatorRange = 0 +pp_data->cap[71]->Reserved1 = 0x000000 +pp_data->cap[71]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[71]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[71]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[71]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[71]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[71]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[71]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[71]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[71]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[71]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[71]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[71]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[71]->NotRange.Usage = 0x0004 +pp_data->cap[71]->NotRange.Reserved1 = 0x0004 +pp_data->cap[71]->NotRange.StringIndex = 0 +pp_data->cap[71]->NotRange.Reserved2 = 0 +pp_data->cap[71]->NotRange.DesignatorIndex = 0 +pp_data->cap[71]->NotRange.Reserved3 = 0 +pp_data->cap[71]->NotRange.DataIndex = 71 +pp_data->cap[71]->NotRange.Reserved4 = 71 +pp_data->cap[71]->NotButton.HasNull = 0 +pp_data->cap[71]->NotButton.Reserved4 = 0x000000 +pp_data->cap[71]->NotButton.LogicalMin = 0 +pp_data->cap[71]->NotButton.LogicalMax = 4095 +pp_data->cap[71]->NotButton.PhysicalMin = 0 +pp_data->cap[71]->NotButton.PhysicalMax = 0 +pp_data->cap[71]->Units = 0 +pp_data->cap[71]->UnitsExp = 0 + +pp_data->cap[72]->UsagePage = 0xFF01 +pp_data->cap[72]->ReportID = 0x02 +pp_data->cap[72]->BitPosition = 0 +pp_data->cap[72]->BitSize = 16 +pp_data->cap[72]->ReportCount = 1 +pp_data->cap[72]->BytePosition = 0x001B +pp_data->cap[72]->BitCount = 16 +pp_data->cap[72]->BitField = 0x02 +pp_data->cap[72]->NextBytePosition = 0x001D +pp_data->cap[72]->LinkCollection = 0x0002 +pp_data->cap[72]->LinkUsagePage = 0xFF01 +pp_data->cap[72]->LinkUsage = 0x0002 +pp_data->cap[72]->IsMultipleItemsForArray = 0 +pp_data->cap[72]->IsButtonCap = 0 +pp_data->cap[72]->IsPadding = 0 +pp_data->cap[72]->IsAbsolute = 1 +pp_data->cap[72]->IsRange = 0 +pp_data->cap[72]->IsAlias = 0 +pp_data->cap[72]->IsStringRange = 0 +pp_data->cap[72]->IsDesignatorRange = 0 +pp_data->cap[72]->Reserved1 = 0x000000 +pp_data->cap[72]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[72]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[72]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[72]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[72]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[72]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[72]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[72]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[72]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[72]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[72]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[72]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[72]->NotRange.Usage = 0x0004 +pp_data->cap[72]->NotRange.Reserved1 = 0x0004 +pp_data->cap[72]->NotRange.StringIndex = 0 +pp_data->cap[72]->NotRange.Reserved2 = 0 +pp_data->cap[72]->NotRange.DesignatorIndex = 0 +pp_data->cap[72]->NotRange.Reserved3 = 0 +pp_data->cap[72]->NotRange.DataIndex = 72 +pp_data->cap[72]->NotRange.Reserved4 = 72 +pp_data->cap[72]->NotButton.HasNull = 0 +pp_data->cap[72]->NotButton.Reserved4 = 0x000000 +pp_data->cap[72]->NotButton.LogicalMin = 0 +pp_data->cap[72]->NotButton.LogicalMax = 4095 +pp_data->cap[72]->NotButton.PhysicalMin = 0 +pp_data->cap[72]->NotButton.PhysicalMax = 0 +pp_data->cap[72]->Units = 0 +pp_data->cap[72]->UnitsExp = 0 + +pp_data->cap[73]->UsagePage = 0xFF01 +pp_data->cap[73]->ReportID = 0x02 +pp_data->cap[73]->BitPosition = 0 +pp_data->cap[73]->BitSize = 16 +pp_data->cap[73]->ReportCount = 1 +pp_data->cap[73]->BytePosition = 0x0019 +pp_data->cap[73]->BitCount = 16 +pp_data->cap[73]->BitField = 0x02 +pp_data->cap[73]->NextBytePosition = 0x001B +pp_data->cap[73]->LinkCollection = 0x0002 +pp_data->cap[73]->LinkUsagePage = 0xFF01 +pp_data->cap[73]->LinkUsage = 0x0002 +pp_data->cap[73]->IsMultipleItemsForArray = 0 +pp_data->cap[73]->IsButtonCap = 0 +pp_data->cap[73]->IsPadding = 0 +pp_data->cap[73]->IsAbsolute = 1 +pp_data->cap[73]->IsRange = 0 +pp_data->cap[73]->IsAlias = 0 +pp_data->cap[73]->IsStringRange = 0 +pp_data->cap[73]->IsDesignatorRange = 0 +pp_data->cap[73]->Reserved1 = 0x000000 +pp_data->cap[73]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[73]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[73]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[73]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[73]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[73]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[73]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[73]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[73]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[73]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[73]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[73]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[73]->NotRange.Usage = 0x0004 +pp_data->cap[73]->NotRange.Reserved1 = 0x0004 +pp_data->cap[73]->NotRange.StringIndex = 0 +pp_data->cap[73]->NotRange.Reserved2 = 0 +pp_data->cap[73]->NotRange.DesignatorIndex = 0 +pp_data->cap[73]->NotRange.Reserved3 = 0 +pp_data->cap[73]->NotRange.DataIndex = 73 +pp_data->cap[73]->NotRange.Reserved4 = 73 +pp_data->cap[73]->NotButton.HasNull = 0 +pp_data->cap[73]->NotButton.Reserved4 = 0x000000 +pp_data->cap[73]->NotButton.LogicalMin = 0 +pp_data->cap[73]->NotButton.LogicalMax = 4095 +pp_data->cap[73]->NotButton.PhysicalMin = 0 +pp_data->cap[73]->NotButton.PhysicalMax = 0 +pp_data->cap[73]->Units = 0 +pp_data->cap[73]->UnitsExp = 0 + +pp_data->cap[74]->UsagePage = 0xFF01 +pp_data->cap[74]->ReportID = 0x02 +pp_data->cap[74]->BitPosition = 0 +pp_data->cap[74]->BitSize = 16 +pp_data->cap[74]->ReportCount = 1 +pp_data->cap[74]->BytePosition = 0x0017 +pp_data->cap[74]->BitCount = 16 +pp_data->cap[74]->BitField = 0x02 +pp_data->cap[74]->NextBytePosition = 0x0019 +pp_data->cap[74]->LinkCollection = 0x0002 +pp_data->cap[74]->LinkUsagePage = 0xFF01 +pp_data->cap[74]->LinkUsage = 0x0002 +pp_data->cap[74]->IsMultipleItemsForArray = 0 +pp_data->cap[74]->IsButtonCap = 0 +pp_data->cap[74]->IsPadding = 0 +pp_data->cap[74]->IsAbsolute = 1 +pp_data->cap[74]->IsRange = 0 +pp_data->cap[74]->IsAlias = 0 +pp_data->cap[74]->IsStringRange = 0 +pp_data->cap[74]->IsDesignatorRange = 0 +pp_data->cap[74]->Reserved1 = 0x000000 +pp_data->cap[74]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[74]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[74]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[74]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[74]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[74]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[74]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[74]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[74]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[74]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[74]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[74]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[74]->NotRange.Usage = 0x0004 +pp_data->cap[74]->NotRange.Reserved1 = 0x0004 +pp_data->cap[74]->NotRange.StringIndex = 0 +pp_data->cap[74]->NotRange.Reserved2 = 0 +pp_data->cap[74]->NotRange.DesignatorIndex = 0 +pp_data->cap[74]->NotRange.Reserved3 = 0 +pp_data->cap[74]->NotRange.DataIndex = 74 +pp_data->cap[74]->NotRange.Reserved4 = 74 +pp_data->cap[74]->NotButton.HasNull = 0 +pp_data->cap[74]->NotButton.Reserved4 = 0x000000 +pp_data->cap[74]->NotButton.LogicalMin = 0 +pp_data->cap[74]->NotButton.LogicalMax = 4095 +pp_data->cap[74]->NotButton.PhysicalMin = 0 +pp_data->cap[74]->NotButton.PhysicalMax = 0 +pp_data->cap[74]->Units = 0 +pp_data->cap[74]->UnitsExp = 0 + +pp_data->cap[75]->UsagePage = 0xFF01 +pp_data->cap[75]->ReportID = 0x02 +pp_data->cap[75]->BitPosition = 0 +pp_data->cap[75]->BitSize = 16 +pp_data->cap[75]->ReportCount = 1 +pp_data->cap[75]->BytePosition = 0x0015 +pp_data->cap[75]->BitCount = 16 +pp_data->cap[75]->BitField = 0x02 +pp_data->cap[75]->NextBytePosition = 0x0017 +pp_data->cap[75]->LinkCollection = 0x0002 +pp_data->cap[75]->LinkUsagePage = 0xFF01 +pp_data->cap[75]->LinkUsage = 0x0002 +pp_data->cap[75]->IsMultipleItemsForArray = 0 +pp_data->cap[75]->IsButtonCap = 0 +pp_data->cap[75]->IsPadding = 0 +pp_data->cap[75]->IsAbsolute = 1 +pp_data->cap[75]->IsRange = 0 +pp_data->cap[75]->IsAlias = 0 +pp_data->cap[75]->IsStringRange = 0 +pp_data->cap[75]->IsDesignatorRange = 0 +pp_data->cap[75]->Reserved1 = 0x000000 +pp_data->cap[75]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[75]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[75]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[75]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[75]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[75]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[75]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[75]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[75]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[75]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[75]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[75]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[75]->NotRange.Usage = 0x0004 +pp_data->cap[75]->NotRange.Reserved1 = 0x0004 +pp_data->cap[75]->NotRange.StringIndex = 0 +pp_data->cap[75]->NotRange.Reserved2 = 0 +pp_data->cap[75]->NotRange.DesignatorIndex = 0 +pp_data->cap[75]->NotRange.Reserved3 = 0 +pp_data->cap[75]->NotRange.DataIndex = 75 +pp_data->cap[75]->NotRange.Reserved4 = 75 +pp_data->cap[75]->NotButton.HasNull = 0 +pp_data->cap[75]->NotButton.Reserved4 = 0x000000 +pp_data->cap[75]->NotButton.LogicalMin = 0 +pp_data->cap[75]->NotButton.LogicalMax = 4095 +pp_data->cap[75]->NotButton.PhysicalMin = 0 +pp_data->cap[75]->NotButton.PhysicalMax = 0 +pp_data->cap[75]->Units = 0 +pp_data->cap[75]->UnitsExp = 0 + +pp_data->cap[76]->UsagePage = 0xFF01 +pp_data->cap[76]->ReportID = 0x02 +pp_data->cap[76]->BitPosition = 0 +pp_data->cap[76]->BitSize = 16 +pp_data->cap[76]->ReportCount = 1 +pp_data->cap[76]->BytePosition = 0x0013 +pp_data->cap[76]->BitCount = 16 +pp_data->cap[76]->BitField = 0x02 +pp_data->cap[76]->NextBytePosition = 0x0015 +pp_data->cap[76]->LinkCollection = 0x0002 +pp_data->cap[76]->LinkUsagePage = 0xFF01 +pp_data->cap[76]->LinkUsage = 0x0002 +pp_data->cap[76]->IsMultipleItemsForArray = 0 +pp_data->cap[76]->IsButtonCap = 0 +pp_data->cap[76]->IsPadding = 0 +pp_data->cap[76]->IsAbsolute = 1 +pp_data->cap[76]->IsRange = 0 +pp_data->cap[76]->IsAlias = 0 +pp_data->cap[76]->IsStringRange = 0 +pp_data->cap[76]->IsDesignatorRange = 0 +pp_data->cap[76]->Reserved1 = 0x000000 +pp_data->cap[76]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[76]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[76]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[76]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[76]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[76]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[76]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[76]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[76]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[76]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[76]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[76]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[76]->NotRange.Usage = 0x0004 +pp_data->cap[76]->NotRange.Reserved1 = 0x0004 +pp_data->cap[76]->NotRange.StringIndex = 0 +pp_data->cap[76]->NotRange.Reserved2 = 0 +pp_data->cap[76]->NotRange.DesignatorIndex = 0 +pp_data->cap[76]->NotRange.Reserved3 = 0 +pp_data->cap[76]->NotRange.DataIndex = 76 +pp_data->cap[76]->NotRange.Reserved4 = 76 +pp_data->cap[76]->NotButton.HasNull = 0 +pp_data->cap[76]->NotButton.Reserved4 = 0x000000 +pp_data->cap[76]->NotButton.LogicalMin = 0 +pp_data->cap[76]->NotButton.LogicalMax = 4095 +pp_data->cap[76]->NotButton.PhysicalMin = 0 +pp_data->cap[76]->NotButton.PhysicalMax = 0 +pp_data->cap[76]->Units = 0 +pp_data->cap[76]->UnitsExp = 0 + +pp_data->cap[77]->UsagePage = 0xFF01 +pp_data->cap[77]->ReportID = 0x02 +pp_data->cap[77]->BitPosition = 0 +pp_data->cap[77]->BitSize = 16 +pp_data->cap[77]->ReportCount = 1 +pp_data->cap[77]->BytePosition = 0x0011 +pp_data->cap[77]->BitCount = 16 +pp_data->cap[77]->BitField = 0x02 +pp_data->cap[77]->NextBytePosition = 0x0013 +pp_data->cap[77]->LinkCollection = 0x0002 +pp_data->cap[77]->LinkUsagePage = 0xFF01 +pp_data->cap[77]->LinkUsage = 0x0002 +pp_data->cap[77]->IsMultipleItemsForArray = 0 +pp_data->cap[77]->IsButtonCap = 0 +pp_data->cap[77]->IsPadding = 0 +pp_data->cap[77]->IsAbsolute = 1 +pp_data->cap[77]->IsRange = 0 +pp_data->cap[77]->IsAlias = 0 +pp_data->cap[77]->IsStringRange = 0 +pp_data->cap[77]->IsDesignatorRange = 0 +pp_data->cap[77]->Reserved1 = 0x000000 +pp_data->cap[77]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[77]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[77]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[77]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[77]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[77]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[77]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[77]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[77]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[77]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[77]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[77]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[77]->NotRange.Usage = 0x0004 +pp_data->cap[77]->NotRange.Reserved1 = 0x0004 +pp_data->cap[77]->NotRange.StringIndex = 0 +pp_data->cap[77]->NotRange.Reserved2 = 0 +pp_data->cap[77]->NotRange.DesignatorIndex = 0 +pp_data->cap[77]->NotRange.Reserved3 = 0 +pp_data->cap[77]->NotRange.DataIndex = 77 +pp_data->cap[77]->NotRange.Reserved4 = 77 +pp_data->cap[77]->NotButton.HasNull = 0 +pp_data->cap[77]->NotButton.Reserved4 = 0x000000 +pp_data->cap[77]->NotButton.LogicalMin = 0 +pp_data->cap[77]->NotButton.LogicalMax = 4095 +pp_data->cap[77]->NotButton.PhysicalMin = 0 +pp_data->cap[77]->NotButton.PhysicalMax = 0 +pp_data->cap[77]->Units = 0 +pp_data->cap[77]->UnitsExp = 0 + +pp_data->cap[78]->UsagePage = 0xFF01 +pp_data->cap[78]->ReportID = 0x02 +pp_data->cap[78]->BitPosition = 0 +pp_data->cap[78]->BitSize = 16 +pp_data->cap[78]->ReportCount = 1 +pp_data->cap[78]->BytePosition = 0x000F +pp_data->cap[78]->BitCount = 16 +pp_data->cap[78]->BitField = 0x02 +pp_data->cap[78]->NextBytePosition = 0x0011 +pp_data->cap[78]->LinkCollection = 0x0002 +pp_data->cap[78]->LinkUsagePage = 0xFF01 +pp_data->cap[78]->LinkUsage = 0x0002 +pp_data->cap[78]->IsMultipleItemsForArray = 0 +pp_data->cap[78]->IsButtonCap = 0 +pp_data->cap[78]->IsPadding = 0 +pp_data->cap[78]->IsAbsolute = 1 +pp_data->cap[78]->IsRange = 0 +pp_data->cap[78]->IsAlias = 0 +pp_data->cap[78]->IsStringRange = 0 +pp_data->cap[78]->IsDesignatorRange = 0 +pp_data->cap[78]->Reserved1 = 0x000000 +pp_data->cap[78]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[78]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[78]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[78]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[78]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[78]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[78]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[78]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[78]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[78]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[78]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[78]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[78]->NotRange.Usage = 0x0004 +pp_data->cap[78]->NotRange.Reserved1 = 0x0004 +pp_data->cap[78]->NotRange.StringIndex = 0 +pp_data->cap[78]->NotRange.Reserved2 = 0 +pp_data->cap[78]->NotRange.DesignatorIndex = 0 +pp_data->cap[78]->NotRange.Reserved3 = 0 +pp_data->cap[78]->NotRange.DataIndex = 78 +pp_data->cap[78]->NotRange.Reserved4 = 78 +pp_data->cap[78]->NotButton.HasNull = 0 +pp_data->cap[78]->NotButton.Reserved4 = 0x000000 +pp_data->cap[78]->NotButton.LogicalMin = 0 +pp_data->cap[78]->NotButton.LogicalMax = 4095 +pp_data->cap[78]->NotButton.PhysicalMin = 0 +pp_data->cap[78]->NotButton.PhysicalMax = 0 +pp_data->cap[78]->Units = 0 +pp_data->cap[78]->UnitsExp = 0 + +pp_data->cap[79]->UsagePage = 0xFF01 +pp_data->cap[79]->ReportID = 0x02 +pp_data->cap[79]->BitPosition = 0 +pp_data->cap[79]->BitSize = 16 +pp_data->cap[79]->ReportCount = 1 +pp_data->cap[79]->BytePosition = 0x000D +pp_data->cap[79]->BitCount = 16 +pp_data->cap[79]->BitField = 0x02 +pp_data->cap[79]->NextBytePosition = 0x000F +pp_data->cap[79]->LinkCollection = 0x0002 +pp_data->cap[79]->LinkUsagePage = 0xFF01 +pp_data->cap[79]->LinkUsage = 0x0002 +pp_data->cap[79]->IsMultipleItemsForArray = 0 +pp_data->cap[79]->IsButtonCap = 0 +pp_data->cap[79]->IsPadding = 0 +pp_data->cap[79]->IsAbsolute = 1 +pp_data->cap[79]->IsRange = 0 +pp_data->cap[79]->IsAlias = 0 +pp_data->cap[79]->IsStringRange = 0 +pp_data->cap[79]->IsDesignatorRange = 0 +pp_data->cap[79]->Reserved1 = 0x000000 +pp_data->cap[79]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[79]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[79]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[79]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[79]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[79]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[79]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[79]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[79]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[79]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[79]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[79]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[79]->NotRange.Usage = 0x0004 +pp_data->cap[79]->NotRange.Reserved1 = 0x0004 +pp_data->cap[79]->NotRange.StringIndex = 0 +pp_data->cap[79]->NotRange.Reserved2 = 0 +pp_data->cap[79]->NotRange.DesignatorIndex = 0 +pp_data->cap[79]->NotRange.Reserved3 = 0 +pp_data->cap[79]->NotRange.DataIndex = 79 +pp_data->cap[79]->NotRange.Reserved4 = 79 +pp_data->cap[79]->NotButton.HasNull = 0 +pp_data->cap[79]->NotButton.Reserved4 = 0x000000 +pp_data->cap[79]->NotButton.LogicalMin = 0 +pp_data->cap[79]->NotButton.LogicalMax = 4095 +pp_data->cap[79]->NotButton.PhysicalMin = 0 +pp_data->cap[79]->NotButton.PhysicalMax = 0 +pp_data->cap[79]->Units = 0 +pp_data->cap[79]->UnitsExp = 0 + +pp_data->cap[80]->UsagePage = 0xFF01 +pp_data->cap[80]->ReportID = 0x02 +pp_data->cap[80]->BitPosition = 0 +pp_data->cap[80]->BitSize = 16 +pp_data->cap[80]->ReportCount = 1 +pp_data->cap[80]->BytePosition = 0x000B +pp_data->cap[80]->BitCount = 16 +pp_data->cap[80]->BitField = 0x02 +pp_data->cap[80]->NextBytePosition = 0x000D +pp_data->cap[80]->LinkCollection = 0x0002 +pp_data->cap[80]->LinkUsagePage = 0xFF01 +pp_data->cap[80]->LinkUsage = 0x0002 +pp_data->cap[80]->IsMultipleItemsForArray = 0 +pp_data->cap[80]->IsButtonCap = 0 +pp_data->cap[80]->IsPadding = 0 +pp_data->cap[80]->IsAbsolute = 1 +pp_data->cap[80]->IsRange = 0 +pp_data->cap[80]->IsAlias = 0 +pp_data->cap[80]->IsStringRange = 0 +pp_data->cap[80]->IsDesignatorRange = 0 +pp_data->cap[80]->Reserved1 = 0x000000 +pp_data->cap[80]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[80]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[80]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[80]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[80]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[80]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[80]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[80]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[80]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[80]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[80]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[80]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[80]->NotRange.Usage = 0x0004 +pp_data->cap[80]->NotRange.Reserved1 = 0x0004 +pp_data->cap[80]->NotRange.StringIndex = 0 +pp_data->cap[80]->NotRange.Reserved2 = 0 +pp_data->cap[80]->NotRange.DesignatorIndex = 0 +pp_data->cap[80]->NotRange.Reserved3 = 0 +pp_data->cap[80]->NotRange.DataIndex = 80 +pp_data->cap[80]->NotRange.Reserved4 = 80 +pp_data->cap[80]->NotButton.HasNull = 0 +pp_data->cap[80]->NotButton.Reserved4 = 0x000000 +pp_data->cap[80]->NotButton.LogicalMin = 0 +pp_data->cap[80]->NotButton.LogicalMax = 4095 +pp_data->cap[80]->NotButton.PhysicalMin = 0 +pp_data->cap[80]->NotButton.PhysicalMax = 0 +pp_data->cap[80]->Units = 0 +pp_data->cap[80]->UnitsExp = 0 + +pp_data->cap[81]->UsagePage = 0xFF01 +pp_data->cap[81]->ReportID = 0x02 +pp_data->cap[81]->BitPosition = 0 +pp_data->cap[81]->BitSize = 16 +pp_data->cap[81]->ReportCount = 1 +pp_data->cap[81]->BytePosition = 0x0009 +pp_data->cap[81]->BitCount = 16 +pp_data->cap[81]->BitField = 0x02 +pp_data->cap[81]->NextBytePosition = 0x000B +pp_data->cap[81]->LinkCollection = 0x0002 +pp_data->cap[81]->LinkUsagePage = 0xFF01 +pp_data->cap[81]->LinkUsage = 0x0002 +pp_data->cap[81]->IsMultipleItemsForArray = 0 +pp_data->cap[81]->IsButtonCap = 0 +pp_data->cap[81]->IsPadding = 0 +pp_data->cap[81]->IsAbsolute = 1 +pp_data->cap[81]->IsRange = 0 +pp_data->cap[81]->IsAlias = 0 +pp_data->cap[81]->IsStringRange = 0 +pp_data->cap[81]->IsDesignatorRange = 0 +pp_data->cap[81]->Reserved1 = 0x000000 +pp_data->cap[81]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[81]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[81]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[81]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[81]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[81]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[81]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[81]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[81]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[81]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[81]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[81]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[81]->NotRange.Usage = 0x0004 +pp_data->cap[81]->NotRange.Reserved1 = 0x0004 +pp_data->cap[81]->NotRange.StringIndex = 0 +pp_data->cap[81]->NotRange.Reserved2 = 0 +pp_data->cap[81]->NotRange.DesignatorIndex = 0 +pp_data->cap[81]->NotRange.Reserved3 = 0 +pp_data->cap[81]->NotRange.DataIndex = 81 +pp_data->cap[81]->NotRange.Reserved4 = 81 +pp_data->cap[81]->NotButton.HasNull = 0 +pp_data->cap[81]->NotButton.Reserved4 = 0x000000 +pp_data->cap[81]->NotButton.LogicalMin = 0 +pp_data->cap[81]->NotButton.LogicalMax = 4095 +pp_data->cap[81]->NotButton.PhysicalMin = 0 +pp_data->cap[81]->NotButton.PhysicalMax = 0 +pp_data->cap[81]->Units = 0 +pp_data->cap[81]->UnitsExp = 0 + +pp_data->cap[82]->UsagePage = 0xFF01 +pp_data->cap[82]->ReportID = 0x02 +pp_data->cap[82]->BitPosition = 0 +pp_data->cap[82]->BitSize = 16 +pp_data->cap[82]->ReportCount = 1 +pp_data->cap[82]->BytePosition = 0x0007 +pp_data->cap[82]->BitCount = 16 +pp_data->cap[82]->BitField = 0x02 +pp_data->cap[82]->NextBytePosition = 0x0009 +pp_data->cap[82]->LinkCollection = 0x0002 +pp_data->cap[82]->LinkUsagePage = 0xFF01 +pp_data->cap[82]->LinkUsage = 0x0002 +pp_data->cap[82]->IsMultipleItemsForArray = 0 +pp_data->cap[82]->IsButtonCap = 0 +pp_data->cap[82]->IsPadding = 0 +pp_data->cap[82]->IsAbsolute = 1 +pp_data->cap[82]->IsRange = 0 +pp_data->cap[82]->IsAlias = 0 +pp_data->cap[82]->IsStringRange = 0 +pp_data->cap[82]->IsDesignatorRange = 0 +pp_data->cap[82]->Reserved1 = 0x000000 +pp_data->cap[82]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[82]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[82]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[82]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[82]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[82]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[82]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[82]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[82]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[82]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[82]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[82]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[82]->NotRange.Usage = 0x0004 +pp_data->cap[82]->NotRange.Reserved1 = 0x0004 +pp_data->cap[82]->NotRange.StringIndex = 0 +pp_data->cap[82]->NotRange.Reserved2 = 0 +pp_data->cap[82]->NotRange.DesignatorIndex = 0 +pp_data->cap[82]->NotRange.Reserved3 = 0 +pp_data->cap[82]->NotRange.DataIndex = 82 +pp_data->cap[82]->NotRange.Reserved4 = 82 +pp_data->cap[82]->NotButton.HasNull = 0 +pp_data->cap[82]->NotButton.Reserved4 = 0x000000 +pp_data->cap[82]->NotButton.LogicalMin = 0 +pp_data->cap[82]->NotButton.LogicalMax = 4095 +pp_data->cap[82]->NotButton.PhysicalMin = 0 +pp_data->cap[82]->NotButton.PhysicalMax = 0 +pp_data->cap[82]->Units = 0 +pp_data->cap[82]->UnitsExp = 0 + +pp_data->cap[83]->UsagePage = 0xFF01 +pp_data->cap[83]->ReportID = 0x02 +pp_data->cap[83]->BitPosition = 0 +pp_data->cap[83]->BitSize = 16 +pp_data->cap[83]->ReportCount = 1 +pp_data->cap[83]->BytePosition = 0x0005 +pp_data->cap[83]->BitCount = 16 +pp_data->cap[83]->BitField = 0x02 +pp_data->cap[83]->NextBytePosition = 0x0007 +pp_data->cap[83]->LinkCollection = 0x0002 +pp_data->cap[83]->LinkUsagePage = 0xFF01 +pp_data->cap[83]->LinkUsage = 0x0002 +pp_data->cap[83]->IsMultipleItemsForArray = 0 +pp_data->cap[83]->IsButtonCap = 0 +pp_data->cap[83]->IsPadding = 0 +pp_data->cap[83]->IsAbsolute = 1 +pp_data->cap[83]->IsRange = 0 +pp_data->cap[83]->IsAlias = 0 +pp_data->cap[83]->IsStringRange = 0 +pp_data->cap[83]->IsDesignatorRange = 0 +pp_data->cap[83]->Reserved1 = 0x000000 +pp_data->cap[83]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[83]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[83]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[83]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[83]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[83]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[83]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[83]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[83]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[83]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[83]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[83]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[83]->NotRange.Usage = 0x0004 +pp_data->cap[83]->NotRange.Reserved1 = 0x0004 +pp_data->cap[83]->NotRange.StringIndex = 0 +pp_data->cap[83]->NotRange.Reserved2 = 0 +pp_data->cap[83]->NotRange.DesignatorIndex = 0 +pp_data->cap[83]->NotRange.Reserved3 = 0 +pp_data->cap[83]->NotRange.DataIndex = 83 +pp_data->cap[83]->NotRange.Reserved4 = 83 +pp_data->cap[83]->NotButton.HasNull = 0 +pp_data->cap[83]->NotButton.Reserved4 = 0x000000 +pp_data->cap[83]->NotButton.LogicalMin = 0 +pp_data->cap[83]->NotButton.LogicalMax = 4095 +pp_data->cap[83]->NotButton.PhysicalMin = 0 +pp_data->cap[83]->NotButton.PhysicalMax = 0 +pp_data->cap[83]->Units = 0 +pp_data->cap[83]->UnitsExp = 0 + +pp_data->cap[84]->UsagePage = 0xFF01 +pp_data->cap[84]->ReportID = 0x02 +pp_data->cap[84]->BitPosition = 0 +pp_data->cap[84]->BitSize = 16 +pp_data->cap[84]->ReportCount = 1 +pp_data->cap[84]->BytePosition = 0x0003 +pp_data->cap[84]->BitCount = 16 +pp_data->cap[84]->BitField = 0x02 +pp_data->cap[84]->NextBytePosition = 0x0005 +pp_data->cap[84]->LinkCollection = 0x0002 +pp_data->cap[84]->LinkUsagePage = 0xFF01 +pp_data->cap[84]->LinkUsage = 0x0002 +pp_data->cap[84]->IsMultipleItemsForArray = 0 +pp_data->cap[84]->IsButtonCap = 0 +pp_data->cap[84]->IsPadding = 0 +pp_data->cap[84]->IsAbsolute = 1 +pp_data->cap[84]->IsRange = 0 +pp_data->cap[84]->IsAlias = 0 +pp_data->cap[84]->IsStringRange = 0 +pp_data->cap[84]->IsDesignatorRange = 0 +pp_data->cap[84]->Reserved1 = 0x000000 +pp_data->cap[84]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[84]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[84]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[84]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[84]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[84]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[84]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[84]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[84]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[84]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[84]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[84]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[84]->NotRange.Usage = 0x0004 +pp_data->cap[84]->NotRange.Reserved1 = 0x0004 +pp_data->cap[84]->NotRange.StringIndex = 0 +pp_data->cap[84]->NotRange.Reserved2 = 0 +pp_data->cap[84]->NotRange.DesignatorIndex = 0 +pp_data->cap[84]->NotRange.Reserved3 = 0 +pp_data->cap[84]->NotRange.DataIndex = 84 +pp_data->cap[84]->NotRange.Reserved4 = 84 +pp_data->cap[84]->NotButton.HasNull = 0 +pp_data->cap[84]->NotButton.Reserved4 = 0x000000 +pp_data->cap[84]->NotButton.LogicalMin = 0 +pp_data->cap[84]->NotButton.LogicalMax = 4095 +pp_data->cap[84]->NotButton.PhysicalMin = 0 +pp_data->cap[84]->NotButton.PhysicalMax = 0 +pp_data->cap[84]->Units = 0 +pp_data->cap[84]->UnitsExp = 0 + +pp_data->cap[85]->UsagePage = 0xFF01 +pp_data->cap[85]->ReportID = 0x02 +pp_data->cap[85]->BitPosition = 0 +pp_data->cap[85]->BitSize = 16 +pp_data->cap[85]->ReportCount = 1 +pp_data->cap[85]->BytePosition = 0x0001 +pp_data->cap[85]->BitCount = 16 +pp_data->cap[85]->BitField = 0x02 +pp_data->cap[85]->NextBytePosition = 0x0003 +pp_data->cap[85]->LinkCollection = 0x0002 +pp_data->cap[85]->LinkUsagePage = 0xFF01 +pp_data->cap[85]->LinkUsage = 0x0002 +pp_data->cap[85]->IsMultipleItemsForArray = 0 +pp_data->cap[85]->IsButtonCap = 0 +pp_data->cap[85]->IsPadding = 0 +pp_data->cap[85]->IsAbsolute = 1 +pp_data->cap[85]->IsRange = 0 +pp_data->cap[85]->IsAlias = 0 +pp_data->cap[85]->IsStringRange = 0 +pp_data->cap[85]->IsDesignatorRange = 0 +pp_data->cap[85]->Reserved1 = 0x000000 +pp_data->cap[85]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[85]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[85]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[85]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[85]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[85]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[85]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[85]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[85]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[85]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[85]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[85]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[85]->NotRange.Usage = 0x0004 +pp_data->cap[85]->NotRange.Reserved1 = 0x0004 +pp_data->cap[85]->NotRange.StringIndex = 0 +pp_data->cap[85]->NotRange.Reserved2 = 0 +pp_data->cap[85]->NotRange.DesignatorIndex = 0 +pp_data->cap[85]->NotRange.Reserved3 = 0 +pp_data->cap[85]->NotRange.DataIndex = 85 +pp_data->cap[85]->NotRange.Reserved4 = 85 +pp_data->cap[85]->NotButton.HasNull = 0 +pp_data->cap[85]->NotButton.Reserved4 = 0x000000 +pp_data->cap[85]->NotButton.LogicalMin = 0 +pp_data->cap[85]->NotButton.LogicalMax = 4095 +pp_data->cap[85]->NotButton.PhysicalMin = 0 +pp_data->cap[85]->NotButton.PhysicalMax = 0 +pp_data->cap[85]->Units = 0 +pp_data->cap[85]->UnitsExp = 0 + +# Output hid_pp_cap struct: +pp_data->cap[87]->UsagePage = 0xFF01 +pp_data->cap[87]->ReportID = 0x80 +pp_data->cap[87]->BitPosition = 0 +pp_data->cap[87]->BitSize = 8 +pp_data->cap[87]->ReportCount = 1 +pp_data->cap[87]->BytePosition = 0x005E +pp_data->cap[87]->BitCount = 8 +pp_data->cap[87]->BitField = 0x02 +pp_data->cap[87]->NextBytePosition = 0x005F +pp_data->cap[87]->LinkCollection = 0x0003 +pp_data->cap[87]->LinkUsagePage = 0xFF01 +pp_data->cap[87]->LinkUsage = 0x0080 +pp_data->cap[87]->IsMultipleItemsForArray = 0 +pp_data->cap[87]->IsButtonCap = 0 +pp_data->cap[87]->IsPadding = 0 +pp_data->cap[87]->IsAbsolute = 1 +pp_data->cap[87]->IsRange = 0 +pp_data->cap[87]->IsAlias = 0 +pp_data->cap[87]->IsStringRange = 0 +pp_data->cap[87]->IsDesignatorRange = 0 +pp_data->cap[87]->Reserved1 = 0x000000 +pp_data->cap[87]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[87]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[87]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[87]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[87]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[87]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[87]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[87]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[87]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[87]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[87]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[87]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[87]->NotRange.Usage = 0x0081 +pp_data->cap[87]->NotRange.Reserved1 = 0x0081 +pp_data->cap[87]->NotRange.StringIndex = 0 +pp_data->cap[87]->NotRange.Reserved2 = 0 +pp_data->cap[87]->NotRange.DesignatorIndex = 0 +pp_data->cap[87]->NotRange.Reserved3 = 0 +pp_data->cap[87]->NotRange.DataIndex = 0 +pp_data->cap[87]->NotRange.Reserved4 = 0 +pp_data->cap[87]->NotButton.HasNull = 0 +pp_data->cap[87]->NotButton.Reserved4 = 0x000000 +pp_data->cap[87]->NotButton.LogicalMin = 0 +pp_data->cap[87]->NotButton.LogicalMax = 127 +pp_data->cap[87]->NotButton.PhysicalMin = 0 +pp_data->cap[87]->NotButton.PhysicalMax = 0 +pp_data->cap[87]->Units = 0 +pp_data->cap[87]->UnitsExp = 0 + +pp_data->cap[88]->UsagePage = 0xFF01 +pp_data->cap[88]->ReportID = 0x80 +pp_data->cap[88]->BitPosition = 0 +pp_data->cap[88]->BitSize = 8 +pp_data->cap[88]->ReportCount = 1 +pp_data->cap[88]->BytePosition = 0x005D +pp_data->cap[88]->BitCount = 8 +pp_data->cap[88]->BitField = 0x02 +pp_data->cap[88]->NextBytePosition = 0x005E +pp_data->cap[88]->LinkCollection = 0x0003 +pp_data->cap[88]->LinkUsagePage = 0xFF01 +pp_data->cap[88]->LinkUsage = 0x0080 +pp_data->cap[88]->IsMultipleItemsForArray = 0 +pp_data->cap[88]->IsButtonCap = 0 +pp_data->cap[88]->IsPadding = 0 +pp_data->cap[88]->IsAbsolute = 1 +pp_data->cap[88]->IsRange = 0 +pp_data->cap[88]->IsAlias = 0 +pp_data->cap[88]->IsStringRange = 0 +pp_data->cap[88]->IsDesignatorRange = 0 +pp_data->cap[88]->Reserved1 = 0x000000 +pp_data->cap[88]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[88]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[88]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[88]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[88]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[88]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[88]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[88]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[88]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[88]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[88]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[88]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[88]->NotRange.Usage = 0x0081 +pp_data->cap[88]->NotRange.Reserved1 = 0x0081 +pp_data->cap[88]->NotRange.StringIndex = 0 +pp_data->cap[88]->NotRange.Reserved2 = 0 +pp_data->cap[88]->NotRange.DesignatorIndex = 0 +pp_data->cap[88]->NotRange.Reserved3 = 0 +pp_data->cap[88]->NotRange.DataIndex = 1 +pp_data->cap[88]->NotRange.Reserved4 = 1 +pp_data->cap[88]->NotButton.HasNull = 0 +pp_data->cap[88]->NotButton.Reserved4 = 0x000000 +pp_data->cap[88]->NotButton.LogicalMin = 0 +pp_data->cap[88]->NotButton.LogicalMax = 127 +pp_data->cap[88]->NotButton.PhysicalMin = 0 +pp_data->cap[88]->NotButton.PhysicalMax = 0 +pp_data->cap[88]->Units = 0 +pp_data->cap[88]->UnitsExp = 0 + +pp_data->cap[89]->UsagePage = 0xFF01 +pp_data->cap[89]->ReportID = 0x80 +pp_data->cap[89]->BitPosition = 0 +pp_data->cap[89]->BitSize = 8 +pp_data->cap[89]->ReportCount = 1 +pp_data->cap[89]->BytePosition = 0x005C +pp_data->cap[89]->BitCount = 8 +pp_data->cap[89]->BitField = 0x02 +pp_data->cap[89]->NextBytePosition = 0x005D +pp_data->cap[89]->LinkCollection = 0x0003 +pp_data->cap[89]->LinkUsagePage = 0xFF01 +pp_data->cap[89]->LinkUsage = 0x0080 +pp_data->cap[89]->IsMultipleItemsForArray = 0 +pp_data->cap[89]->IsButtonCap = 0 +pp_data->cap[89]->IsPadding = 0 +pp_data->cap[89]->IsAbsolute = 1 +pp_data->cap[89]->IsRange = 0 +pp_data->cap[89]->IsAlias = 0 +pp_data->cap[89]->IsStringRange = 0 +pp_data->cap[89]->IsDesignatorRange = 0 +pp_data->cap[89]->Reserved1 = 0x000000 +pp_data->cap[89]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[89]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[89]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[89]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[89]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[89]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[89]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[89]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[89]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[89]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[89]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[89]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[89]->NotRange.Usage = 0x0081 +pp_data->cap[89]->NotRange.Reserved1 = 0x0081 +pp_data->cap[89]->NotRange.StringIndex = 0 +pp_data->cap[89]->NotRange.Reserved2 = 0 +pp_data->cap[89]->NotRange.DesignatorIndex = 0 +pp_data->cap[89]->NotRange.Reserved3 = 0 +pp_data->cap[89]->NotRange.DataIndex = 2 +pp_data->cap[89]->NotRange.Reserved4 = 2 +pp_data->cap[89]->NotButton.HasNull = 0 +pp_data->cap[89]->NotButton.Reserved4 = 0x000000 +pp_data->cap[89]->NotButton.LogicalMin = 0 +pp_data->cap[89]->NotButton.LogicalMax = 127 +pp_data->cap[89]->NotButton.PhysicalMin = 0 +pp_data->cap[89]->NotButton.PhysicalMax = 0 +pp_data->cap[89]->Units = 0 +pp_data->cap[89]->UnitsExp = 0 + +pp_data->cap[90]->UsagePage = 0xFF01 +pp_data->cap[90]->ReportID = 0x80 +pp_data->cap[90]->BitPosition = 0 +pp_data->cap[90]->BitSize = 8 +pp_data->cap[90]->ReportCount = 1 +pp_data->cap[90]->BytePosition = 0x005B +pp_data->cap[90]->BitCount = 8 +pp_data->cap[90]->BitField = 0x02 +pp_data->cap[90]->NextBytePosition = 0x005C +pp_data->cap[90]->LinkCollection = 0x0003 +pp_data->cap[90]->LinkUsagePage = 0xFF01 +pp_data->cap[90]->LinkUsage = 0x0080 +pp_data->cap[90]->IsMultipleItemsForArray = 0 +pp_data->cap[90]->IsButtonCap = 0 +pp_data->cap[90]->IsPadding = 0 +pp_data->cap[90]->IsAbsolute = 1 +pp_data->cap[90]->IsRange = 0 +pp_data->cap[90]->IsAlias = 0 +pp_data->cap[90]->IsStringRange = 0 +pp_data->cap[90]->IsDesignatorRange = 0 +pp_data->cap[90]->Reserved1 = 0x000000 +pp_data->cap[90]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[90]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[90]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[90]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[90]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[90]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[90]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[90]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[90]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[90]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[90]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[90]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[90]->NotRange.Usage = 0x0081 +pp_data->cap[90]->NotRange.Reserved1 = 0x0081 +pp_data->cap[90]->NotRange.StringIndex = 0 +pp_data->cap[90]->NotRange.Reserved2 = 0 +pp_data->cap[90]->NotRange.DesignatorIndex = 0 +pp_data->cap[90]->NotRange.Reserved3 = 0 +pp_data->cap[90]->NotRange.DataIndex = 3 +pp_data->cap[90]->NotRange.Reserved4 = 3 +pp_data->cap[90]->NotButton.HasNull = 0 +pp_data->cap[90]->NotButton.Reserved4 = 0x000000 +pp_data->cap[90]->NotButton.LogicalMin = 0 +pp_data->cap[90]->NotButton.LogicalMax = 127 +pp_data->cap[90]->NotButton.PhysicalMin = 0 +pp_data->cap[90]->NotButton.PhysicalMax = 0 +pp_data->cap[90]->Units = 0 +pp_data->cap[90]->UnitsExp = 0 + +pp_data->cap[91]->UsagePage = 0xFF01 +pp_data->cap[91]->ReportID = 0x80 +pp_data->cap[91]->BitPosition = 0 +pp_data->cap[91]->BitSize = 8 +pp_data->cap[91]->ReportCount = 1 +pp_data->cap[91]->BytePosition = 0x005A +pp_data->cap[91]->BitCount = 8 +pp_data->cap[91]->BitField = 0x02 +pp_data->cap[91]->NextBytePosition = 0x005B +pp_data->cap[91]->LinkCollection = 0x0003 +pp_data->cap[91]->LinkUsagePage = 0xFF01 +pp_data->cap[91]->LinkUsage = 0x0080 +pp_data->cap[91]->IsMultipleItemsForArray = 0 +pp_data->cap[91]->IsButtonCap = 0 +pp_data->cap[91]->IsPadding = 0 +pp_data->cap[91]->IsAbsolute = 1 +pp_data->cap[91]->IsRange = 0 +pp_data->cap[91]->IsAlias = 0 +pp_data->cap[91]->IsStringRange = 0 +pp_data->cap[91]->IsDesignatorRange = 0 +pp_data->cap[91]->Reserved1 = 0x000000 +pp_data->cap[91]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[91]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[91]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[91]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[91]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[91]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[91]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[91]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[91]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[91]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[91]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[91]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[91]->NotRange.Usage = 0x0081 +pp_data->cap[91]->NotRange.Reserved1 = 0x0081 +pp_data->cap[91]->NotRange.StringIndex = 0 +pp_data->cap[91]->NotRange.Reserved2 = 0 +pp_data->cap[91]->NotRange.DesignatorIndex = 0 +pp_data->cap[91]->NotRange.Reserved3 = 0 +pp_data->cap[91]->NotRange.DataIndex = 4 +pp_data->cap[91]->NotRange.Reserved4 = 4 +pp_data->cap[91]->NotButton.HasNull = 0 +pp_data->cap[91]->NotButton.Reserved4 = 0x000000 +pp_data->cap[91]->NotButton.LogicalMin = 0 +pp_data->cap[91]->NotButton.LogicalMax = 127 +pp_data->cap[91]->NotButton.PhysicalMin = 0 +pp_data->cap[91]->NotButton.PhysicalMax = 0 +pp_data->cap[91]->Units = 0 +pp_data->cap[91]->UnitsExp = 0 + +pp_data->cap[92]->UsagePage = 0xFF01 +pp_data->cap[92]->ReportID = 0x80 +pp_data->cap[92]->BitPosition = 0 +pp_data->cap[92]->BitSize = 8 +pp_data->cap[92]->ReportCount = 1 +pp_data->cap[92]->BytePosition = 0x0059 +pp_data->cap[92]->BitCount = 8 +pp_data->cap[92]->BitField = 0x02 +pp_data->cap[92]->NextBytePosition = 0x005A +pp_data->cap[92]->LinkCollection = 0x0003 +pp_data->cap[92]->LinkUsagePage = 0xFF01 +pp_data->cap[92]->LinkUsage = 0x0080 +pp_data->cap[92]->IsMultipleItemsForArray = 0 +pp_data->cap[92]->IsButtonCap = 0 +pp_data->cap[92]->IsPadding = 0 +pp_data->cap[92]->IsAbsolute = 1 +pp_data->cap[92]->IsRange = 0 +pp_data->cap[92]->IsAlias = 0 +pp_data->cap[92]->IsStringRange = 0 +pp_data->cap[92]->IsDesignatorRange = 0 +pp_data->cap[92]->Reserved1 = 0x000000 +pp_data->cap[92]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[92]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[92]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[92]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[92]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[92]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[92]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[92]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[92]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[92]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[92]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[92]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[92]->NotRange.Usage = 0x0081 +pp_data->cap[92]->NotRange.Reserved1 = 0x0081 +pp_data->cap[92]->NotRange.StringIndex = 0 +pp_data->cap[92]->NotRange.Reserved2 = 0 +pp_data->cap[92]->NotRange.DesignatorIndex = 0 +pp_data->cap[92]->NotRange.Reserved3 = 0 +pp_data->cap[92]->NotRange.DataIndex = 5 +pp_data->cap[92]->NotRange.Reserved4 = 5 +pp_data->cap[92]->NotButton.HasNull = 0 +pp_data->cap[92]->NotButton.Reserved4 = 0x000000 +pp_data->cap[92]->NotButton.LogicalMin = 0 +pp_data->cap[92]->NotButton.LogicalMax = 127 +pp_data->cap[92]->NotButton.PhysicalMin = 0 +pp_data->cap[92]->NotButton.PhysicalMax = 0 +pp_data->cap[92]->Units = 0 +pp_data->cap[92]->UnitsExp = 0 + +pp_data->cap[93]->UsagePage = 0xFF01 +pp_data->cap[93]->ReportID = 0x80 +pp_data->cap[93]->BitPosition = 0 +pp_data->cap[93]->BitSize = 8 +pp_data->cap[93]->ReportCount = 1 +pp_data->cap[93]->BytePosition = 0x0058 +pp_data->cap[93]->BitCount = 8 +pp_data->cap[93]->BitField = 0x02 +pp_data->cap[93]->NextBytePosition = 0x0059 +pp_data->cap[93]->LinkCollection = 0x0003 +pp_data->cap[93]->LinkUsagePage = 0xFF01 +pp_data->cap[93]->LinkUsage = 0x0080 +pp_data->cap[93]->IsMultipleItemsForArray = 0 +pp_data->cap[93]->IsButtonCap = 0 +pp_data->cap[93]->IsPadding = 0 +pp_data->cap[93]->IsAbsolute = 1 +pp_data->cap[93]->IsRange = 0 +pp_data->cap[93]->IsAlias = 0 +pp_data->cap[93]->IsStringRange = 0 +pp_data->cap[93]->IsDesignatorRange = 0 +pp_data->cap[93]->Reserved1 = 0x000000 +pp_data->cap[93]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[93]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[93]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[93]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[93]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[93]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[93]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[93]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[93]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[93]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[93]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[93]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[93]->NotRange.Usage = 0x0081 +pp_data->cap[93]->NotRange.Reserved1 = 0x0081 +pp_data->cap[93]->NotRange.StringIndex = 0 +pp_data->cap[93]->NotRange.Reserved2 = 0 +pp_data->cap[93]->NotRange.DesignatorIndex = 0 +pp_data->cap[93]->NotRange.Reserved3 = 0 +pp_data->cap[93]->NotRange.DataIndex = 6 +pp_data->cap[93]->NotRange.Reserved4 = 6 +pp_data->cap[93]->NotButton.HasNull = 0 +pp_data->cap[93]->NotButton.Reserved4 = 0x000000 +pp_data->cap[93]->NotButton.LogicalMin = 0 +pp_data->cap[93]->NotButton.LogicalMax = 127 +pp_data->cap[93]->NotButton.PhysicalMin = 0 +pp_data->cap[93]->NotButton.PhysicalMax = 0 +pp_data->cap[93]->Units = 0 +pp_data->cap[93]->UnitsExp = 0 + +pp_data->cap[94]->UsagePage = 0xFF01 +pp_data->cap[94]->ReportID = 0x80 +pp_data->cap[94]->BitPosition = 0 +pp_data->cap[94]->BitSize = 8 +pp_data->cap[94]->ReportCount = 1 +pp_data->cap[94]->BytePosition = 0x0057 +pp_data->cap[94]->BitCount = 8 +pp_data->cap[94]->BitField = 0x02 +pp_data->cap[94]->NextBytePosition = 0x0058 +pp_data->cap[94]->LinkCollection = 0x0003 +pp_data->cap[94]->LinkUsagePage = 0xFF01 +pp_data->cap[94]->LinkUsage = 0x0080 +pp_data->cap[94]->IsMultipleItemsForArray = 0 +pp_data->cap[94]->IsButtonCap = 0 +pp_data->cap[94]->IsPadding = 0 +pp_data->cap[94]->IsAbsolute = 1 +pp_data->cap[94]->IsRange = 0 +pp_data->cap[94]->IsAlias = 0 +pp_data->cap[94]->IsStringRange = 0 +pp_data->cap[94]->IsDesignatorRange = 0 +pp_data->cap[94]->Reserved1 = 0x000000 +pp_data->cap[94]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[94]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[94]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[94]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[94]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[94]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[94]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[94]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[94]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[94]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[94]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[94]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[94]->NotRange.Usage = 0x0081 +pp_data->cap[94]->NotRange.Reserved1 = 0x0081 +pp_data->cap[94]->NotRange.StringIndex = 0 +pp_data->cap[94]->NotRange.Reserved2 = 0 +pp_data->cap[94]->NotRange.DesignatorIndex = 0 +pp_data->cap[94]->NotRange.Reserved3 = 0 +pp_data->cap[94]->NotRange.DataIndex = 7 +pp_data->cap[94]->NotRange.Reserved4 = 7 +pp_data->cap[94]->NotButton.HasNull = 0 +pp_data->cap[94]->NotButton.Reserved4 = 0x000000 +pp_data->cap[94]->NotButton.LogicalMin = 0 +pp_data->cap[94]->NotButton.LogicalMax = 127 +pp_data->cap[94]->NotButton.PhysicalMin = 0 +pp_data->cap[94]->NotButton.PhysicalMax = 0 +pp_data->cap[94]->Units = 0 +pp_data->cap[94]->UnitsExp = 0 + +pp_data->cap[95]->UsagePage = 0xFF01 +pp_data->cap[95]->ReportID = 0x80 +pp_data->cap[95]->BitPosition = 0 +pp_data->cap[95]->BitSize = 8 +pp_data->cap[95]->ReportCount = 1 +pp_data->cap[95]->BytePosition = 0x0056 +pp_data->cap[95]->BitCount = 8 +pp_data->cap[95]->BitField = 0x02 +pp_data->cap[95]->NextBytePosition = 0x0057 +pp_data->cap[95]->LinkCollection = 0x0003 +pp_data->cap[95]->LinkUsagePage = 0xFF01 +pp_data->cap[95]->LinkUsage = 0x0080 +pp_data->cap[95]->IsMultipleItemsForArray = 0 +pp_data->cap[95]->IsButtonCap = 0 +pp_data->cap[95]->IsPadding = 0 +pp_data->cap[95]->IsAbsolute = 1 +pp_data->cap[95]->IsRange = 0 +pp_data->cap[95]->IsAlias = 0 +pp_data->cap[95]->IsStringRange = 0 +pp_data->cap[95]->IsDesignatorRange = 0 +pp_data->cap[95]->Reserved1 = 0x000000 +pp_data->cap[95]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[95]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[95]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[95]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[95]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[95]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[95]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[95]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[95]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[95]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[95]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[95]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[95]->NotRange.Usage = 0x0081 +pp_data->cap[95]->NotRange.Reserved1 = 0x0081 +pp_data->cap[95]->NotRange.StringIndex = 0 +pp_data->cap[95]->NotRange.Reserved2 = 0 +pp_data->cap[95]->NotRange.DesignatorIndex = 0 +pp_data->cap[95]->NotRange.Reserved3 = 0 +pp_data->cap[95]->NotRange.DataIndex = 8 +pp_data->cap[95]->NotRange.Reserved4 = 8 +pp_data->cap[95]->NotButton.HasNull = 0 +pp_data->cap[95]->NotButton.Reserved4 = 0x000000 +pp_data->cap[95]->NotButton.LogicalMin = 0 +pp_data->cap[95]->NotButton.LogicalMax = 127 +pp_data->cap[95]->NotButton.PhysicalMin = 0 +pp_data->cap[95]->NotButton.PhysicalMax = 0 +pp_data->cap[95]->Units = 0 +pp_data->cap[95]->UnitsExp = 0 + +pp_data->cap[96]->UsagePage = 0xFF01 +pp_data->cap[96]->ReportID = 0x80 +pp_data->cap[96]->BitPosition = 0 +pp_data->cap[96]->BitSize = 8 +pp_data->cap[96]->ReportCount = 1 +pp_data->cap[96]->BytePosition = 0x0055 +pp_data->cap[96]->BitCount = 8 +pp_data->cap[96]->BitField = 0x02 +pp_data->cap[96]->NextBytePosition = 0x0056 +pp_data->cap[96]->LinkCollection = 0x0003 +pp_data->cap[96]->LinkUsagePage = 0xFF01 +pp_data->cap[96]->LinkUsage = 0x0080 +pp_data->cap[96]->IsMultipleItemsForArray = 0 +pp_data->cap[96]->IsButtonCap = 0 +pp_data->cap[96]->IsPadding = 0 +pp_data->cap[96]->IsAbsolute = 1 +pp_data->cap[96]->IsRange = 0 +pp_data->cap[96]->IsAlias = 0 +pp_data->cap[96]->IsStringRange = 0 +pp_data->cap[96]->IsDesignatorRange = 0 +pp_data->cap[96]->Reserved1 = 0x000000 +pp_data->cap[96]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[96]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[96]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[96]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[96]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[96]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[96]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[96]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[96]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[96]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[96]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[96]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[96]->NotRange.Usage = 0x0081 +pp_data->cap[96]->NotRange.Reserved1 = 0x0081 +pp_data->cap[96]->NotRange.StringIndex = 0 +pp_data->cap[96]->NotRange.Reserved2 = 0 +pp_data->cap[96]->NotRange.DesignatorIndex = 0 +pp_data->cap[96]->NotRange.Reserved3 = 0 +pp_data->cap[96]->NotRange.DataIndex = 9 +pp_data->cap[96]->NotRange.Reserved4 = 9 +pp_data->cap[96]->NotButton.HasNull = 0 +pp_data->cap[96]->NotButton.Reserved4 = 0x000000 +pp_data->cap[96]->NotButton.LogicalMin = 0 +pp_data->cap[96]->NotButton.LogicalMax = 127 +pp_data->cap[96]->NotButton.PhysicalMin = 0 +pp_data->cap[96]->NotButton.PhysicalMax = 0 +pp_data->cap[96]->Units = 0 +pp_data->cap[96]->UnitsExp = 0 + +pp_data->cap[97]->UsagePage = 0xFF01 +pp_data->cap[97]->ReportID = 0x80 +pp_data->cap[97]->BitPosition = 0 +pp_data->cap[97]->BitSize = 8 +pp_data->cap[97]->ReportCount = 1 +pp_data->cap[97]->BytePosition = 0x0054 +pp_data->cap[97]->BitCount = 8 +pp_data->cap[97]->BitField = 0x02 +pp_data->cap[97]->NextBytePosition = 0x0055 +pp_data->cap[97]->LinkCollection = 0x0003 +pp_data->cap[97]->LinkUsagePage = 0xFF01 +pp_data->cap[97]->LinkUsage = 0x0080 +pp_data->cap[97]->IsMultipleItemsForArray = 0 +pp_data->cap[97]->IsButtonCap = 0 +pp_data->cap[97]->IsPadding = 0 +pp_data->cap[97]->IsAbsolute = 1 +pp_data->cap[97]->IsRange = 0 +pp_data->cap[97]->IsAlias = 0 +pp_data->cap[97]->IsStringRange = 0 +pp_data->cap[97]->IsDesignatorRange = 0 +pp_data->cap[97]->Reserved1 = 0x000000 +pp_data->cap[97]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[97]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[97]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[97]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[97]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[97]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[97]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[97]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[97]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[97]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[97]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[97]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[97]->NotRange.Usage = 0x0081 +pp_data->cap[97]->NotRange.Reserved1 = 0x0081 +pp_data->cap[97]->NotRange.StringIndex = 0 +pp_data->cap[97]->NotRange.Reserved2 = 0 +pp_data->cap[97]->NotRange.DesignatorIndex = 0 +pp_data->cap[97]->NotRange.Reserved3 = 0 +pp_data->cap[97]->NotRange.DataIndex = 10 +pp_data->cap[97]->NotRange.Reserved4 = 10 +pp_data->cap[97]->NotButton.HasNull = 0 +pp_data->cap[97]->NotButton.Reserved4 = 0x000000 +pp_data->cap[97]->NotButton.LogicalMin = 0 +pp_data->cap[97]->NotButton.LogicalMax = 127 +pp_data->cap[97]->NotButton.PhysicalMin = 0 +pp_data->cap[97]->NotButton.PhysicalMax = 0 +pp_data->cap[97]->Units = 0 +pp_data->cap[97]->UnitsExp = 0 + +pp_data->cap[98]->UsagePage = 0xFF01 +pp_data->cap[98]->ReportID = 0x80 +pp_data->cap[98]->BitPosition = 0 +pp_data->cap[98]->BitSize = 8 +pp_data->cap[98]->ReportCount = 1 +pp_data->cap[98]->BytePosition = 0x0053 +pp_data->cap[98]->BitCount = 8 +pp_data->cap[98]->BitField = 0x02 +pp_data->cap[98]->NextBytePosition = 0x0054 +pp_data->cap[98]->LinkCollection = 0x0003 +pp_data->cap[98]->LinkUsagePage = 0xFF01 +pp_data->cap[98]->LinkUsage = 0x0080 +pp_data->cap[98]->IsMultipleItemsForArray = 0 +pp_data->cap[98]->IsButtonCap = 0 +pp_data->cap[98]->IsPadding = 0 +pp_data->cap[98]->IsAbsolute = 1 +pp_data->cap[98]->IsRange = 0 +pp_data->cap[98]->IsAlias = 0 +pp_data->cap[98]->IsStringRange = 0 +pp_data->cap[98]->IsDesignatorRange = 0 +pp_data->cap[98]->Reserved1 = 0x000000 +pp_data->cap[98]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[98]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[98]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[98]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[98]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[98]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[98]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[98]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[98]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[98]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[98]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[98]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[98]->NotRange.Usage = 0x0081 +pp_data->cap[98]->NotRange.Reserved1 = 0x0081 +pp_data->cap[98]->NotRange.StringIndex = 0 +pp_data->cap[98]->NotRange.Reserved2 = 0 +pp_data->cap[98]->NotRange.DesignatorIndex = 0 +pp_data->cap[98]->NotRange.Reserved3 = 0 +pp_data->cap[98]->NotRange.DataIndex = 11 +pp_data->cap[98]->NotRange.Reserved4 = 11 +pp_data->cap[98]->NotButton.HasNull = 0 +pp_data->cap[98]->NotButton.Reserved4 = 0x000000 +pp_data->cap[98]->NotButton.LogicalMin = 0 +pp_data->cap[98]->NotButton.LogicalMax = 127 +pp_data->cap[98]->NotButton.PhysicalMin = 0 +pp_data->cap[98]->NotButton.PhysicalMax = 0 +pp_data->cap[98]->Units = 0 +pp_data->cap[98]->UnitsExp = 0 + +pp_data->cap[99]->UsagePage = 0xFF01 +pp_data->cap[99]->ReportID = 0x80 +pp_data->cap[99]->BitPosition = 0 +pp_data->cap[99]->BitSize = 8 +pp_data->cap[99]->ReportCount = 1 +pp_data->cap[99]->BytePosition = 0x0052 +pp_data->cap[99]->BitCount = 8 +pp_data->cap[99]->BitField = 0x02 +pp_data->cap[99]->NextBytePosition = 0x0053 +pp_data->cap[99]->LinkCollection = 0x0003 +pp_data->cap[99]->LinkUsagePage = 0xFF01 +pp_data->cap[99]->LinkUsage = 0x0080 +pp_data->cap[99]->IsMultipleItemsForArray = 0 +pp_data->cap[99]->IsButtonCap = 0 +pp_data->cap[99]->IsPadding = 0 +pp_data->cap[99]->IsAbsolute = 1 +pp_data->cap[99]->IsRange = 0 +pp_data->cap[99]->IsAlias = 0 +pp_data->cap[99]->IsStringRange = 0 +pp_data->cap[99]->IsDesignatorRange = 0 +pp_data->cap[99]->Reserved1 = 0x000000 +pp_data->cap[99]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[99]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[99]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[99]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[99]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[99]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[99]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[99]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[99]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[99]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[99]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[99]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[99]->NotRange.Usage = 0x0081 +pp_data->cap[99]->NotRange.Reserved1 = 0x0081 +pp_data->cap[99]->NotRange.StringIndex = 0 +pp_data->cap[99]->NotRange.Reserved2 = 0 +pp_data->cap[99]->NotRange.DesignatorIndex = 0 +pp_data->cap[99]->NotRange.Reserved3 = 0 +pp_data->cap[99]->NotRange.DataIndex = 12 +pp_data->cap[99]->NotRange.Reserved4 = 12 +pp_data->cap[99]->NotButton.HasNull = 0 +pp_data->cap[99]->NotButton.Reserved4 = 0x000000 +pp_data->cap[99]->NotButton.LogicalMin = 0 +pp_data->cap[99]->NotButton.LogicalMax = 127 +pp_data->cap[99]->NotButton.PhysicalMin = 0 +pp_data->cap[99]->NotButton.PhysicalMax = 0 +pp_data->cap[99]->Units = 0 +pp_data->cap[99]->UnitsExp = 0 + +pp_data->cap[100]->UsagePage = 0xFF01 +pp_data->cap[100]->ReportID = 0x80 +pp_data->cap[100]->BitPosition = 0 +pp_data->cap[100]->BitSize = 8 +pp_data->cap[100]->ReportCount = 1 +pp_data->cap[100]->BytePosition = 0x0051 +pp_data->cap[100]->BitCount = 8 +pp_data->cap[100]->BitField = 0x02 +pp_data->cap[100]->NextBytePosition = 0x0052 +pp_data->cap[100]->LinkCollection = 0x0003 +pp_data->cap[100]->LinkUsagePage = 0xFF01 +pp_data->cap[100]->LinkUsage = 0x0080 +pp_data->cap[100]->IsMultipleItemsForArray = 0 +pp_data->cap[100]->IsButtonCap = 0 +pp_data->cap[100]->IsPadding = 0 +pp_data->cap[100]->IsAbsolute = 1 +pp_data->cap[100]->IsRange = 0 +pp_data->cap[100]->IsAlias = 0 +pp_data->cap[100]->IsStringRange = 0 +pp_data->cap[100]->IsDesignatorRange = 0 +pp_data->cap[100]->Reserved1 = 0x000000 +pp_data->cap[100]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[100]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[100]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[100]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[100]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[100]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[100]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[100]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[100]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[100]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[100]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[100]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[100]->NotRange.Usage = 0x0081 +pp_data->cap[100]->NotRange.Reserved1 = 0x0081 +pp_data->cap[100]->NotRange.StringIndex = 0 +pp_data->cap[100]->NotRange.Reserved2 = 0 +pp_data->cap[100]->NotRange.DesignatorIndex = 0 +pp_data->cap[100]->NotRange.Reserved3 = 0 +pp_data->cap[100]->NotRange.DataIndex = 13 +pp_data->cap[100]->NotRange.Reserved4 = 13 +pp_data->cap[100]->NotButton.HasNull = 0 +pp_data->cap[100]->NotButton.Reserved4 = 0x000000 +pp_data->cap[100]->NotButton.LogicalMin = 0 +pp_data->cap[100]->NotButton.LogicalMax = 127 +pp_data->cap[100]->NotButton.PhysicalMin = 0 +pp_data->cap[100]->NotButton.PhysicalMax = 0 +pp_data->cap[100]->Units = 0 +pp_data->cap[100]->UnitsExp = 0 + +pp_data->cap[101]->UsagePage = 0xFF01 +pp_data->cap[101]->ReportID = 0x80 +pp_data->cap[101]->BitPosition = 0 +pp_data->cap[101]->BitSize = 8 +pp_data->cap[101]->ReportCount = 1 +pp_data->cap[101]->BytePosition = 0x0050 +pp_data->cap[101]->BitCount = 8 +pp_data->cap[101]->BitField = 0x02 +pp_data->cap[101]->NextBytePosition = 0x0051 +pp_data->cap[101]->LinkCollection = 0x0003 +pp_data->cap[101]->LinkUsagePage = 0xFF01 +pp_data->cap[101]->LinkUsage = 0x0080 +pp_data->cap[101]->IsMultipleItemsForArray = 0 +pp_data->cap[101]->IsButtonCap = 0 +pp_data->cap[101]->IsPadding = 0 +pp_data->cap[101]->IsAbsolute = 1 +pp_data->cap[101]->IsRange = 0 +pp_data->cap[101]->IsAlias = 0 +pp_data->cap[101]->IsStringRange = 0 +pp_data->cap[101]->IsDesignatorRange = 0 +pp_data->cap[101]->Reserved1 = 0x000000 +pp_data->cap[101]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[101]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[101]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[101]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[101]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[101]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[101]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[101]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[101]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[101]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[101]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[101]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[101]->NotRange.Usage = 0x0081 +pp_data->cap[101]->NotRange.Reserved1 = 0x0081 +pp_data->cap[101]->NotRange.StringIndex = 0 +pp_data->cap[101]->NotRange.Reserved2 = 0 +pp_data->cap[101]->NotRange.DesignatorIndex = 0 +pp_data->cap[101]->NotRange.Reserved3 = 0 +pp_data->cap[101]->NotRange.DataIndex = 14 +pp_data->cap[101]->NotRange.Reserved4 = 14 +pp_data->cap[101]->NotButton.HasNull = 0 +pp_data->cap[101]->NotButton.Reserved4 = 0x000000 +pp_data->cap[101]->NotButton.LogicalMin = 0 +pp_data->cap[101]->NotButton.LogicalMax = 127 +pp_data->cap[101]->NotButton.PhysicalMin = 0 +pp_data->cap[101]->NotButton.PhysicalMax = 0 +pp_data->cap[101]->Units = 0 +pp_data->cap[101]->UnitsExp = 0 + +pp_data->cap[102]->UsagePage = 0xFF01 +pp_data->cap[102]->ReportID = 0x80 +pp_data->cap[102]->BitPosition = 0 +pp_data->cap[102]->BitSize = 8 +pp_data->cap[102]->ReportCount = 1 +pp_data->cap[102]->BytePosition = 0x004F +pp_data->cap[102]->BitCount = 8 +pp_data->cap[102]->BitField = 0x02 +pp_data->cap[102]->NextBytePosition = 0x0050 +pp_data->cap[102]->LinkCollection = 0x0003 +pp_data->cap[102]->LinkUsagePage = 0xFF01 +pp_data->cap[102]->LinkUsage = 0x0080 +pp_data->cap[102]->IsMultipleItemsForArray = 0 +pp_data->cap[102]->IsButtonCap = 0 +pp_data->cap[102]->IsPadding = 0 +pp_data->cap[102]->IsAbsolute = 1 +pp_data->cap[102]->IsRange = 0 +pp_data->cap[102]->IsAlias = 0 +pp_data->cap[102]->IsStringRange = 0 +pp_data->cap[102]->IsDesignatorRange = 0 +pp_data->cap[102]->Reserved1 = 0x000000 +pp_data->cap[102]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[102]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[102]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[102]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[102]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[102]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[102]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[102]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[102]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[102]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[102]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[102]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[102]->NotRange.Usage = 0x0081 +pp_data->cap[102]->NotRange.Reserved1 = 0x0081 +pp_data->cap[102]->NotRange.StringIndex = 0 +pp_data->cap[102]->NotRange.Reserved2 = 0 +pp_data->cap[102]->NotRange.DesignatorIndex = 0 +pp_data->cap[102]->NotRange.Reserved3 = 0 +pp_data->cap[102]->NotRange.DataIndex = 15 +pp_data->cap[102]->NotRange.Reserved4 = 15 +pp_data->cap[102]->NotButton.HasNull = 0 +pp_data->cap[102]->NotButton.Reserved4 = 0x000000 +pp_data->cap[102]->NotButton.LogicalMin = 0 +pp_data->cap[102]->NotButton.LogicalMax = 127 +pp_data->cap[102]->NotButton.PhysicalMin = 0 +pp_data->cap[102]->NotButton.PhysicalMax = 0 +pp_data->cap[102]->Units = 0 +pp_data->cap[102]->UnitsExp = 0 + +pp_data->cap[103]->UsagePage = 0xFF01 +pp_data->cap[103]->ReportID = 0x80 +pp_data->cap[103]->BitPosition = 0 +pp_data->cap[103]->BitSize = 8 +pp_data->cap[103]->ReportCount = 1 +pp_data->cap[103]->BytePosition = 0x004E +pp_data->cap[103]->BitCount = 8 +pp_data->cap[103]->BitField = 0x02 +pp_data->cap[103]->NextBytePosition = 0x004F +pp_data->cap[103]->LinkCollection = 0x0003 +pp_data->cap[103]->LinkUsagePage = 0xFF01 +pp_data->cap[103]->LinkUsage = 0x0080 +pp_data->cap[103]->IsMultipleItemsForArray = 0 +pp_data->cap[103]->IsButtonCap = 0 +pp_data->cap[103]->IsPadding = 0 +pp_data->cap[103]->IsAbsolute = 1 +pp_data->cap[103]->IsRange = 0 +pp_data->cap[103]->IsAlias = 0 +pp_data->cap[103]->IsStringRange = 0 +pp_data->cap[103]->IsDesignatorRange = 0 +pp_data->cap[103]->Reserved1 = 0x000000 +pp_data->cap[103]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[103]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[103]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[103]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[103]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[103]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[103]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[103]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[103]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[103]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[103]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[103]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[103]->NotRange.Usage = 0x0081 +pp_data->cap[103]->NotRange.Reserved1 = 0x0081 +pp_data->cap[103]->NotRange.StringIndex = 0 +pp_data->cap[103]->NotRange.Reserved2 = 0 +pp_data->cap[103]->NotRange.DesignatorIndex = 0 +pp_data->cap[103]->NotRange.Reserved3 = 0 +pp_data->cap[103]->NotRange.DataIndex = 16 +pp_data->cap[103]->NotRange.Reserved4 = 16 +pp_data->cap[103]->NotButton.HasNull = 0 +pp_data->cap[103]->NotButton.Reserved4 = 0x000000 +pp_data->cap[103]->NotButton.LogicalMin = 0 +pp_data->cap[103]->NotButton.LogicalMax = 127 +pp_data->cap[103]->NotButton.PhysicalMin = 0 +pp_data->cap[103]->NotButton.PhysicalMax = 0 +pp_data->cap[103]->Units = 0 +pp_data->cap[103]->UnitsExp = 0 + +pp_data->cap[104]->UsagePage = 0xFF01 +pp_data->cap[104]->ReportID = 0x80 +pp_data->cap[104]->BitPosition = 0 +pp_data->cap[104]->BitSize = 8 +pp_data->cap[104]->ReportCount = 1 +pp_data->cap[104]->BytePosition = 0x004D +pp_data->cap[104]->BitCount = 8 +pp_data->cap[104]->BitField = 0x02 +pp_data->cap[104]->NextBytePosition = 0x004E +pp_data->cap[104]->LinkCollection = 0x0003 +pp_data->cap[104]->LinkUsagePage = 0xFF01 +pp_data->cap[104]->LinkUsage = 0x0080 +pp_data->cap[104]->IsMultipleItemsForArray = 0 +pp_data->cap[104]->IsButtonCap = 0 +pp_data->cap[104]->IsPadding = 0 +pp_data->cap[104]->IsAbsolute = 1 +pp_data->cap[104]->IsRange = 0 +pp_data->cap[104]->IsAlias = 0 +pp_data->cap[104]->IsStringRange = 0 +pp_data->cap[104]->IsDesignatorRange = 0 +pp_data->cap[104]->Reserved1 = 0x000000 +pp_data->cap[104]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[104]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[104]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[104]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[104]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[104]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[104]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[104]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[104]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[104]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[104]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[104]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[104]->NotRange.Usage = 0x0081 +pp_data->cap[104]->NotRange.Reserved1 = 0x0081 +pp_data->cap[104]->NotRange.StringIndex = 0 +pp_data->cap[104]->NotRange.Reserved2 = 0 +pp_data->cap[104]->NotRange.DesignatorIndex = 0 +pp_data->cap[104]->NotRange.Reserved3 = 0 +pp_data->cap[104]->NotRange.DataIndex = 17 +pp_data->cap[104]->NotRange.Reserved4 = 17 +pp_data->cap[104]->NotButton.HasNull = 0 +pp_data->cap[104]->NotButton.Reserved4 = 0x000000 +pp_data->cap[104]->NotButton.LogicalMin = 0 +pp_data->cap[104]->NotButton.LogicalMax = 127 +pp_data->cap[104]->NotButton.PhysicalMin = 0 +pp_data->cap[104]->NotButton.PhysicalMax = 0 +pp_data->cap[104]->Units = 0 +pp_data->cap[104]->UnitsExp = 0 + +pp_data->cap[105]->UsagePage = 0xFF01 +pp_data->cap[105]->ReportID = 0x80 +pp_data->cap[105]->BitPosition = 0 +pp_data->cap[105]->BitSize = 8 +pp_data->cap[105]->ReportCount = 1 +pp_data->cap[105]->BytePosition = 0x004C +pp_data->cap[105]->BitCount = 8 +pp_data->cap[105]->BitField = 0x02 +pp_data->cap[105]->NextBytePosition = 0x004D +pp_data->cap[105]->LinkCollection = 0x0003 +pp_data->cap[105]->LinkUsagePage = 0xFF01 +pp_data->cap[105]->LinkUsage = 0x0080 +pp_data->cap[105]->IsMultipleItemsForArray = 0 +pp_data->cap[105]->IsButtonCap = 0 +pp_data->cap[105]->IsPadding = 0 +pp_data->cap[105]->IsAbsolute = 1 +pp_data->cap[105]->IsRange = 0 +pp_data->cap[105]->IsAlias = 0 +pp_data->cap[105]->IsStringRange = 0 +pp_data->cap[105]->IsDesignatorRange = 0 +pp_data->cap[105]->Reserved1 = 0x000000 +pp_data->cap[105]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[105]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[105]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[105]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[105]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[105]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[105]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[105]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[105]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[105]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[105]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[105]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[105]->NotRange.Usage = 0x0081 +pp_data->cap[105]->NotRange.Reserved1 = 0x0081 +pp_data->cap[105]->NotRange.StringIndex = 0 +pp_data->cap[105]->NotRange.Reserved2 = 0 +pp_data->cap[105]->NotRange.DesignatorIndex = 0 +pp_data->cap[105]->NotRange.Reserved3 = 0 +pp_data->cap[105]->NotRange.DataIndex = 18 +pp_data->cap[105]->NotRange.Reserved4 = 18 +pp_data->cap[105]->NotButton.HasNull = 0 +pp_data->cap[105]->NotButton.Reserved4 = 0x000000 +pp_data->cap[105]->NotButton.LogicalMin = 0 +pp_data->cap[105]->NotButton.LogicalMax = 127 +pp_data->cap[105]->NotButton.PhysicalMin = 0 +pp_data->cap[105]->NotButton.PhysicalMax = 0 +pp_data->cap[105]->Units = 0 +pp_data->cap[105]->UnitsExp = 0 + +pp_data->cap[106]->UsagePage = 0xFF01 +pp_data->cap[106]->ReportID = 0x80 +pp_data->cap[106]->BitPosition = 0 +pp_data->cap[106]->BitSize = 8 +pp_data->cap[106]->ReportCount = 1 +pp_data->cap[106]->BytePosition = 0x004B +pp_data->cap[106]->BitCount = 8 +pp_data->cap[106]->BitField = 0x02 +pp_data->cap[106]->NextBytePosition = 0x004C +pp_data->cap[106]->LinkCollection = 0x0003 +pp_data->cap[106]->LinkUsagePage = 0xFF01 +pp_data->cap[106]->LinkUsage = 0x0080 +pp_data->cap[106]->IsMultipleItemsForArray = 0 +pp_data->cap[106]->IsButtonCap = 0 +pp_data->cap[106]->IsPadding = 0 +pp_data->cap[106]->IsAbsolute = 1 +pp_data->cap[106]->IsRange = 0 +pp_data->cap[106]->IsAlias = 0 +pp_data->cap[106]->IsStringRange = 0 +pp_data->cap[106]->IsDesignatorRange = 0 +pp_data->cap[106]->Reserved1 = 0x000000 +pp_data->cap[106]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[106]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[106]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[106]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[106]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[106]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[106]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[106]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[106]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[106]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[106]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[106]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[106]->NotRange.Usage = 0x0081 +pp_data->cap[106]->NotRange.Reserved1 = 0x0081 +pp_data->cap[106]->NotRange.StringIndex = 0 +pp_data->cap[106]->NotRange.Reserved2 = 0 +pp_data->cap[106]->NotRange.DesignatorIndex = 0 +pp_data->cap[106]->NotRange.Reserved3 = 0 +pp_data->cap[106]->NotRange.DataIndex = 19 +pp_data->cap[106]->NotRange.Reserved4 = 19 +pp_data->cap[106]->NotButton.HasNull = 0 +pp_data->cap[106]->NotButton.Reserved4 = 0x000000 +pp_data->cap[106]->NotButton.LogicalMin = 0 +pp_data->cap[106]->NotButton.LogicalMax = 127 +pp_data->cap[106]->NotButton.PhysicalMin = 0 +pp_data->cap[106]->NotButton.PhysicalMax = 0 +pp_data->cap[106]->Units = 0 +pp_data->cap[106]->UnitsExp = 0 + +pp_data->cap[107]->UsagePage = 0xFF01 +pp_data->cap[107]->ReportID = 0x80 +pp_data->cap[107]->BitPosition = 0 +pp_data->cap[107]->BitSize = 8 +pp_data->cap[107]->ReportCount = 1 +pp_data->cap[107]->BytePosition = 0x004A +pp_data->cap[107]->BitCount = 8 +pp_data->cap[107]->BitField = 0x02 +pp_data->cap[107]->NextBytePosition = 0x004B +pp_data->cap[107]->LinkCollection = 0x0003 +pp_data->cap[107]->LinkUsagePage = 0xFF01 +pp_data->cap[107]->LinkUsage = 0x0080 +pp_data->cap[107]->IsMultipleItemsForArray = 0 +pp_data->cap[107]->IsButtonCap = 0 +pp_data->cap[107]->IsPadding = 0 +pp_data->cap[107]->IsAbsolute = 1 +pp_data->cap[107]->IsRange = 0 +pp_data->cap[107]->IsAlias = 0 +pp_data->cap[107]->IsStringRange = 0 +pp_data->cap[107]->IsDesignatorRange = 0 +pp_data->cap[107]->Reserved1 = 0x000000 +pp_data->cap[107]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[107]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[107]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[107]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[107]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[107]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[107]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[107]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[107]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[107]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[107]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[107]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[107]->NotRange.Usage = 0x0081 +pp_data->cap[107]->NotRange.Reserved1 = 0x0081 +pp_data->cap[107]->NotRange.StringIndex = 0 +pp_data->cap[107]->NotRange.Reserved2 = 0 +pp_data->cap[107]->NotRange.DesignatorIndex = 0 +pp_data->cap[107]->NotRange.Reserved3 = 0 +pp_data->cap[107]->NotRange.DataIndex = 20 +pp_data->cap[107]->NotRange.Reserved4 = 20 +pp_data->cap[107]->NotButton.HasNull = 0 +pp_data->cap[107]->NotButton.Reserved4 = 0x000000 +pp_data->cap[107]->NotButton.LogicalMin = 0 +pp_data->cap[107]->NotButton.LogicalMax = 127 +pp_data->cap[107]->NotButton.PhysicalMin = 0 +pp_data->cap[107]->NotButton.PhysicalMax = 0 +pp_data->cap[107]->Units = 0 +pp_data->cap[107]->UnitsExp = 0 + +pp_data->cap[108]->UsagePage = 0xFF01 +pp_data->cap[108]->ReportID = 0x80 +pp_data->cap[108]->BitPosition = 0 +pp_data->cap[108]->BitSize = 8 +pp_data->cap[108]->ReportCount = 1 +pp_data->cap[108]->BytePosition = 0x0049 +pp_data->cap[108]->BitCount = 8 +pp_data->cap[108]->BitField = 0x02 +pp_data->cap[108]->NextBytePosition = 0x004A +pp_data->cap[108]->LinkCollection = 0x0003 +pp_data->cap[108]->LinkUsagePage = 0xFF01 +pp_data->cap[108]->LinkUsage = 0x0080 +pp_data->cap[108]->IsMultipleItemsForArray = 0 +pp_data->cap[108]->IsButtonCap = 0 +pp_data->cap[108]->IsPadding = 0 +pp_data->cap[108]->IsAbsolute = 1 +pp_data->cap[108]->IsRange = 0 +pp_data->cap[108]->IsAlias = 0 +pp_data->cap[108]->IsStringRange = 0 +pp_data->cap[108]->IsDesignatorRange = 0 +pp_data->cap[108]->Reserved1 = 0x000000 +pp_data->cap[108]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[108]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[108]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[108]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[108]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[108]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[108]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[108]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[108]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[108]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[108]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[108]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[108]->NotRange.Usage = 0x0081 +pp_data->cap[108]->NotRange.Reserved1 = 0x0081 +pp_data->cap[108]->NotRange.StringIndex = 0 +pp_data->cap[108]->NotRange.Reserved2 = 0 +pp_data->cap[108]->NotRange.DesignatorIndex = 0 +pp_data->cap[108]->NotRange.Reserved3 = 0 +pp_data->cap[108]->NotRange.DataIndex = 21 +pp_data->cap[108]->NotRange.Reserved4 = 21 +pp_data->cap[108]->NotButton.HasNull = 0 +pp_data->cap[108]->NotButton.Reserved4 = 0x000000 +pp_data->cap[108]->NotButton.LogicalMin = 0 +pp_data->cap[108]->NotButton.LogicalMax = 127 +pp_data->cap[108]->NotButton.PhysicalMin = 0 +pp_data->cap[108]->NotButton.PhysicalMax = 0 +pp_data->cap[108]->Units = 0 +pp_data->cap[108]->UnitsExp = 0 + +pp_data->cap[109]->UsagePage = 0xFF01 +pp_data->cap[109]->ReportID = 0x80 +pp_data->cap[109]->BitPosition = 0 +pp_data->cap[109]->BitSize = 8 +pp_data->cap[109]->ReportCount = 1 +pp_data->cap[109]->BytePosition = 0x0048 +pp_data->cap[109]->BitCount = 8 +pp_data->cap[109]->BitField = 0x02 +pp_data->cap[109]->NextBytePosition = 0x0049 +pp_data->cap[109]->LinkCollection = 0x0003 +pp_data->cap[109]->LinkUsagePage = 0xFF01 +pp_data->cap[109]->LinkUsage = 0x0080 +pp_data->cap[109]->IsMultipleItemsForArray = 0 +pp_data->cap[109]->IsButtonCap = 0 +pp_data->cap[109]->IsPadding = 0 +pp_data->cap[109]->IsAbsolute = 1 +pp_data->cap[109]->IsRange = 0 +pp_data->cap[109]->IsAlias = 0 +pp_data->cap[109]->IsStringRange = 0 +pp_data->cap[109]->IsDesignatorRange = 0 +pp_data->cap[109]->Reserved1 = 0x000000 +pp_data->cap[109]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[109]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[109]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[109]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[109]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[109]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[109]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[109]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[109]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[109]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[109]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[109]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[109]->NotRange.Usage = 0x0081 +pp_data->cap[109]->NotRange.Reserved1 = 0x0081 +pp_data->cap[109]->NotRange.StringIndex = 0 +pp_data->cap[109]->NotRange.Reserved2 = 0 +pp_data->cap[109]->NotRange.DesignatorIndex = 0 +pp_data->cap[109]->NotRange.Reserved3 = 0 +pp_data->cap[109]->NotRange.DataIndex = 22 +pp_data->cap[109]->NotRange.Reserved4 = 22 +pp_data->cap[109]->NotButton.HasNull = 0 +pp_data->cap[109]->NotButton.Reserved4 = 0x000000 +pp_data->cap[109]->NotButton.LogicalMin = 0 +pp_data->cap[109]->NotButton.LogicalMax = 127 +pp_data->cap[109]->NotButton.PhysicalMin = 0 +pp_data->cap[109]->NotButton.PhysicalMax = 0 +pp_data->cap[109]->Units = 0 +pp_data->cap[109]->UnitsExp = 0 + +pp_data->cap[110]->UsagePage = 0xFF01 +pp_data->cap[110]->ReportID = 0x80 +pp_data->cap[110]->BitPosition = 0 +pp_data->cap[110]->BitSize = 8 +pp_data->cap[110]->ReportCount = 1 +pp_data->cap[110]->BytePosition = 0x0047 +pp_data->cap[110]->BitCount = 8 +pp_data->cap[110]->BitField = 0x02 +pp_data->cap[110]->NextBytePosition = 0x0048 +pp_data->cap[110]->LinkCollection = 0x0003 +pp_data->cap[110]->LinkUsagePage = 0xFF01 +pp_data->cap[110]->LinkUsage = 0x0080 +pp_data->cap[110]->IsMultipleItemsForArray = 0 +pp_data->cap[110]->IsButtonCap = 0 +pp_data->cap[110]->IsPadding = 0 +pp_data->cap[110]->IsAbsolute = 1 +pp_data->cap[110]->IsRange = 0 +pp_data->cap[110]->IsAlias = 0 +pp_data->cap[110]->IsStringRange = 0 +pp_data->cap[110]->IsDesignatorRange = 0 +pp_data->cap[110]->Reserved1 = 0x000000 +pp_data->cap[110]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[110]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[110]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[110]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[110]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[110]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[110]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[110]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[110]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[110]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[110]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[110]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[110]->NotRange.Usage = 0x0081 +pp_data->cap[110]->NotRange.Reserved1 = 0x0081 +pp_data->cap[110]->NotRange.StringIndex = 0 +pp_data->cap[110]->NotRange.Reserved2 = 0 +pp_data->cap[110]->NotRange.DesignatorIndex = 0 +pp_data->cap[110]->NotRange.Reserved3 = 0 +pp_data->cap[110]->NotRange.DataIndex = 23 +pp_data->cap[110]->NotRange.Reserved4 = 23 +pp_data->cap[110]->NotButton.HasNull = 0 +pp_data->cap[110]->NotButton.Reserved4 = 0x000000 +pp_data->cap[110]->NotButton.LogicalMin = 0 +pp_data->cap[110]->NotButton.LogicalMax = 127 +pp_data->cap[110]->NotButton.PhysicalMin = 0 +pp_data->cap[110]->NotButton.PhysicalMax = 0 +pp_data->cap[110]->Units = 0 +pp_data->cap[110]->UnitsExp = 0 + +pp_data->cap[111]->UsagePage = 0xFF01 +pp_data->cap[111]->ReportID = 0x80 +pp_data->cap[111]->BitPosition = 0 +pp_data->cap[111]->BitSize = 8 +pp_data->cap[111]->ReportCount = 1 +pp_data->cap[111]->BytePosition = 0x0046 +pp_data->cap[111]->BitCount = 8 +pp_data->cap[111]->BitField = 0x02 +pp_data->cap[111]->NextBytePosition = 0x0047 +pp_data->cap[111]->LinkCollection = 0x0003 +pp_data->cap[111]->LinkUsagePage = 0xFF01 +pp_data->cap[111]->LinkUsage = 0x0080 +pp_data->cap[111]->IsMultipleItemsForArray = 0 +pp_data->cap[111]->IsButtonCap = 0 +pp_data->cap[111]->IsPadding = 0 +pp_data->cap[111]->IsAbsolute = 1 +pp_data->cap[111]->IsRange = 0 +pp_data->cap[111]->IsAlias = 0 +pp_data->cap[111]->IsStringRange = 0 +pp_data->cap[111]->IsDesignatorRange = 0 +pp_data->cap[111]->Reserved1 = 0x000000 +pp_data->cap[111]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[111]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[111]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[111]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[111]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[111]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[111]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[111]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[111]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[111]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[111]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[111]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[111]->NotRange.Usage = 0x0081 +pp_data->cap[111]->NotRange.Reserved1 = 0x0081 +pp_data->cap[111]->NotRange.StringIndex = 0 +pp_data->cap[111]->NotRange.Reserved2 = 0 +pp_data->cap[111]->NotRange.DesignatorIndex = 0 +pp_data->cap[111]->NotRange.Reserved3 = 0 +pp_data->cap[111]->NotRange.DataIndex = 24 +pp_data->cap[111]->NotRange.Reserved4 = 24 +pp_data->cap[111]->NotButton.HasNull = 0 +pp_data->cap[111]->NotButton.Reserved4 = 0x000000 +pp_data->cap[111]->NotButton.LogicalMin = 0 +pp_data->cap[111]->NotButton.LogicalMax = 127 +pp_data->cap[111]->NotButton.PhysicalMin = 0 +pp_data->cap[111]->NotButton.PhysicalMax = 0 +pp_data->cap[111]->Units = 0 +pp_data->cap[111]->UnitsExp = 0 + +pp_data->cap[112]->UsagePage = 0xFF01 +pp_data->cap[112]->ReportID = 0x80 +pp_data->cap[112]->BitPosition = 0 +pp_data->cap[112]->BitSize = 8 +pp_data->cap[112]->ReportCount = 1 +pp_data->cap[112]->BytePosition = 0x0045 +pp_data->cap[112]->BitCount = 8 +pp_data->cap[112]->BitField = 0x02 +pp_data->cap[112]->NextBytePosition = 0x0046 +pp_data->cap[112]->LinkCollection = 0x0003 +pp_data->cap[112]->LinkUsagePage = 0xFF01 +pp_data->cap[112]->LinkUsage = 0x0080 +pp_data->cap[112]->IsMultipleItemsForArray = 0 +pp_data->cap[112]->IsButtonCap = 0 +pp_data->cap[112]->IsPadding = 0 +pp_data->cap[112]->IsAbsolute = 1 +pp_data->cap[112]->IsRange = 0 +pp_data->cap[112]->IsAlias = 0 +pp_data->cap[112]->IsStringRange = 0 +pp_data->cap[112]->IsDesignatorRange = 0 +pp_data->cap[112]->Reserved1 = 0x000000 +pp_data->cap[112]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[112]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[112]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[112]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[112]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[112]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[112]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[112]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[112]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[112]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[112]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[112]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[112]->NotRange.Usage = 0x0081 +pp_data->cap[112]->NotRange.Reserved1 = 0x0081 +pp_data->cap[112]->NotRange.StringIndex = 0 +pp_data->cap[112]->NotRange.Reserved2 = 0 +pp_data->cap[112]->NotRange.DesignatorIndex = 0 +pp_data->cap[112]->NotRange.Reserved3 = 0 +pp_data->cap[112]->NotRange.DataIndex = 25 +pp_data->cap[112]->NotRange.Reserved4 = 25 +pp_data->cap[112]->NotButton.HasNull = 0 +pp_data->cap[112]->NotButton.Reserved4 = 0x000000 +pp_data->cap[112]->NotButton.LogicalMin = 0 +pp_data->cap[112]->NotButton.LogicalMax = 127 +pp_data->cap[112]->NotButton.PhysicalMin = 0 +pp_data->cap[112]->NotButton.PhysicalMax = 0 +pp_data->cap[112]->Units = 0 +pp_data->cap[112]->UnitsExp = 0 + +pp_data->cap[113]->UsagePage = 0xFF01 +pp_data->cap[113]->ReportID = 0x80 +pp_data->cap[113]->BitPosition = 0 +pp_data->cap[113]->BitSize = 8 +pp_data->cap[113]->ReportCount = 1 +pp_data->cap[113]->BytePosition = 0x0044 +pp_data->cap[113]->BitCount = 8 +pp_data->cap[113]->BitField = 0x02 +pp_data->cap[113]->NextBytePosition = 0x0045 +pp_data->cap[113]->LinkCollection = 0x0003 +pp_data->cap[113]->LinkUsagePage = 0xFF01 +pp_data->cap[113]->LinkUsage = 0x0080 +pp_data->cap[113]->IsMultipleItemsForArray = 0 +pp_data->cap[113]->IsButtonCap = 0 +pp_data->cap[113]->IsPadding = 0 +pp_data->cap[113]->IsAbsolute = 1 +pp_data->cap[113]->IsRange = 0 +pp_data->cap[113]->IsAlias = 0 +pp_data->cap[113]->IsStringRange = 0 +pp_data->cap[113]->IsDesignatorRange = 0 +pp_data->cap[113]->Reserved1 = 0x000000 +pp_data->cap[113]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[113]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[113]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[113]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[113]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[113]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[113]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[113]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[113]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[113]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[113]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[113]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[113]->NotRange.Usage = 0x0081 +pp_data->cap[113]->NotRange.Reserved1 = 0x0081 +pp_data->cap[113]->NotRange.StringIndex = 0 +pp_data->cap[113]->NotRange.Reserved2 = 0 +pp_data->cap[113]->NotRange.DesignatorIndex = 0 +pp_data->cap[113]->NotRange.Reserved3 = 0 +pp_data->cap[113]->NotRange.DataIndex = 26 +pp_data->cap[113]->NotRange.Reserved4 = 26 +pp_data->cap[113]->NotButton.HasNull = 0 +pp_data->cap[113]->NotButton.Reserved4 = 0x000000 +pp_data->cap[113]->NotButton.LogicalMin = 0 +pp_data->cap[113]->NotButton.LogicalMax = 127 +pp_data->cap[113]->NotButton.PhysicalMin = 0 +pp_data->cap[113]->NotButton.PhysicalMax = 0 +pp_data->cap[113]->Units = 0 +pp_data->cap[113]->UnitsExp = 0 + +pp_data->cap[114]->UsagePage = 0xFF01 +pp_data->cap[114]->ReportID = 0x80 +pp_data->cap[114]->BitPosition = 0 +pp_data->cap[114]->BitSize = 8 +pp_data->cap[114]->ReportCount = 1 +pp_data->cap[114]->BytePosition = 0x0043 +pp_data->cap[114]->BitCount = 8 +pp_data->cap[114]->BitField = 0x02 +pp_data->cap[114]->NextBytePosition = 0x0044 +pp_data->cap[114]->LinkCollection = 0x0003 +pp_data->cap[114]->LinkUsagePage = 0xFF01 +pp_data->cap[114]->LinkUsage = 0x0080 +pp_data->cap[114]->IsMultipleItemsForArray = 0 +pp_data->cap[114]->IsButtonCap = 0 +pp_data->cap[114]->IsPadding = 0 +pp_data->cap[114]->IsAbsolute = 1 +pp_data->cap[114]->IsRange = 0 +pp_data->cap[114]->IsAlias = 0 +pp_data->cap[114]->IsStringRange = 0 +pp_data->cap[114]->IsDesignatorRange = 0 +pp_data->cap[114]->Reserved1 = 0x000000 +pp_data->cap[114]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[114]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[114]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[114]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[114]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[114]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[114]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[114]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[114]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[114]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[114]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[114]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[114]->NotRange.Usage = 0x0081 +pp_data->cap[114]->NotRange.Reserved1 = 0x0081 +pp_data->cap[114]->NotRange.StringIndex = 0 +pp_data->cap[114]->NotRange.Reserved2 = 0 +pp_data->cap[114]->NotRange.DesignatorIndex = 0 +pp_data->cap[114]->NotRange.Reserved3 = 0 +pp_data->cap[114]->NotRange.DataIndex = 27 +pp_data->cap[114]->NotRange.Reserved4 = 27 +pp_data->cap[114]->NotButton.HasNull = 0 +pp_data->cap[114]->NotButton.Reserved4 = 0x000000 +pp_data->cap[114]->NotButton.LogicalMin = 0 +pp_data->cap[114]->NotButton.LogicalMax = 127 +pp_data->cap[114]->NotButton.PhysicalMin = 0 +pp_data->cap[114]->NotButton.PhysicalMax = 0 +pp_data->cap[114]->Units = 0 +pp_data->cap[114]->UnitsExp = 0 + +pp_data->cap[115]->UsagePage = 0xFF01 +pp_data->cap[115]->ReportID = 0x80 +pp_data->cap[115]->BitPosition = 0 +pp_data->cap[115]->BitSize = 8 +pp_data->cap[115]->ReportCount = 1 +pp_data->cap[115]->BytePosition = 0x0042 +pp_data->cap[115]->BitCount = 8 +pp_data->cap[115]->BitField = 0x02 +pp_data->cap[115]->NextBytePosition = 0x0043 +pp_data->cap[115]->LinkCollection = 0x0003 +pp_data->cap[115]->LinkUsagePage = 0xFF01 +pp_data->cap[115]->LinkUsage = 0x0080 +pp_data->cap[115]->IsMultipleItemsForArray = 0 +pp_data->cap[115]->IsButtonCap = 0 +pp_data->cap[115]->IsPadding = 0 +pp_data->cap[115]->IsAbsolute = 1 +pp_data->cap[115]->IsRange = 0 +pp_data->cap[115]->IsAlias = 0 +pp_data->cap[115]->IsStringRange = 0 +pp_data->cap[115]->IsDesignatorRange = 0 +pp_data->cap[115]->Reserved1 = 0x000000 +pp_data->cap[115]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[115]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[115]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[115]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[115]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[115]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[115]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[115]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[115]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[115]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[115]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[115]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[115]->NotRange.Usage = 0x0081 +pp_data->cap[115]->NotRange.Reserved1 = 0x0081 +pp_data->cap[115]->NotRange.StringIndex = 0 +pp_data->cap[115]->NotRange.Reserved2 = 0 +pp_data->cap[115]->NotRange.DesignatorIndex = 0 +pp_data->cap[115]->NotRange.Reserved3 = 0 +pp_data->cap[115]->NotRange.DataIndex = 28 +pp_data->cap[115]->NotRange.Reserved4 = 28 +pp_data->cap[115]->NotButton.HasNull = 0 +pp_data->cap[115]->NotButton.Reserved4 = 0x000000 +pp_data->cap[115]->NotButton.LogicalMin = 0 +pp_data->cap[115]->NotButton.LogicalMax = 127 +pp_data->cap[115]->NotButton.PhysicalMin = 0 +pp_data->cap[115]->NotButton.PhysicalMax = 0 +pp_data->cap[115]->Units = 0 +pp_data->cap[115]->UnitsExp = 0 + +pp_data->cap[116]->UsagePage = 0xFF01 +pp_data->cap[116]->ReportID = 0x80 +pp_data->cap[116]->BitPosition = 0 +pp_data->cap[116]->BitSize = 8 +pp_data->cap[116]->ReportCount = 1 +pp_data->cap[116]->BytePosition = 0x0041 +pp_data->cap[116]->BitCount = 8 +pp_data->cap[116]->BitField = 0x02 +pp_data->cap[116]->NextBytePosition = 0x0042 +pp_data->cap[116]->LinkCollection = 0x0003 +pp_data->cap[116]->LinkUsagePage = 0xFF01 +pp_data->cap[116]->LinkUsage = 0x0080 +pp_data->cap[116]->IsMultipleItemsForArray = 0 +pp_data->cap[116]->IsButtonCap = 0 +pp_data->cap[116]->IsPadding = 0 +pp_data->cap[116]->IsAbsolute = 1 +pp_data->cap[116]->IsRange = 0 +pp_data->cap[116]->IsAlias = 0 +pp_data->cap[116]->IsStringRange = 0 +pp_data->cap[116]->IsDesignatorRange = 0 +pp_data->cap[116]->Reserved1 = 0x000000 +pp_data->cap[116]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[116]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[116]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[116]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[116]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[116]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[116]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[116]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[116]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[116]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[116]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[116]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[116]->NotRange.Usage = 0x0081 +pp_data->cap[116]->NotRange.Reserved1 = 0x0081 +pp_data->cap[116]->NotRange.StringIndex = 0 +pp_data->cap[116]->NotRange.Reserved2 = 0 +pp_data->cap[116]->NotRange.DesignatorIndex = 0 +pp_data->cap[116]->NotRange.Reserved3 = 0 +pp_data->cap[116]->NotRange.DataIndex = 29 +pp_data->cap[116]->NotRange.Reserved4 = 29 +pp_data->cap[116]->NotButton.HasNull = 0 +pp_data->cap[116]->NotButton.Reserved4 = 0x000000 +pp_data->cap[116]->NotButton.LogicalMin = 0 +pp_data->cap[116]->NotButton.LogicalMax = 127 +pp_data->cap[116]->NotButton.PhysicalMin = 0 +pp_data->cap[116]->NotButton.PhysicalMax = 0 +pp_data->cap[116]->Units = 0 +pp_data->cap[116]->UnitsExp = 0 + +pp_data->cap[117]->UsagePage = 0xFF01 +pp_data->cap[117]->ReportID = 0x80 +pp_data->cap[117]->BitPosition = 0 +pp_data->cap[117]->BitSize = 8 +pp_data->cap[117]->ReportCount = 1 +pp_data->cap[117]->BytePosition = 0x0040 +pp_data->cap[117]->BitCount = 8 +pp_data->cap[117]->BitField = 0x02 +pp_data->cap[117]->NextBytePosition = 0x0041 +pp_data->cap[117]->LinkCollection = 0x0003 +pp_data->cap[117]->LinkUsagePage = 0xFF01 +pp_data->cap[117]->LinkUsage = 0x0080 +pp_data->cap[117]->IsMultipleItemsForArray = 0 +pp_data->cap[117]->IsButtonCap = 0 +pp_data->cap[117]->IsPadding = 0 +pp_data->cap[117]->IsAbsolute = 1 +pp_data->cap[117]->IsRange = 0 +pp_data->cap[117]->IsAlias = 0 +pp_data->cap[117]->IsStringRange = 0 +pp_data->cap[117]->IsDesignatorRange = 0 +pp_data->cap[117]->Reserved1 = 0x000000 +pp_data->cap[117]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[117]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[117]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[117]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[117]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[117]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[117]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[117]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[117]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[117]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[117]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[117]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[117]->NotRange.Usage = 0x0081 +pp_data->cap[117]->NotRange.Reserved1 = 0x0081 +pp_data->cap[117]->NotRange.StringIndex = 0 +pp_data->cap[117]->NotRange.Reserved2 = 0 +pp_data->cap[117]->NotRange.DesignatorIndex = 0 +pp_data->cap[117]->NotRange.Reserved3 = 0 +pp_data->cap[117]->NotRange.DataIndex = 30 +pp_data->cap[117]->NotRange.Reserved4 = 30 +pp_data->cap[117]->NotButton.HasNull = 0 +pp_data->cap[117]->NotButton.Reserved4 = 0x000000 +pp_data->cap[117]->NotButton.LogicalMin = 0 +pp_data->cap[117]->NotButton.LogicalMax = 127 +pp_data->cap[117]->NotButton.PhysicalMin = 0 +pp_data->cap[117]->NotButton.PhysicalMax = 0 +pp_data->cap[117]->Units = 0 +pp_data->cap[117]->UnitsExp = 0 + +pp_data->cap[118]->UsagePage = 0xFF01 +pp_data->cap[118]->ReportID = 0x80 +pp_data->cap[118]->BitPosition = 0 +pp_data->cap[118]->BitSize = 8 +pp_data->cap[118]->ReportCount = 1 +pp_data->cap[118]->BytePosition = 0x003F +pp_data->cap[118]->BitCount = 8 +pp_data->cap[118]->BitField = 0x02 +pp_data->cap[118]->NextBytePosition = 0x0040 +pp_data->cap[118]->LinkCollection = 0x0003 +pp_data->cap[118]->LinkUsagePage = 0xFF01 +pp_data->cap[118]->LinkUsage = 0x0080 +pp_data->cap[118]->IsMultipleItemsForArray = 0 +pp_data->cap[118]->IsButtonCap = 0 +pp_data->cap[118]->IsPadding = 0 +pp_data->cap[118]->IsAbsolute = 1 +pp_data->cap[118]->IsRange = 0 +pp_data->cap[118]->IsAlias = 0 +pp_data->cap[118]->IsStringRange = 0 +pp_data->cap[118]->IsDesignatorRange = 0 +pp_data->cap[118]->Reserved1 = 0x000000 +pp_data->cap[118]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[118]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[118]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[118]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[118]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[118]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[118]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[118]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[118]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[118]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[118]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[118]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[118]->NotRange.Usage = 0x0081 +pp_data->cap[118]->NotRange.Reserved1 = 0x0081 +pp_data->cap[118]->NotRange.StringIndex = 0 +pp_data->cap[118]->NotRange.Reserved2 = 0 +pp_data->cap[118]->NotRange.DesignatorIndex = 0 +pp_data->cap[118]->NotRange.Reserved3 = 0 +pp_data->cap[118]->NotRange.DataIndex = 31 +pp_data->cap[118]->NotRange.Reserved4 = 31 +pp_data->cap[118]->NotButton.HasNull = 0 +pp_data->cap[118]->NotButton.Reserved4 = 0x000000 +pp_data->cap[118]->NotButton.LogicalMin = 0 +pp_data->cap[118]->NotButton.LogicalMax = 127 +pp_data->cap[118]->NotButton.PhysicalMin = 0 +pp_data->cap[118]->NotButton.PhysicalMax = 0 +pp_data->cap[118]->Units = 0 +pp_data->cap[118]->UnitsExp = 0 + +pp_data->cap[119]->UsagePage = 0xFF01 +pp_data->cap[119]->ReportID = 0x80 +pp_data->cap[119]->BitPosition = 0 +pp_data->cap[119]->BitSize = 8 +pp_data->cap[119]->ReportCount = 1 +pp_data->cap[119]->BytePosition = 0x003E +pp_data->cap[119]->BitCount = 8 +pp_data->cap[119]->BitField = 0x02 +pp_data->cap[119]->NextBytePosition = 0x003F +pp_data->cap[119]->LinkCollection = 0x0003 +pp_data->cap[119]->LinkUsagePage = 0xFF01 +pp_data->cap[119]->LinkUsage = 0x0080 +pp_data->cap[119]->IsMultipleItemsForArray = 0 +pp_data->cap[119]->IsButtonCap = 0 +pp_data->cap[119]->IsPadding = 0 +pp_data->cap[119]->IsAbsolute = 1 +pp_data->cap[119]->IsRange = 0 +pp_data->cap[119]->IsAlias = 0 +pp_data->cap[119]->IsStringRange = 0 +pp_data->cap[119]->IsDesignatorRange = 0 +pp_data->cap[119]->Reserved1 = 0x000000 +pp_data->cap[119]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[119]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[119]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[119]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[119]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[119]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[119]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[119]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[119]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[119]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[119]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[119]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[119]->NotRange.Usage = 0x0081 +pp_data->cap[119]->NotRange.Reserved1 = 0x0081 +pp_data->cap[119]->NotRange.StringIndex = 0 +pp_data->cap[119]->NotRange.Reserved2 = 0 +pp_data->cap[119]->NotRange.DesignatorIndex = 0 +pp_data->cap[119]->NotRange.Reserved3 = 0 +pp_data->cap[119]->NotRange.DataIndex = 32 +pp_data->cap[119]->NotRange.Reserved4 = 32 +pp_data->cap[119]->NotButton.HasNull = 0 +pp_data->cap[119]->NotButton.Reserved4 = 0x000000 +pp_data->cap[119]->NotButton.LogicalMin = 0 +pp_data->cap[119]->NotButton.LogicalMax = 127 +pp_data->cap[119]->NotButton.PhysicalMin = 0 +pp_data->cap[119]->NotButton.PhysicalMax = 0 +pp_data->cap[119]->Units = 0 +pp_data->cap[119]->UnitsExp = 0 + +pp_data->cap[120]->UsagePage = 0xFF01 +pp_data->cap[120]->ReportID = 0x80 +pp_data->cap[120]->BitPosition = 0 +pp_data->cap[120]->BitSize = 8 +pp_data->cap[120]->ReportCount = 1 +pp_data->cap[120]->BytePosition = 0x003D +pp_data->cap[120]->BitCount = 8 +pp_data->cap[120]->BitField = 0x02 +pp_data->cap[120]->NextBytePosition = 0x003E +pp_data->cap[120]->LinkCollection = 0x0003 +pp_data->cap[120]->LinkUsagePage = 0xFF01 +pp_data->cap[120]->LinkUsage = 0x0080 +pp_data->cap[120]->IsMultipleItemsForArray = 0 +pp_data->cap[120]->IsButtonCap = 0 +pp_data->cap[120]->IsPadding = 0 +pp_data->cap[120]->IsAbsolute = 1 +pp_data->cap[120]->IsRange = 0 +pp_data->cap[120]->IsAlias = 0 +pp_data->cap[120]->IsStringRange = 0 +pp_data->cap[120]->IsDesignatorRange = 0 +pp_data->cap[120]->Reserved1 = 0x000000 +pp_data->cap[120]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[120]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[120]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[120]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[120]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[120]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[120]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[120]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[120]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[120]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[120]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[120]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[120]->NotRange.Usage = 0x0081 +pp_data->cap[120]->NotRange.Reserved1 = 0x0081 +pp_data->cap[120]->NotRange.StringIndex = 0 +pp_data->cap[120]->NotRange.Reserved2 = 0 +pp_data->cap[120]->NotRange.DesignatorIndex = 0 +pp_data->cap[120]->NotRange.Reserved3 = 0 +pp_data->cap[120]->NotRange.DataIndex = 33 +pp_data->cap[120]->NotRange.Reserved4 = 33 +pp_data->cap[120]->NotButton.HasNull = 0 +pp_data->cap[120]->NotButton.Reserved4 = 0x000000 +pp_data->cap[120]->NotButton.LogicalMin = 0 +pp_data->cap[120]->NotButton.LogicalMax = 127 +pp_data->cap[120]->NotButton.PhysicalMin = 0 +pp_data->cap[120]->NotButton.PhysicalMax = 0 +pp_data->cap[120]->Units = 0 +pp_data->cap[120]->UnitsExp = 0 + +pp_data->cap[121]->UsagePage = 0xFF01 +pp_data->cap[121]->ReportID = 0x80 +pp_data->cap[121]->BitPosition = 0 +pp_data->cap[121]->BitSize = 8 +pp_data->cap[121]->ReportCount = 1 +pp_data->cap[121]->BytePosition = 0x003C +pp_data->cap[121]->BitCount = 8 +pp_data->cap[121]->BitField = 0x02 +pp_data->cap[121]->NextBytePosition = 0x003D +pp_data->cap[121]->LinkCollection = 0x0003 +pp_data->cap[121]->LinkUsagePage = 0xFF01 +pp_data->cap[121]->LinkUsage = 0x0080 +pp_data->cap[121]->IsMultipleItemsForArray = 0 +pp_data->cap[121]->IsButtonCap = 0 +pp_data->cap[121]->IsPadding = 0 +pp_data->cap[121]->IsAbsolute = 1 +pp_data->cap[121]->IsRange = 0 +pp_data->cap[121]->IsAlias = 0 +pp_data->cap[121]->IsStringRange = 0 +pp_data->cap[121]->IsDesignatorRange = 0 +pp_data->cap[121]->Reserved1 = 0x000000 +pp_data->cap[121]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[121]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[121]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[121]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[121]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[121]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[121]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[121]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[121]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[121]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[121]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[121]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[121]->NotRange.Usage = 0x0081 +pp_data->cap[121]->NotRange.Reserved1 = 0x0081 +pp_data->cap[121]->NotRange.StringIndex = 0 +pp_data->cap[121]->NotRange.Reserved2 = 0 +pp_data->cap[121]->NotRange.DesignatorIndex = 0 +pp_data->cap[121]->NotRange.Reserved3 = 0 +pp_data->cap[121]->NotRange.DataIndex = 34 +pp_data->cap[121]->NotRange.Reserved4 = 34 +pp_data->cap[121]->NotButton.HasNull = 0 +pp_data->cap[121]->NotButton.Reserved4 = 0x000000 +pp_data->cap[121]->NotButton.LogicalMin = 0 +pp_data->cap[121]->NotButton.LogicalMax = 127 +pp_data->cap[121]->NotButton.PhysicalMin = 0 +pp_data->cap[121]->NotButton.PhysicalMax = 0 +pp_data->cap[121]->Units = 0 +pp_data->cap[121]->UnitsExp = 0 + +pp_data->cap[122]->UsagePage = 0xFF01 +pp_data->cap[122]->ReportID = 0x80 +pp_data->cap[122]->BitPosition = 0 +pp_data->cap[122]->BitSize = 8 +pp_data->cap[122]->ReportCount = 1 +pp_data->cap[122]->BytePosition = 0x003B +pp_data->cap[122]->BitCount = 8 +pp_data->cap[122]->BitField = 0x02 +pp_data->cap[122]->NextBytePosition = 0x003C +pp_data->cap[122]->LinkCollection = 0x0003 +pp_data->cap[122]->LinkUsagePage = 0xFF01 +pp_data->cap[122]->LinkUsage = 0x0080 +pp_data->cap[122]->IsMultipleItemsForArray = 0 +pp_data->cap[122]->IsButtonCap = 0 +pp_data->cap[122]->IsPadding = 0 +pp_data->cap[122]->IsAbsolute = 1 +pp_data->cap[122]->IsRange = 0 +pp_data->cap[122]->IsAlias = 0 +pp_data->cap[122]->IsStringRange = 0 +pp_data->cap[122]->IsDesignatorRange = 0 +pp_data->cap[122]->Reserved1 = 0x000000 +pp_data->cap[122]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[122]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[122]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[122]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[122]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[122]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[122]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[122]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[122]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[122]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[122]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[122]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[122]->NotRange.Usage = 0x0081 +pp_data->cap[122]->NotRange.Reserved1 = 0x0081 +pp_data->cap[122]->NotRange.StringIndex = 0 +pp_data->cap[122]->NotRange.Reserved2 = 0 +pp_data->cap[122]->NotRange.DesignatorIndex = 0 +pp_data->cap[122]->NotRange.Reserved3 = 0 +pp_data->cap[122]->NotRange.DataIndex = 35 +pp_data->cap[122]->NotRange.Reserved4 = 35 +pp_data->cap[122]->NotButton.HasNull = 0 +pp_data->cap[122]->NotButton.Reserved4 = 0x000000 +pp_data->cap[122]->NotButton.LogicalMin = 0 +pp_data->cap[122]->NotButton.LogicalMax = 127 +pp_data->cap[122]->NotButton.PhysicalMin = 0 +pp_data->cap[122]->NotButton.PhysicalMax = 0 +pp_data->cap[122]->Units = 0 +pp_data->cap[122]->UnitsExp = 0 + +pp_data->cap[123]->UsagePage = 0xFF01 +pp_data->cap[123]->ReportID = 0x80 +pp_data->cap[123]->BitPosition = 0 +pp_data->cap[123]->BitSize = 8 +pp_data->cap[123]->ReportCount = 1 +pp_data->cap[123]->BytePosition = 0x003A +pp_data->cap[123]->BitCount = 8 +pp_data->cap[123]->BitField = 0x02 +pp_data->cap[123]->NextBytePosition = 0x003B +pp_data->cap[123]->LinkCollection = 0x0003 +pp_data->cap[123]->LinkUsagePage = 0xFF01 +pp_data->cap[123]->LinkUsage = 0x0080 +pp_data->cap[123]->IsMultipleItemsForArray = 0 +pp_data->cap[123]->IsButtonCap = 0 +pp_data->cap[123]->IsPadding = 0 +pp_data->cap[123]->IsAbsolute = 1 +pp_data->cap[123]->IsRange = 0 +pp_data->cap[123]->IsAlias = 0 +pp_data->cap[123]->IsStringRange = 0 +pp_data->cap[123]->IsDesignatorRange = 0 +pp_data->cap[123]->Reserved1 = 0x000000 +pp_data->cap[123]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[123]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[123]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[123]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[123]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[123]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[123]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[123]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[123]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[123]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[123]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[123]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[123]->NotRange.Usage = 0x0081 +pp_data->cap[123]->NotRange.Reserved1 = 0x0081 +pp_data->cap[123]->NotRange.StringIndex = 0 +pp_data->cap[123]->NotRange.Reserved2 = 0 +pp_data->cap[123]->NotRange.DesignatorIndex = 0 +pp_data->cap[123]->NotRange.Reserved3 = 0 +pp_data->cap[123]->NotRange.DataIndex = 36 +pp_data->cap[123]->NotRange.Reserved4 = 36 +pp_data->cap[123]->NotButton.HasNull = 0 +pp_data->cap[123]->NotButton.Reserved4 = 0x000000 +pp_data->cap[123]->NotButton.LogicalMin = 0 +pp_data->cap[123]->NotButton.LogicalMax = 127 +pp_data->cap[123]->NotButton.PhysicalMin = 0 +pp_data->cap[123]->NotButton.PhysicalMax = 0 +pp_data->cap[123]->Units = 0 +pp_data->cap[123]->UnitsExp = 0 + +pp_data->cap[124]->UsagePage = 0xFF01 +pp_data->cap[124]->ReportID = 0x80 +pp_data->cap[124]->BitPosition = 0 +pp_data->cap[124]->BitSize = 8 +pp_data->cap[124]->ReportCount = 1 +pp_data->cap[124]->BytePosition = 0x0039 +pp_data->cap[124]->BitCount = 8 +pp_data->cap[124]->BitField = 0x02 +pp_data->cap[124]->NextBytePosition = 0x003A +pp_data->cap[124]->LinkCollection = 0x0003 +pp_data->cap[124]->LinkUsagePage = 0xFF01 +pp_data->cap[124]->LinkUsage = 0x0080 +pp_data->cap[124]->IsMultipleItemsForArray = 0 +pp_data->cap[124]->IsButtonCap = 0 +pp_data->cap[124]->IsPadding = 0 +pp_data->cap[124]->IsAbsolute = 1 +pp_data->cap[124]->IsRange = 0 +pp_data->cap[124]->IsAlias = 0 +pp_data->cap[124]->IsStringRange = 0 +pp_data->cap[124]->IsDesignatorRange = 0 +pp_data->cap[124]->Reserved1 = 0x000000 +pp_data->cap[124]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[124]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[124]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[124]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[124]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[124]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[124]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[124]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[124]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[124]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[124]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[124]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[124]->NotRange.Usage = 0x0081 +pp_data->cap[124]->NotRange.Reserved1 = 0x0081 +pp_data->cap[124]->NotRange.StringIndex = 0 +pp_data->cap[124]->NotRange.Reserved2 = 0 +pp_data->cap[124]->NotRange.DesignatorIndex = 0 +pp_data->cap[124]->NotRange.Reserved3 = 0 +pp_data->cap[124]->NotRange.DataIndex = 37 +pp_data->cap[124]->NotRange.Reserved4 = 37 +pp_data->cap[124]->NotButton.HasNull = 0 +pp_data->cap[124]->NotButton.Reserved4 = 0x000000 +pp_data->cap[124]->NotButton.LogicalMin = 0 +pp_data->cap[124]->NotButton.LogicalMax = 127 +pp_data->cap[124]->NotButton.PhysicalMin = 0 +pp_data->cap[124]->NotButton.PhysicalMax = 0 +pp_data->cap[124]->Units = 0 +pp_data->cap[124]->UnitsExp = 0 + +pp_data->cap[125]->UsagePage = 0xFF01 +pp_data->cap[125]->ReportID = 0x80 +pp_data->cap[125]->BitPosition = 0 +pp_data->cap[125]->BitSize = 8 +pp_data->cap[125]->ReportCount = 1 +pp_data->cap[125]->BytePosition = 0x0038 +pp_data->cap[125]->BitCount = 8 +pp_data->cap[125]->BitField = 0x02 +pp_data->cap[125]->NextBytePosition = 0x0039 +pp_data->cap[125]->LinkCollection = 0x0003 +pp_data->cap[125]->LinkUsagePage = 0xFF01 +pp_data->cap[125]->LinkUsage = 0x0080 +pp_data->cap[125]->IsMultipleItemsForArray = 0 +pp_data->cap[125]->IsButtonCap = 0 +pp_data->cap[125]->IsPadding = 0 +pp_data->cap[125]->IsAbsolute = 1 +pp_data->cap[125]->IsRange = 0 +pp_data->cap[125]->IsAlias = 0 +pp_data->cap[125]->IsStringRange = 0 +pp_data->cap[125]->IsDesignatorRange = 0 +pp_data->cap[125]->Reserved1 = 0x000000 +pp_data->cap[125]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[125]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[125]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[125]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[125]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[125]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[125]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[125]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[125]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[125]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[125]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[125]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[125]->NotRange.Usage = 0x0081 +pp_data->cap[125]->NotRange.Reserved1 = 0x0081 +pp_data->cap[125]->NotRange.StringIndex = 0 +pp_data->cap[125]->NotRange.Reserved2 = 0 +pp_data->cap[125]->NotRange.DesignatorIndex = 0 +pp_data->cap[125]->NotRange.Reserved3 = 0 +pp_data->cap[125]->NotRange.DataIndex = 38 +pp_data->cap[125]->NotRange.Reserved4 = 38 +pp_data->cap[125]->NotButton.HasNull = 0 +pp_data->cap[125]->NotButton.Reserved4 = 0x000000 +pp_data->cap[125]->NotButton.LogicalMin = 0 +pp_data->cap[125]->NotButton.LogicalMax = 127 +pp_data->cap[125]->NotButton.PhysicalMin = 0 +pp_data->cap[125]->NotButton.PhysicalMax = 0 +pp_data->cap[125]->Units = 0 +pp_data->cap[125]->UnitsExp = 0 + +pp_data->cap[126]->UsagePage = 0xFF01 +pp_data->cap[126]->ReportID = 0x80 +pp_data->cap[126]->BitPosition = 0 +pp_data->cap[126]->BitSize = 8 +pp_data->cap[126]->ReportCount = 1 +pp_data->cap[126]->BytePosition = 0x0037 +pp_data->cap[126]->BitCount = 8 +pp_data->cap[126]->BitField = 0x02 +pp_data->cap[126]->NextBytePosition = 0x0038 +pp_data->cap[126]->LinkCollection = 0x0003 +pp_data->cap[126]->LinkUsagePage = 0xFF01 +pp_data->cap[126]->LinkUsage = 0x0080 +pp_data->cap[126]->IsMultipleItemsForArray = 0 +pp_data->cap[126]->IsButtonCap = 0 +pp_data->cap[126]->IsPadding = 0 +pp_data->cap[126]->IsAbsolute = 1 +pp_data->cap[126]->IsRange = 0 +pp_data->cap[126]->IsAlias = 0 +pp_data->cap[126]->IsStringRange = 0 +pp_data->cap[126]->IsDesignatorRange = 0 +pp_data->cap[126]->Reserved1 = 0x000000 +pp_data->cap[126]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[126]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[126]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[126]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[126]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[126]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[126]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[126]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[126]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[126]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[126]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[126]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[126]->NotRange.Usage = 0x0081 +pp_data->cap[126]->NotRange.Reserved1 = 0x0081 +pp_data->cap[126]->NotRange.StringIndex = 0 +pp_data->cap[126]->NotRange.Reserved2 = 0 +pp_data->cap[126]->NotRange.DesignatorIndex = 0 +pp_data->cap[126]->NotRange.Reserved3 = 0 +pp_data->cap[126]->NotRange.DataIndex = 39 +pp_data->cap[126]->NotRange.Reserved4 = 39 +pp_data->cap[126]->NotButton.HasNull = 0 +pp_data->cap[126]->NotButton.Reserved4 = 0x000000 +pp_data->cap[126]->NotButton.LogicalMin = 0 +pp_data->cap[126]->NotButton.LogicalMax = 127 +pp_data->cap[126]->NotButton.PhysicalMin = 0 +pp_data->cap[126]->NotButton.PhysicalMax = 0 +pp_data->cap[126]->Units = 0 +pp_data->cap[126]->UnitsExp = 0 + +pp_data->cap[127]->UsagePage = 0xFF01 +pp_data->cap[127]->ReportID = 0x80 +pp_data->cap[127]->BitPosition = 0 +pp_data->cap[127]->BitSize = 8 +pp_data->cap[127]->ReportCount = 1 +pp_data->cap[127]->BytePosition = 0x0036 +pp_data->cap[127]->BitCount = 8 +pp_data->cap[127]->BitField = 0x02 +pp_data->cap[127]->NextBytePosition = 0x0037 +pp_data->cap[127]->LinkCollection = 0x0003 +pp_data->cap[127]->LinkUsagePage = 0xFF01 +pp_data->cap[127]->LinkUsage = 0x0080 +pp_data->cap[127]->IsMultipleItemsForArray = 0 +pp_data->cap[127]->IsButtonCap = 0 +pp_data->cap[127]->IsPadding = 0 +pp_data->cap[127]->IsAbsolute = 1 +pp_data->cap[127]->IsRange = 0 +pp_data->cap[127]->IsAlias = 0 +pp_data->cap[127]->IsStringRange = 0 +pp_data->cap[127]->IsDesignatorRange = 0 +pp_data->cap[127]->Reserved1 = 0x000000 +pp_data->cap[127]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[127]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[127]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[127]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[127]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[127]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[127]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[127]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[127]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[127]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[127]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[127]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[127]->NotRange.Usage = 0x0081 +pp_data->cap[127]->NotRange.Reserved1 = 0x0081 +pp_data->cap[127]->NotRange.StringIndex = 0 +pp_data->cap[127]->NotRange.Reserved2 = 0 +pp_data->cap[127]->NotRange.DesignatorIndex = 0 +pp_data->cap[127]->NotRange.Reserved3 = 0 +pp_data->cap[127]->NotRange.DataIndex = 40 +pp_data->cap[127]->NotRange.Reserved4 = 40 +pp_data->cap[127]->NotButton.HasNull = 0 +pp_data->cap[127]->NotButton.Reserved4 = 0x000000 +pp_data->cap[127]->NotButton.LogicalMin = 0 +pp_data->cap[127]->NotButton.LogicalMax = 127 +pp_data->cap[127]->NotButton.PhysicalMin = 0 +pp_data->cap[127]->NotButton.PhysicalMax = 0 +pp_data->cap[127]->Units = 0 +pp_data->cap[127]->UnitsExp = 0 + +pp_data->cap[128]->UsagePage = 0xFF01 +pp_data->cap[128]->ReportID = 0x80 +pp_data->cap[128]->BitPosition = 0 +pp_data->cap[128]->BitSize = 8 +pp_data->cap[128]->ReportCount = 1 +pp_data->cap[128]->BytePosition = 0x0035 +pp_data->cap[128]->BitCount = 8 +pp_data->cap[128]->BitField = 0x02 +pp_data->cap[128]->NextBytePosition = 0x0036 +pp_data->cap[128]->LinkCollection = 0x0003 +pp_data->cap[128]->LinkUsagePage = 0xFF01 +pp_data->cap[128]->LinkUsage = 0x0080 +pp_data->cap[128]->IsMultipleItemsForArray = 0 +pp_data->cap[128]->IsButtonCap = 0 +pp_data->cap[128]->IsPadding = 0 +pp_data->cap[128]->IsAbsolute = 1 +pp_data->cap[128]->IsRange = 0 +pp_data->cap[128]->IsAlias = 0 +pp_data->cap[128]->IsStringRange = 0 +pp_data->cap[128]->IsDesignatorRange = 0 +pp_data->cap[128]->Reserved1 = 0x000000 +pp_data->cap[128]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[128]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[128]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[128]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[128]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[128]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[128]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[128]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[128]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[128]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[128]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[128]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[128]->NotRange.Usage = 0x0081 +pp_data->cap[128]->NotRange.Reserved1 = 0x0081 +pp_data->cap[128]->NotRange.StringIndex = 0 +pp_data->cap[128]->NotRange.Reserved2 = 0 +pp_data->cap[128]->NotRange.DesignatorIndex = 0 +pp_data->cap[128]->NotRange.Reserved3 = 0 +pp_data->cap[128]->NotRange.DataIndex = 41 +pp_data->cap[128]->NotRange.Reserved4 = 41 +pp_data->cap[128]->NotButton.HasNull = 0 +pp_data->cap[128]->NotButton.Reserved4 = 0x000000 +pp_data->cap[128]->NotButton.LogicalMin = 0 +pp_data->cap[128]->NotButton.LogicalMax = 127 +pp_data->cap[128]->NotButton.PhysicalMin = 0 +pp_data->cap[128]->NotButton.PhysicalMax = 0 +pp_data->cap[128]->Units = 0 +pp_data->cap[128]->UnitsExp = 0 + +pp_data->cap[129]->UsagePage = 0xFF01 +pp_data->cap[129]->ReportID = 0x80 +pp_data->cap[129]->BitPosition = 0 +pp_data->cap[129]->BitSize = 8 +pp_data->cap[129]->ReportCount = 1 +pp_data->cap[129]->BytePosition = 0x0034 +pp_data->cap[129]->BitCount = 8 +pp_data->cap[129]->BitField = 0x02 +pp_data->cap[129]->NextBytePosition = 0x0035 +pp_data->cap[129]->LinkCollection = 0x0003 +pp_data->cap[129]->LinkUsagePage = 0xFF01 +pp_data->cap[129]->LinkUsage = 0x0080 +pp_data->cap[129]->IsMultipleItemsForArray = 0 +pp_data->cap[129]->IsButtonCap = 0 +pp_data->cap[129]->IsPadding = 0 +pp_data->cap[129]->IsAbsolute = 1 +pp_data->cap[129]->IsRange = 0 +pp_data->cap[129]->IsAlias = 0 +pp_data->cap[129]->IsStringRange = 0 +pp_data->cap[129]->IsDesignatorRange = 0 +pp_data->cap[129]->Reserved1 = 0x000000 +pp_data->cap[129]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[129]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[129]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[129]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[129]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[129]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[129]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[129]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[129]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[129]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[129]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[129]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[129]->NotRange.Usage = 0x0081 +pp_data->cap[129]->NotRange.Reserved1 = 0x0081 +pp_data->cap[129]->NotRange.StringIndex = 0 +pp_data->cap[129]->NotRange.Reserved2 = 0 +pp_data->cap[129]->NotRange.DesignatorIndex = 0 +pp_data->cap[129]->NotRange.Reserved3 = 0 +pp_data->cap[129]->NotRange.DataIndex = 42 +pp_data->cap[129]->NotRange.Reserved4 = 42 +pp_data->cap[129]->NotButton.HasNull = 0 +pp_data->cap[129]->NotButton.Reserved4 = 0x000000 +pp_data->cap[129]->NotButton.LogicalMin = 0 +pp_data->cap[129]->NotButton.LogicalMax = 127 +pp_data->cap[129]->NotButton.PhysicalMin = 0 +pp_data->cap[129]->NotButton.PhysicalMax = 0 +pp_data->cap[129]->Units = 0 +pp_data->cap[129]->UnitsExp = 0 + +pp_data->cap[130]->UsagePage = 0xFF01 +pp_data->cap[130]->ReportID = 0x80 +pp_data->cap[130]->BitPosition = 0 +pp_data->cap[130]->BitSize = 8 +pp_data->cap[130]->ReportCount = 1 +pp_data->cap[130]->BytePosition = 0x0033 +pp_data->cap[130]->BitCount = 8 +pp_data->cap[130]->BitField = 0x02 +pp_data->cap[130]->NextBytePosition = 0x0034 +pp_data->cap[130]->LinkCollection = 0x0003 +pp_data->cap[130]->LinkUsagePage = 0xFF01 +pp_data->cap[130]->LinkUsage = 0x0080 +pp_data->cap[130]->IsMultipleItemsForArray = 0 +pp_data->cap[130]->IsButtonCap = 0 +pp_data->cap[130]->IsPadding = 0 +pp_data->cap[130]->IsAbsolute = 1 +pp_data->cap[130]->IsRange = 0 +pp_data->cap[130]->IsAlias = 0 +pp_data->cap[130]->IsStringRange = 0 +pp_data->cap[130]->IsDesignatorRange = 0 +pp_data->cap[130]->Reserved1 = 0x000000 +pp_data->cap[130]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[130]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[130]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[130]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[130]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[130]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[130]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[130]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[130]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[130]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[130]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[130]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[130]->NotRange.Usage = 0x0081 +pp_data->cap[130]->NotRange.Reserved1 = 0x0081 +pp_data->cap[130]->NotRange.StringIndex = 0 +pp_data->cap[130]->NotRange.Reserved2 = 0 +pp_data->cap[130]->NotRange.DesignatorIndex = 0 +pp_data->cap[130]->NotRange.Reserved3 = 0 +pp_data->cap[130]->NotRange.DataIndex = 43 +pp_data->cap[130]->NotRange.Reserved4 = 43 +pp_data->cap[130]->NotButton.HasNull = 0 +pp_data->cap[130]->NotButton.Reserved4 = 0x000000 +pp_data->cap[130]->NotButton.LogicalMin = 0 +pp_data->cap[130]->NotButton.LogicalMax = 127 +pp_data->cap[130]->NotButton.PhysicalMin = 0 +pp_data->cap[130]->NotButton.PhysicalMax = 0 +pp_data->cap[130]->Units = 0 +pp_data->cap[130]->UnitsExp = 0 + +pp_data->cap[131]->UsagePage = 0xFF01 +pp_data->cap[131]->ReportID = 0x80 +pp_data->cap[131]->BitPosition = 0 +pp_data->cap[131]->BitSize = 8 +pp_data->cap[131]->ReportCount = 1 +pp_data->cap[131]->BytePosition = 0x0032 +pp_data->cap[131]->BitCount = 8 +pp_data->cap[131]->BitField = 0x02 +pp_data->cap[131]->NextBytePosition = 0x0033 +pp_data->cap[131]->LinkCollection = 0x0003 +pp_data->cap[131]->LinkUsagePage = 0xFF01 +pp_data->cap[131]->LinkUsage = 0x0080 +pp_data->cap[131]->IsMultipleItemsForArray = 0 +pp_data->cap[131]->IsButtonCap = 0 +pp_data->cap[131]->IsPadding = 0 +pp_data->cap[131]->IsAbsolute = 1 +pp_data->cap[131]->IsRange = 0 +pp_data->cap[131]->IsAlias = 0 +pp_data->cap[131]->IsStringRange = 0 +pp_data->cap[131]->IsDesignatorRange = 0 +pp_data->cap[131]->Reserved1 = 0x000000 +pp_data->cap[131]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[131]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[131]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[131]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[131]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[131]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[131]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[131]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[131]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[131]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[131]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[131]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[131]->NotRange.Usage = 0x0081 +pp_data->cap[131]->NotRange.Reserved1 = 0x0081 +pp_data->cap[131]->NotRange.StringIndex = 0 +pp_data->cap[131]->NotRange.Reserved2 = 0 +pp_data->cap[131]->NotRange.DesignatorIndex = 0 +pp_data->cap[131]->NotRange.Reserved3 = 0 +pp_data->cap[131]->NotRange.DataIndex = 44 +pp_data->cap[131]->NotRange.Reserved4 = 44 +pp_data->cap[131]->NotButton.HasNull = 0 +pp_data->cap[131]->NotButton.Reserved4 = 0x000000 +pp_data->cap[131]->NotButton.LogicalMin = 0 +pp_data->cap[131]->NotButton.LogicalMax = 127 +pp_data->cap[131]->NotButton.PhysicalMin = 0 +pp_data->cap[131]->NotButton.PhysicalMax = 0 +pp_data->cap[131]->Units = 0 +pp_data->cap[131]->UnitsExp = 0 + +pp_data->cap[132]->UsagePage = 0xFF01 +pp_data->cap[132]->ReportID = 0x80 +pp_data->cap[132]->BitPosition = 0 +pp_data->cap[132]->BitSize = 8 +pp_data->cap[132]->ReportCount = 1 +pp_data->cap[132]->BytePosition = 0x0031 +pp_data->cap[132]->BitCount = 8 +pp_data->cap[132]->BitField = 0x02 +pp_data->cap[132]->NextBytePosition = 0x0032 +pp_data->cap[132]->LinkCollection = 0x0003 +pp_data->cap[132]->LinkUsagePage = 0xFF01 +pp_data->cap[132]->LinkUsage = 0x0080 +pp_data->cap[132]->IsMultipleItemsForArray = 0 +pp_data->cap[132]->IsButtonCap = 0 +pp_data->cap[132]->IsPadding = 0 +pp_data->cap[132]->IsAbsolute = 1 +pp_data->cap[132]->IsRange = 0 +pp_data->cap[132]->IsAlias = 0 +pp_data->cap[132]->IsStringRange = 0 +pp_data->cap[132]->IsDesignatorRange = 0 +pp_data->cap[132]->Reserved1 = 0x000000 +pp_data->cap[132]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[132]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[132]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[132]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[132]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[132]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[132]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[132]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[132]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[132]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[132]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[132]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[132]->NotRange.Usage = 0x0081 +pp_data->cap[132]->NotRange.Reserved1 = 0x0081 +pp_data->cap[132]->NotRange.StringIndex = 0 +pp_data->cap[132]->NotRange.Reserved2 = 0 +pp_data->cap[132]->NotRange.DesignatorIndex = 0 +pp_data->cap[132]->NotRange.Reserved3 = 0 +pp_data->cap[132]->NotRange.DataIndex = 45 +pp_data->cap[132]->NotRange.Reserved4 = 45 +pp_data->cap[132]->NotButton.HasNull = 0 +pp_data->cap[132]->NotButton.Reserved4 = 0x000000 +pp_data->cap[132]->NotButton.LogicalMin = 0 +pp_data->cap[132]->NotButton.LogicalMax = 127 +pp_data->cap[132]->NotButton.PhysicalMin = 0 +pp_data->cap[132]->NotButton.PhysicalMax = 0 +pp_data->cap[132]->Units = 0 +pp_data->cap[132]->UnitsExp = 0 + +pp_data->cap[133]->UsagePage = 0xFF01 +pp_data->cap[133]->ReportID = 0x80 +pp_data->cap[133]->BitPosition = 0 +pp_data->cap[133]->BitSize = 8 +pp_data->cap[133]->ReportCount = 1 +pp_data->cap[133]->BytePosition = 0x0030 +pp_data->cap[133]->BitCount = 8 +pp_data->cap[133]->BitField = 0x02 +pp_data->cap[133]->NextBytePosition = 0x0031 +pp_data->cap[133]->LinkCollection = 0x0003 +pp_data->cap[133]->LinkUsagePage = 0xFF01 +pp_data->cap[133]->LinkUsage = 0x0080 +pp_data->cap[133]->IsMultipleItemsForArray = 0 +pp_data->cap[133]->IsButtonCap = 0 +pp_data->cap[133]->IsPadding = 0 +pp_data->cap[133]->IsAbsolute = 1 +pp_data->cap[133]->IsRange = 0 +pp_data->cap[133]->IsAlias = 0 +pp_data->cap[133]->IsStringRange = 0 +pp_data->cap[133]->IsDesignatorRange = 0 +pp_data->cap[133]->Reserved1 = 0x000000 +pp_data->cap[133]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[133]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[133]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[133]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[133]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[133]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[133]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[133]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[133]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[133]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[133]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[133]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[133]->NotRange.Usage = 0x0081 +pp_data->cap[133]->NotRange.Reserved1 = 0x0081 +pp_data->cap[133]->NotRange.StringIndex = 0 +pp_data->cap[133]->NotRange.Reserved2 = 0 +pp_data->cap[133]->NotRange.DesignatorIndex = 0 +pp_data->cap[133]->NotRange.Reserved3 = 0 +pp_data->cap[133]->NotRange.DataIndex = 46 +pp_data->cap[133]->NotRange.Reserved4 = 46 +pp_data->cap[133]->NotButton.HasNull = 0 +pp_data->cap[133]->NotButton.Reserved4 = 0x000000 +pp_data->cap[133]->NotButton.LogicalMin = 0 +pp_data->cap[133]->NotButton.LogicalMax = 127 +pp_data->cap[133]->NotButton.PhysicalMin = 0 +pp_data->cap[133]->NotButton.PhysicalMax = 0 +pp_data->cap[133]->Units = 0 +pp_data->cap[133]->UnitsExp = 0 + +pp_data->cap[134]->UsagePage = 0xFF01 +pp_data->cap[134]->ReportID = 0x80 +pp_data->cap[134]->BitPosition = 0 +pp_data->cap[134]->BitSize = 8 +pp_data->cap[134]->ReportCount = 1 +pp_data->cap[134]->BytePosition = 0x002F +pp_data->cap[134]->BitCount = 8 +pp_data->cap[134]->BitField = 0x02 +pp_data->cap[134]->NextBytePosition = 0x0030 +pp_data->cap[134]->LinkCollection = 0x0003 +pp_data->cap[134]->LinkUsagePage = 0xFF01 +pp_data->cap[134]->LinkUsage = 0x0080 +pp_data->cap[134]->IsMultipleItemsForArray = 0 +pp_data->cap[134]->IsButtonCap = 0 +pp_data->cap[134]->IsPadding = 0 +pp_data->cap[134]->IsAbsolute = 1 +pp_data->cap[134]->IsRange = 0 +pp_data->cap[134]->IsAlias = 0 +pp_data->cap[134]->IsStringRange = 0 +pp_data->cap[134]->IsDesignatorRange = 0 +pp_data->cap[134]->Reserved1 = 0x000000 +pp_data->cap[134]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[134]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[134]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[134]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[134]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[134]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[134]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[134]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[134]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[134]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[134]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[134]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[134]->NotRange.Usage = 0x0081 +pp_data->cap[134]->NotRange.Reserved1 = 0x0081 +pp_data->cap[134]->NotRange.StringIndex = 0 +pp_data->cap[134]->NotRange.Reserved2 = 0 +pp_data->cap[134]->NotRange.DesignatorIndex = 0 +pp_data->cap[134]->NotRange.Reserved3 = 0 +pp_data->cap[134]->NotRange.DataIndex = 47 +pp_data->cap[134]->NotRange.Reserved4 = 47 +pp_data->cap[134]->NotButton.HasNull = 0 +pp_data->cap[134]->NotButton.Reserved4 = 0x000000 +pp_data->cap[134]->NotButton.LogicalMin = 0 +pp_data->cap[134]->NotButton.LogicalMax = 127 +pp_data->cap[134]->NotButton.PhysicalMin = 0 +pp_data->cap[134]->NotButton.PhysicalMax = 0 +pp_data->cap[134]->Units = 0 +pp_data->cap[134]->UnitsExp = 0 + +pp_data->cap[135]->UsagePage = 0xFF01 +pp_data->cap[135]->ReportID = 0x80 +pp_data->cap[135]->BitPosition = 0 +pp_data->cap[135]->BitSize = 8 +pp_data->cap[135]->ReportCount = 1 +pp_data->cap[135]->BytePosition = 0x002E +pp_data->cap[135]->BitCount = 8 +pp_data->cap[135]->BitField = 0x02 +pp_data->cap[135]->NextBytePosition = 0x002F +pp_data->cap[135]->LinkCollection = 0x0003 +pp_data->cap[135]->LinkUsagePage = 0xFF01 +pp_data->cap[135]->LinkUsage = 0x0080 +pp_data->cap[135]->IsMultipleItemsForArray = 0 +pp_data->cap[135]->IsButtonCap = 0 +pp_data->cap[135]->IsPadding = 0 +pp_data->cap[135]->IsAbsolute = 1 +pp_data->cap[135]->IsRange = 0 +pp_data->cap[135]->IsAlias = 0 +pp_data->cap[135]->IsStringRange = 0 +pp_data->cap[135]->IsDesignatorRange = 0 +pp_data->cap[135]->Reserved1 = 0x000000 +pp_data->cap[135]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[135]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[135]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[135]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[135]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[135]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[135]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[135]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[135]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[135]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[135]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[135]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[135]->NotRange.Usage = 0x0081 +pp_data->cap[135]->NotRange.Reserved1 = 0x0081 +pp_data->cap[135]->NotRange.StringIndex = 0 +pp_data->cap[135]->NotRange.Reserved2 = 0 +pp_data->cap[135]->NotRange.DesignatorIndex = 0 +pp_data->cap[135]->NotRange.Reserved3 = 0 +pp_data->cap[135]->NotRange.DataIndex = 48 +pp_data->cap[135]->NotRange.Reserved4 = 48 +pp_data->cap[135]->NotButton.HasNull = 0 +pp_data->cap[135]->NotButton.Reserved4 = 0x000000 +pp_data->cap[135]->NotButton.LogicalMin = 0 +pp_data->cap[135]->NotButton.LogicalMax = 127 +pp_data->cap[135]->NotButton.PhysicalMin = 0 +pp_data->cap[135]->NotButton.PhysicalMax = 0 +pp_data->cap[135]->Units = 0 +pp_data->cap[135]->UnitsExp = 0 + +pp_data->cap[136]->UsagePage = 0xFF01 +pp_data->cap[136]->ReportID = 0x80 +pp_data->cap[136]->BitPosition = 0 +pp_data->cap[136]->BitSize = 8 +pp_data->cap[136]->ReportCount = 1 +pp_data->cap[136]->BytePosition = 0x002D +pp_data->cap[136]->BitCount = 8 +pp_data->cap[136]->BitField = 0x02 +pp_data->cap[136]->NextBytePosition = 0x002E +pp_data->cap[136]->LinkCollection = 0x0003 +pp_data->cap[136]->LinkUsagePage = 0xFF01 +pp_data->cap[136]->LinkUsage = 0x0080 +pp_data->cap[136]->IsMultipleItemsForArray = 0 +pp_data->cap[136]->IsButtonCap = 0 +pp_data->cap[136]->IsPadding = 0 +pp_data->cap[136]->IsAbsolute = 1 +pp_data->cap[136]->IsRange = 0 +pp_data->cap[136]->IsAlias = 0 +pp_data->cap[136]->IsStringRange = 0 +pp_data->cap[136]->IsDesignatorRange = 0 +pp_data->cap[136]->Reserved1 = 0x000000 +pp_data->cap[136]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[136]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[136]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[136]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[136]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[136]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[136]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[136]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[136]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[136]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[136]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[136]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[136]->NotRange.Usage = 0x0081 +pp_data->cap[136]->NotRange.Reserved1 = 0x0081 +pp_data->cap[136]->NotRange.StringIndex = 0 +pp_data->cap[136]->NotRange.Reserved2 = 0 +pp_data->cap[136]->NotRange.DesignatorIndex = 0 +pp_data->cap[136]->NotRange.Reserved3 = 0 +pp_data->cap[136]->NotRange.DataIndex = 49 +pp_data->cap[136]->NotRange.Reserved4 = 49 +pp_data->cap[136]->NotButton.HasNull = 0 +pp_data->cap[136]->NotButton.Reserved4 = 0x000000 +pp_data->cap[136]->NotButton.LogicalMin = 0 +pp_data->cap[136]->NotButton.LogicalMax = 127 +pp_data->cap[136]->NotButton.PhysicalMin = 0 +pp_data->cap[136]->NotButton.PhysicalMax = 0 +pp_data->cap[136]->Units = 0 +pp_data->cap[136]->UnitsExp = 0 + +pp_data->cap[137]->UsagePage = 0xFF01 +pp_data->cap[137]->ReportID = 0x80 +pp_data->cap[137]->BitPosition = 0 +pp_data->cap[137]->BitSize = 8 +pp_data->cap[137]->ReportCount = 1 +pp_data->cap[137]->BytePosition = 0x002C +pp_data->cap[137]->BitCount = 8 +pp_data->cap[137]->BitField = 0x02 +pp_data->cap[137]->NextBytePosition = 0x002D +pp_data->cap[137]->LinkCollection = 0x0003 +pp_data->cap[137]->LinkUsagePage = 0xFF01 +pp_data->cap[137]->LinkUsage = 0x0080 +pp_data->cap[137]->IsMultipleItemsForArray = 0 +pp_data->cap[137]->IsButtonCap = 0 +pp_data->cap[137]->IsPadding = 0 +pp_data->cap[137]->IsAbsolute = 1 +pp_data->cap[137]->IsRange = 0 +pp_data->cap[137]->IsAlias = 0 +pp_data->cap[137]->IsStringRange = 0 +pp_data->cap[137]->IsDesignatorRange = 0 +pp_data->cap[137]->Reserved1 = 0x000000 +pp_data->cap[137]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[137]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[137]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[137]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[137]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[137]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[137]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[137]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[137]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[137]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[137]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[137]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[137]->NotRange.Usage = 0x0081 +pp_data->cap[137]->NotRange.Reserved1 = 0x0081 +pp_data->cap[137]->NotRange.StringIndex = 0 +pp_data->cap[137]->NotRange.Reserved2 = 0 +pp_data->cap[137]->NotRange.DesignatorIndex = 0 +pp_data->cap[137]->NotRange.Reserved3 = 0 +pp_data->cap[137]->NotRange.DataIndex = 50 +pp_data->cap[137]->NotRange.Reserved4 = 50 +pp_data->cap[137]->NotButton.HasNull = 0 +pp_data->cap[137]->NotButton.Reserved4 = 0x000000 +pp_data->cap[137]->NotButton.LogicalMin = 0 +pp_data->cap[137]->NotButton.LogicalMax = 127 +pp_data->cap[137]->NotButton.PhysicalMin = 0 +pp_data->cap[137]->NotButton.PhysicalMax = 0 +pp_data->cap[137]->Units = 0 +pp_data->cap[137]->UnitsExp = 0 + +pp_data->cap[138]->UsagePage = 0xFF01 +pp_data->cap[138]->ReportID = 0x80 +pp_data->cap[138]->BitPosition = 0 +pp_data->cap[138]->BitSize = 8 +pp_data->cap[138]->ReportCount = 1 +pp_data->cap[138]->BytePosition = 0x002B +pp_data->cap[138]->BitCount = 8 +pp_data->cap[138]->BitField = 0x02 +pp_data->cap[138]->NextBytePosition = 0x002C +pp_data->cap[138]->LinkCollection = 0x0003 +pp_data->cap[138]->LinkUsagePage = 0xFF01 +pp_data->cap[138]->LinkUsage = 0x0080 +pp_data->cap[138]->IsMultipleItemsForArray = 0 +pp_data->cap[138]->IsButtonCap = 0 +pp_data->cap[138]->IsPadding = 0 +pp_data->cap[138]->IsAbsolute = 1 +pp_data->cap[138]->IsRange = 0 +pp_data->cap[138]->IsAlias = 0 +pp_data->cap[138]->IsStringRange = 0 +pp_data->cap[138]->IsDesignatorRange = 0 +pp_data->cap[138]->Reserved1 = 0x000000 +pp_data->cap[138]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[138]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[138]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[138]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[138]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[138]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[138]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[138]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[138]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[138]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[138]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[138]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[138]->NotRange.Usage = 0x0081 +pp_data->cap[138]->NotRange.Reserved1 = 0x0081 +pp_data->cap[138]->NotRange.StringIndex = 0 +pp_data->cap[138]->NotRange.Reserved2 = 0 +pp_data->cap[138]->NotRange.DesignatorIndex = 0 +pp_data->cap[138]->NotRange.Reserved3 = 0 +pp_data->cap[138]->NotRange.DataIndex = 51 +pp_data->cap[138]->NotRange.Reserved4 = 51 +pp_data->cap[138]->NotButton.HasNull = 0 +pp_data->cap[138]->NotButton.Reserved4 = 0x000000 +pp_data->cap[138]->NotButton.LogicalMin = 0 +pp_data->cap[138]->NotButton.LogicalMax = 127 +pp_data->cap[138]->NotButton.PhysicalMin = 0 +pp_data->cap[138]->NotButton.PhysicalMax = 0 +pp_data->cap[138]->Units = 0 +pp_data->cap[138]->UnitsExp = 0 + +pp_data->cap[139]->UsagePage = 0xFF01 +pp_data->cap[139]->ReportID = 0x80 +pp_data->cap[139]->BitPosition = 0 +pp_data->cap[139]->BitSize = 8 +pp_data->cap[139]->ReportCount = 1 +pp_data->cap[139]->BytePosition = 0x002A +pp_data->cap[139]->BitCount = 8 +pp_data->cap[139]->BitField = 0x02 +pp_data->cap[139]->NextBytePosition = 0x002B +pp_data->cap[139]->LinkCollection = 0x0003 +pp_data->cap[139]->LinkUsagePage = 0xFF01 +pp_data->cap[139]->LinkUsage = 0x0080 +pp_data->cap[139]->IsMultipleItemsForArray = 0 +pp_data->cap[139]->IsButtonCap = 0 +pp_data->cap[139]->IsPadding = 0 +pp_data->cap[139]->IsAbsolute = 1 +pp_data->cap[139]->IsRange = 0 +pp_data->cap[139]->IsAlias = 0 +pp_data->cap[139]->IsStringRange = 0 +pp_data->cap[139]->IsDesignatorRange = 0 +pp_data->cap[139]->Reserved1 = 0x000000 +pp_data->cap[139]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[139]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[139]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[139]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[139]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[139]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[139]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[139]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[139]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[139]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[139]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[139]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[139]->NotRange.Usage = 0x0081 +pp_data->cap[139]->NotRange.Reserved1 = 0x0081 +pp_data->cap[139]->NotRange.StringIndex = 0 +pp_data->cap[139]->NotRange.Reserved2 = 0 +pp_data->cap[139]->NotRange.DesignatorIndex = 0 +pp_data->cap[139]->NotRange.Reserved3 = 0 +pp_data->cap[139]->NotRange.DataIndex = 52 +pp_data->cap[139]->NotRange.Reserved4 = 52 +pp_data->cap[139]->NotButton.HasNull = 0 +pp_data->cap[139]->NotButton.Reserved4 = 0x000000 +pp_data->cap[139]->NotButton.LogicalMin = 0 +pp_data->cap[139]->NotButton.LogicalMax = 127 +pp_data->cap[139]->NotButton.PhysicalMin = 0 +pp_data->cap[139]->NotButton.PhysicalMax = 0 +pp_data->cap[139]->Units = 0 +pp_data->cap[139]->UnitsExp = 0 + +pp_data->cap[140]->UsagePage = 0xFF01 +pp_data->cap[140]->ReportID = 0x80 +pp_data->cap[140]->BitPosition = 0 +pp_data->cap[140]->BitSize = 8 +pp_data->cap[140]->ReportCount = 1 +pp_data->cap[140]->BytePosition = 0x0029 +pp_data->cap[140]->BitCount = 8 +pp_data->cap[140]->BitField = 0x02 +pp_data->cap[140]->NextBytePosition = 0x002A +pp_data->cap[140]->LinkCollection = 0x0003 +pp_data->cap[140]->LinkUsagePage = 0xFF01 +pp_data->cap[140]->LinkUsage = 0x0080 +pp_data->cap[140]->IsMultipleItemsForArray = 0 +pp_data->cap[140]->IsButtonCap = 0 +pp_data->cap[140]->IsPadding = 0 +pp_data->cap[140]->IsAbsolute = 1 +pp_data->cap[140]->IsRange = 0 +pp_data->cap[140]->IsAlias = 0 +pp_data->cap[140]->IsStringRange = 0 +pp_data->cap[140]->IsDesignatorRange = 0 +pp_data->cap[140]->Reserved1 = 0x000000 +pp_data->cap[140]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[140]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[140]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[140]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[140]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[140]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[140]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[140]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[140]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[140]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[140]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[140]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[140]->NotRange.Usage = 0x0081 +pp_data->cap[140]->NotRange.Reserved1 = 0x0081 +pp_data->cap[140]->NotRange.StringIndex = 0 +pp_data->cap[140]->NotRange.Reserved2 = 0 +pp_data->cap[140]->NotRange.DesignatorIndex = 0 +pp_data->cap[140]->NotRange.Reserved3 = 0 +pp_data->cap[140]->NotRange.DataIndex = 53 +pp_data->cap[140]->NotRange.Reserved4 = 53 +pp_data->cap[140]->NotButton.HasNull = 0 +pp_data->cap[140]->NotButton.Reserved4 = 0x000000 +pp_data->cap[140]->NotButton.LogicalMin = 0 +pp_data->cap[140]->NotButton.LogicalMax = 127 +pp_data->cap[140]->NotButton.PhysicalMin = 0 +pp_data->cap[140]->NotButton.PhysicalMax = 0 +pp_data->cap[140]->Units = 0 +pp_data->cap[140]->UnitsExp = 0 + +pp_data->cap[141]->UsagePage = 0xFF01 +pp_data->cap[141]->ReportID = 0x80 +pp_data->cap[141]->BitPosition = 0 +pp_data->cap[141]->BitSize = 8 +pp_data->cap[141]->ReportCount = 1 +pp_data->cap[141]->BytePosition = 0x0028 +pp_data->cap[141]->BitCount = 8 +pp_data->cap[141]->BitField = 0x02 +pp_data->cap[141]->NextBytePosition = 0x0029 +pp_data->cap[141]->LinkCollection = 0x0003 +pp_data->cap[141]->LinkUsagePage = 0xFF01 +pp_data->cap[141]->LinkUsage = 0x0080 +pp_data->cap[141]->IsMultipleItemsForArray = 0 +pp_data->cap[141]->IsButtonCap = 0 +pp_data->cap[141]->IsPadding = 0 +pp_data->cap[141]->IsAbsolute = 1 +pp_data->cap[141]->IsRange = 0 +pp_data->cap[141]->IsAlias = 0 +pp_data->cap[141]->IsStringRange = 0 +pp_data->cap[141]->IsDesignatorRange = 0 +pp_data->cap[141]->Reserved1 = 0x000000 +pp_data->cap[141]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[141]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[141]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[141]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[141]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[141]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[141]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[141]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[141]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[141]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[141]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[141]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[141]->NotRange.Usage = 0x0081 +pp_data->cap[141]->NotRange.Reserved1 = 0x0081 +pp_data->cap[141]->NotRange.StringIndex = 0 +pp_data->cap[141]->NotRange.Reserved2 = 0 +pp_data->cap[141]->NotRange.DesignatorIndex = 0 +pp_data->cap[141]->NotRange.Reserved3 = 0 +pp_data->cap[141]->NotRange.DataIndex = 54 +pp_data->cap[141]->NotRange.Reserved4 = 54 +pp_data->cap[141]->NotButton.HasNull = 0 +pp_data->cap[141]->NotButton.Reserved4 = 0x000000 +pp_data->cap[141]->NotButton.LogicalMin = 0 +pp_data->cap[141]->NotButton.LogicalMax = 127 +pp_data->cap[141]->NotButton.PhysicalMin = 0 +pp_data->cap[141]->NotButton.PhysicalMax = 0 +pp_data->cap[141]->Units = 0 +pp_data->cap[141]->UnitsExp = 0 + +pp_data->cap[142]->UsagePage = 0xFF01 +pp_data->cap[142]->ReportID = 0x80 +pp_data->cap[142]->BitPosition = 0 +pp_data->cap[142]->BitSize = 8 +pp_data->cap[142]->ReportCount = 1 +pp_data->cap[142]->BytePosition = 0x0027 +pp_data->cap[142]->BitCount = 8 +pp_data->cap[142]->BitField = 0x02 +pp_data->cap[142]->NextBytePosition = 0x0028 +pp_data->cap[142]->LinkCollection = 0x0003 +pp_data->cap[142]->LinkUsagePage = 0xFF01 +pp_data->cap[142]->LinkUsage = 0x0080 +pp_data->cap[142]->IsMultipleItemsForArray = 0 +pp_data->cap[142]->IsButtonCap = 0 +pp_data->cap[142]->IsPadding = 0 +pp_data->cap[142]->IsAbsolute = 1 +pp_data->cap[142]->IsRange = 0 +pp_data->cap[142]->IsAlias = 0 +pp_data->cap[142]->IsStringRange = 0 +pp_data->cap[142]->IsDesignatorRange = 0 +pp_data->cap[142]->Reserved1 = 0x000000 +pp_data->cap[142]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[142]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[142]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[142]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[142]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[142]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[142]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[142]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[142]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[142]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[142]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[142]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[142]->NotRange.Usage = 0x0081 +pp_data->cap[142]->NotRange.Reserved1 = 0x0081 +pp_data->cap[142]->NotRange.StringIndex = 0 +pp_data->cap[142]->NotRange.Reserved2 = 0 +pp_data->cap[142]->NotRange.DesignatorIndex = 0 +pp_data->cap[142]->NotRange.Reserved3 = 0 +pp_data->cap[142]->NotRange.DataIndex = 55 +pp_data->cap[142]->NotRange.Reserved4 = 55 +pp_data->cap[142]->NotButton.HasNull = 0 +pp_data->cap[142]->NotButton.Reserved4 = 0x000000 +pp_data->cap[142]->NotButton.LogicalMin = 0 +pp_data->cap[142]->NotButton.LogicalMax = 127 +pp_data->cap[142]->NotButton.PhysicalMin = 0 +pp_data->cap[142]->NotButton.PhysicalMax = 0 +pp_data->cap[142]->Units = 0 +pp_data->cap[142]->UnitsExp = 0 + +pp_data->cap[143]->UsagePage = 0xFF01 +pp_data->cap[143]->ReportID = 0x80 +pp_data->cap[143]->BitPosition = 0 +pp_data->cap[143]->BitSize = 8 +pp_data->cap[143]->ReportCount = 1 +pp_data->cap[143]->BytePosition = 0x0026 +pp_data->cap[143]->BitCount = 8 +pp_data->cap[143]->BitField = 0x02 +pp_data->cap[143]->NextBytePosition = 0x0027 +pp_data->cap[143]->LinkCollection = 0x0003 +pp_data->cap[143]->LinkUsagePage = 0xFF01 +pp_data->cap[143]->LinkUsage = 0x0080 +pp_data->cap[143]->IsMultipleItemsForArray = 0 +pp_data->cap[143]->IsButtonCap = 0 +pp_data->cap[143]->IsPadding = 0 +pp_data->cap[143]->IsAbsolute = 1 +pp_data->cap[143]->IsRange = 0 +pp_data->cap[143]->IsAlias = 0 +pp_data->cap[143]->IsStringRange = 0 +pp_data->cap[143]->IsDesignatorRange = 0 +pp_data->cap[143]->Reserved1 = 0x000000 +pp_data->cap[143]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[143]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[143]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[143]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[143]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[143]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[143]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[143]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[143]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[143]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[143]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[143]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[143]->NotRange.Usage = 0x0081 +pp_data->cap[143]->NotRange.Reserved1 = 0x0081 +pp_data->cap[143]->NotRange.StringIndex = 0 +pp_data->cap[143]->NotRange.Reserved2 = 0 +pp_data->cap[143]->NotRange.DesignatorIndex = 0 +pp_data->cap[143]->NotRange.Reserved3 = 0 +pp_data->cap[143]->NotRange.DataIndex = 56 +pp_data->cap[143]->NotRange.Reserved4 = 56 +pp_data->cap[143]->NotButton.HasNull = 0 +pp_data->cap[143]->NotButton.Reserved4 = 0x000000 +pp_data->cap[143]->NotButton.LogicalMin = 0 +pp_data->cap[143]->NotButton.LogicalMax = 127 +pp_data->cap[143]->NotButton.PhysicalMin = 0 +pp_data->cap[143]->NotButton.PhysicalMax = 0 +pp_data->cap[143]->Units = 0 +pp_data->cap[143]->UnitsExp = 0 + +pp_data->cap[144]->UsagePage = 0xFF01 +pp_data->cap[144]->ReportID = 0x80 +pp_data->cap[144]->BitPosition = 0 +pp_data->cap[144]->BitSize = 8 +pp_data->cap[144]->ReportCount = 1 +pp_data->cap[144]->BytePosition = 0x0025 +pp_data->cap[144]->BitCount = 8 +pp_data->cap[144]->BitField = 0x02 +pp_data->cap[144]->NextBytePosition = 0x0026 +pp_data->cap[144]->LinkCollection = 0x0003 +pp_data->cap[144]->LinkUsagePage = 0xFF01 +pp_data->cap[144]->LinkUsage = 0x0080 +pp_data->cap[144]->IsMultipleItemsForArray = 0 +pp_data->cap[144]->IsButtonCap = 0 +pp_data->cap[144]->IsPadding = 0 +pp_data->cap[144]->IsAbsolute = 1 +pp_data->cap[144]->IsRange = 0 +pp_data->cap[144]->IsAlias = 0 +pp_data->cap[144]->IsStringRange = 0 +pp_data->cap[144]->IsDesignatorRange = 0 +pp_data->cap[144]->Reserved1 = 0x000000 +pp_data->cap[144]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[144]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[144]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[144]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[144]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[144]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[144]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[144]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[144]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[144]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[144]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[144]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[144]->NotRange.Usage = 0x0081 +pp_data->cap[144]->NotRange.Reserved1 = 0x0081 +pp_data->cap[144]->NotRange.StringIndex = 0 +pp_data->cap[144]->NotRange.Reserved2 = 0 +pp_data->cap[144]->NotRange.DesignatorIndex = 0 +pp_data->cap[144]->NotRange.Reserved3 = 0 +pp_data->cap[144]->NotRange.DataIndex = 57 +pp_data->cap[144]->NotRange.Reserved4 = 57 +pp_data->cap[144]->NotButton.HasNull = 0 +pp_data->cap[144]->NotButton.Reserved4 = 0x000000 +pp_data->cap[144]->NotButton.LogicalMin = 0 +pp_data->cap[144]->NotButton.LogicalMax = 127 +pp_data->cap[144]->NotButton.PhysicalMin = 0 +pp_data->cap[144]->NotButton.PhysicalMax = 0 +pp_data->cap[144]->Units = 0 +pp_data->cap[144]->UnitsExp = 0 + +pp_data->cap[145]->UsagePage = 0xFF01 +pp_data->cap[145]->ReportID = 0x80 +pp_data->cap[145]->BitPosition = 0 +pp_data->cap[145]->BitSize = 8 +pp_data->cap[145]->ReportCount = 1 +pp_data->cap[145]->BytePosition = 0x0024 +pp_data->cap[145]->BitCount = 8 +pp_data->cap[145]->BitField = 0x02 +pp_data->cap[145]->NextBytePosition = 0x0025 +pp_data->cap[145]->LinkCollection = 0x0003 +pp_data->cap[145]->LinkUsagePage = 0xFF01 +pp_data->cap[145]->LinkUsage = 0x0080 +pp_data->cap[145]->IsMultipleItemsForArray = 0 +pp_data->cap[145]->IsButtonCap = 0 +pp_data->cap[145]->IsPadding = 0 +pp_data->cap[145]->IsAbsolute = 1 +pp_data->cap[145]->IsRange = 0 +pp_data->cap[145]->IsAlias = 0 +pp_data->cap[145]->IsStringRange = 0 +pp_data->cap[145]->IsDesignatorRange = 0 +pp_data->cap[145]->Reserved1 = 0x000000 +pp_data->cap[145]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[145]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[145]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[145]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[145]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[145]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[145]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[145]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[145]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[145]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[145]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[145]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[145]->NotRange.Usage = 0x0081 +pp_data->cap[145]->NotRange.Reserved1 = 0x0081 +pp_data->cap[145]->NotRange.StringIndex = 0 +pp_data->cap[145]->NotRange.Reserved2 = 0 +pp_data->cap[145]->NotRange.DesignatorIndex = 0 +pp_data->cap[145]->NotRange.Reserved3 = 0 +pp_data->cap[145]->NotRange.DataIndex = 58 +pp_data->cap[145]->NotRange.Reserved4 = 58 +pp_data->cap[145]->NotButton.HasNull = 0 +pp_data->cap[145]->NotButton.Reserved4 = 0x000000 +pp_data->cap[145]->NotButton.LogicalMin = 0 +pp_data->cap[145]->NotButton.LogicalMax = 127 +pp_data->cap[145]->NotButton.PhysicalMin = 0 +pp_data->cap[145]->NotButton.PhysicalMax = 0 +pp_data->cap[145]->Units = 0 +pp_data->cap[145]->UnitsExp = 0 + +pp_data->cap[146]->UsagePage = 0xFF01 +pp_data->cap[146]->ReportID = 0x80 +pp_data->cap[146]->BitPosition = 0 +pp_data->cap[146]->BitSize = 8 +pp_data->cap[146]->ReportCount = 1 +pp_data->cap[146]->BytePosition = 0x0023 +pp_data->cap[146]->BitCount = 8 +pp_data->cap[146]->BitField = 0x02 +pp_data->cap[146]->NextBytePosition = 0x0024 +pp_data->cap[146]->LinkCollection = 0x0003 +pp_data->cap[146]->LinkUsagePage = 0xFF01 +pp_data->cap[146]->LinkUsage = 0x0080 +pp_data->cap[146]->IsMultipleItemsForArray = 0 +pp_data->cap[146]->IsButtonCap = 0 +pp_data->cap[146]->IsPadding = 0 +pp_data->cap[146]->IsAbsolute = 1 +pp_data->cap[146]->IsRange = 0 +pp_data->cap[146]->IsAlias = 0 +pp_data->cap[146]->IsStringRange = 0 +pp_data->cap[146]->IsDesignatorRange = 0 +pp_data->cap[146]->Reserved1 = 0x000000 +pp_data->cap[146]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[146]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[146]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[146]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[146]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[146]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[146]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[146]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[146]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[146]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[146]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[146]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[146]->NotRange.Usage = 0x0081 +pp_data->cap[146]->NotRange.Reserved1 = 0x0081 +pp_data->cap[146]->NotRange.StringIndex = 0 +pp_data->cap[146]->NotRange.Reserved2 = 0 +pp_data->cap[146]->NotRange.DesignatorIndex = 0 +pp_data->cap[146]->NotRange.Reserved3 = 0 +pp_data->cap[146]->NotRange.DataIndex = 59 +pp_data->cap[146]->NotRange.Reserved4 = 59 +pp_data->cap[146]->NotButton.HasNull = 0 +pp_data->cap[146]->NotButton.Reserved4 = 0x000000 +pp_data->cap[146]->NotButton.LogicalMin = 0 +pp_data->cap[146]->NotButton.LogicalMax = 127 +pp_data->cap[146]->NotButton.PhysicalMin = 0 +pp_data->cap[146]->NotButton.PhysicalMax = 0 +pp_data->cap[146]->Units = 0 +pp_data->cap[146]->UnitsExp = 0 + +pp_data->cap[147]->UsagePage = 0xFF01 +pp_data->cap[147]->ReportID = 0x80 +pp_data->cap[147]->BitPosition = 0 +pp_data->cap[147]->BitSize = 8 +pp_data->cap[147]->ReportCount = 1 +pp_data->cap[147]->BytePosition = 0x0022 +pp_data->cap[147]->BitCount = 8 +pp_data->cap[147]->BitField = 0x02 +pp_data->cap[147]->NextBytePosition = 0x0023 +pp_data->cap[147]->LinkCollection = 0x0003 +pp_data->cap[147]->LinkUsagePage = 0xFF01 +pp_data->cap[147]->LinkUsage = 0x0080 +pp_data->cap[147]->IsMultipleItemsForArray = 0 +pp_data->cap[147]->IsButtonCap = 0 +pp_data->cap[147]->IsPadding = 0 +pp_data->cap[147]->IsAbsolute = 1 +pp_data->cap[147]->IsRange = 0 +pp_data->cap[147]->IsAlias = 0 +pp_data->cap[147]->IsStringRange = 0 +pp_data->cap[147]->IsDesignatorRange = 0 +pp_data->cap[147]->Reserved1 = 0x000000 +pp_data->cap[147]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[147]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[147]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[147]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[147]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[147]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[147]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[147]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[147]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[147]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[147]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[147]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[147]->NotRange.Usage = 0x0081 +pp_data->cap[147]->NotRange.Reserved1 = 0x0081 +pp_data->cap[147]->NotRange.StringIndex = 0 +pp_data->cap[147]->NotRange.Reserved2 = 0 +pp_data->cap[147]->NotRange.DesignatorIndex = 0 +pp_data->cap[147]->NotRange.Reserved3 = 0 +pp_data->cap[147]->NotRange.DataIndex = 60 +pp_data->cap[147]->NotRange.Reserved4 = 60 +pp_data->cap[147]->NotButton.HasNull = 0 +pp_data->cap[147]->NotButton.Reserved4 = 0x000000 +pp_data->cap[147]->NotButton.LogicalMin = 0 +pp_data->cap[147]->NotButton.LogicalMax = 127 +pp_data->cap[147]->NotButton.PhysicalMin = 0 +pp_data->cap[147]->NotButton.PhysicalMax = 0 +pp_data->cap[147]->Units = 0 +pp_data->cap[147]->UnitsExp = 0 + +pp_data->cap[148]->UsagePage = 0xFF01 +pp_data->cap[148]->ReportID = 0x80 +pp_data->cap[148]->BitPosition = 0 +pp_data->cap[148]->BitSize = 8 +pp_data->cap[148]->ReportCount = 1 +pp_data->cap[148]->BytePosition = 0x0021 +pp_data->cap[148]->BitCount = 8 +pp_data->cap[148]->BitField = 0x02 +pp_data->cap[148]->NextBytePosition = 0x0022 +pp_data->cap[148]->LinkCollection = 0x0003 +pp_data->cap[148]->LinkUsagePage = 0xFF01 +pp_data->cap[148]->LinkUsage = 0x0080 +pp_data->cap[148]->IsMultipleItemsForArray = 0 +pp_data->cap[148]->IsButtonCap = 0 +pp_data->cap[148]->IsPadding = 0 +pp_data->cap[148]->IsAbsolute = 1 +pp_data->cap[148]->IsRange = 0 +pp_data->cap[148]->IsAlias = 0 +pp_data->cap[148]->IsStringRange = 0 +pp_data->cap[148]->IsDesignatorRange = 0 +pp_data->cap[148]->Reserved1 = 0x000000 +pp_data->cap[148]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[148]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[148]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[148]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[148]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[148]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[148]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[148]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[148]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[148]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[148]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[148]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[148]->NotRange.Usage = 0x0081 +pp_data->cap[148]->NotRange.Reserved1 = 0x0081 +pp_data->cap[148]->NotRange.StringIndex = 0 +pp_data->cap[148]->NotRange.Reserved2 = 0 +pp_data->cap[148]->NotRange.DesignatorIndex = 0 +pp_data->cap[148]->NotRange.Reserved3 = 0 +pp_data->cap[148]->NotRange.DataIndex = 61 +pp_data->cap[148]->NotRange.Reserved4 = 61 +pp_data->cap[148]->NotButton.HasNull = 0 +pp_data->cap[148]->NotButton.Reserved4 = 0x000000 +pp_data->cap[148]->NotButton.LogicalMin = 0 +pp_data->cap[148]->NotButton.LogicalMax = 127 +pp_data->cap[148]->NotButton.PhysicalMin = 0 +pp_data->cap[148]->NotButton.PhysicalMax = 0 +pp_data->cap[148]->Units = 0 +pp_data->cap[148]->UnitsExp = 0 + +pp_data->cap[149]->UsagePage = 0xFF01 +pp_data->cap[149]->ReportID = 0x80 +pp_data->cap[149]->BitPosition = 0 +pp_data->cap[149]->BitSize = 8 +pp_data->cap[149]->ReportCount = 1 +pp_data->cap[149]->BytePosition = 0x0020 +pp_data->cap[149]->BitCount = 8 +pp_data->cap[149]->BitField = 0x02 +pp_data->cap[149]->NextBytePosition = 0x0021 +pp_data->cap[149]->LinkCollection = 0x0003 +pp_data->cap[149]->LinkUsagePage = 0xFF01 +pp_data->cap[149]->LinkUsage = 0x0080 +pp_data->cap[149]->IsMultipleItemsForArray = 0 +pp_data->cap[149]->IsButtonCap = 0 +pp_data->cap[149]->IsPadding = 0 +pp_data->cap[149]->IsAbsolute = 1 +pp_data->cap[149]->IsRange = 0 +pp_data->cap[149]->IsAlias = 0 +pp_data->cap[149]->IsStringRange = 0 +pp_data->cap[149]->IsDesignatorRange = 0 +pp_data->cap[149]->Reserved1 = 0x000000 +pp_data->cap[149]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[149]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[149]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[149]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[149]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[149]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[149]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[149]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[149]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[149]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[149]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[149]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[149]->NotRange.Usage = 0x0081 +pp_data->cap[149]->NotRange.Reserved1 = 0x0081 +pp_data->cap[149]->NotRange.StringIndex = 0 +pp_data->cap[149]->NotRange.Reserved2 = 0 +pp_data->cap[149]->NotRange.DesignatorIndex = 0 +pp_data->cap[149]->NotRange.Reserved3 = 0 +pp_data->cap[149]->NotRange.DataIndex = 62 +pp_data->cap[149]->NotRange.Reserved4 = 62 +pp_data->cap[149]->NotButton.HasNull = 0 +pp_data->cap[149]->NotButton.Reserved4 = 0x000000 +pp_data->cap[149]->NotButton.LogicalMin = 0 +pp_data->cap[149]->NotButton.LogicalMax = 127 +pp_data->cap[149]->NotButton.PhysicalMin = 0 +pp_data->cap[149]->NotButton.PhysicalMax = 0 +pp_data->cap[149]->Units = 0 +pp_data->cap[149]->UnitsExp = 0 + +pp_data->cap[150]->UsagePage = 0xFF01 +pp_data->cap[150]->ReportID = 0x80 +pp_data->cap[150]->BitPosition = 0 +pp_data->cap[150]->BitSize = 8 +pp_data->cap[150]->ReportCount = 1 +pp_data->cap[150]->BytePosition = 0x001F +pp_data->cap[150]->BitCount = 8 +pp_data->cap[150]->BitField = 0x02 +pp_data->cap[150]->NextBytePosition = 0x0020 +pp_data->cap[150]->LinkCollection = 0x0003 +pp_data->cap[150]->LinkUsagePage = 0xFF01 +pp_data->cap[150]->LinkUsage = 0x0080 +pp_data->cap[150]->IsMultipleItemsForArray = 0 +pp_data->cap[150]->IsButtonCap = 0 +pp_data->cap[150]->IsPadding = 0 +pp_data->cap[150]->IsAbsolute = 1 +pp_data->cap[150]->IsRange = 0 +pp_data->cap[150]->IsAlias = 0 +pp_data->cap[150]->IsStringRange = 0 +pp_data->cap[150]->IsDesignatorRange = 0 +pp_data->cap[150]->Reserved1 = 0x000000 +pp_data->cap[150]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[150]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[150]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[150]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[150]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[150]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[150]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[150]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[150]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[150]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[150]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[150]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[150]->NotRange.Usage = 0x0081 +pp_data->cap[150]->NotRange.Reserved1 = 0x0081 +pp_data->cap[150]->NotRange.StringIndex = 0 +pp_data->cap[150]->NotRange.Reserved2 = 0 +pp_data->cap[150]->NotRange.DesignatorIndex = 0 +pp_data->cap[150]->NotRange.Reserved3 = 0 +pp_data->cap[150]->NotRange.DataIndex = 63 +pp_data->cap[150]->NotRange.Reserved4 = 63 +pp_data->cap[150]->NotButton.HasNull = 0 +pp_data->cap[150]->NotButton.Reserved4 = 0x000000 +pp_data->cap[150]->NotButton.LogicalMin = 0 +pp_data->cap[150]->NotButton.LogicalMax = 127 +pp_data->cap[150]->NotButton.PhysicalMin = 0 +pp_data->cap[150]->NotButton.PhysicalMax = 0 +pp_data->cap[150]->Units = 0 +pp_data->cap[150]->UnitsExp = 0 + +pp_data->cap[151]->UsagePage = 0xFF01 +pp_data->cap[151]->ReportID = 0x80 +pp_data->cap[151]->BitPosition = 0 +pp_data->cap[151]->BitSize = 8 +pp_data->cap[151]->ReportCount = 1 +pp_data->cap[151]->BytePosition = 0x001E +pp_data->cap[151]->BitCount = 8 +pp_data->cap[151]->BitField = 0x02 +pp_data->cap[151]->NextBytePosition = 0x001F +pp_data->cap[151]->LinkCollection = 0x0003 +pp_data->cap[151]->LinkUsagePage = 0xFF01 +pp_data->cap[151]->LinkUsage = 0x0080 +pp_data->cap[151]->IsMultipleItemsForArray = 0 +pp_data->cap[151]->IsButtonCap = 0 +pp_data->cap[151]->IsPadding = 0 +pp_data->cap[151]->IsAbsolute = 1 +pp_data->cap[151]->IsRange = 0 +pp_data->cap[151]->IsAlias = 0 +pp_data->cap[151]->IsStringRange = 0 +pp_data->cap[151]->IsDesignatorRange = 0 +pp_data->cap[151]->Reserved1 = 0x000000 +pp_data->cap[151]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[151]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[151]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[151]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[151]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[151]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[151]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[151]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[151]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[151]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[151]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[151]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[151]->NotRange.Usage = 0x0081 +pp_data->cap[151]->NotRange.Reserved1 = 0x0081 +pp_data->cap[151]->NotRange.StringIndex = 0 +pp_data->cap[151]->NotRange.Reserved2 = 0 +pp_data->cap[151]->NotRange.DesignatorIndex = 0 +pp_data->cap[151]->NotRange.Reserved3 = 0 +pp_data->cap[151]->NotRange.DataIndex = 64 +pp_data->cap[151]->NotRange.Reserved4 = 64 +pp_data->cap[151]->NotButton.HasNull = 0 +pp_data->cap[151]->NotButton.Reserved4 = 0x000000 +pp_data->cap[151]->NotButton.LogicalMin = 0 +pp_data->cap[151]->NotButton.LogicalMax = 127 +pp_data->cap[151]->NotButton.PhysicalMin = 0 +pp_data->cap[151]->NotButton.PhysicalMax = 0 +pp_data->cap[151]->Units = 0 +pp_data->cap[151]->UnitsExp = 0 + +pp_data->cap[152]->UsagePage = 0xFF01 +pp_data->cap[152]->ReportID = 0x80 +pp_data->cap[152]->BitPosition = 0 +pp_data->cap[152]->BitSize = 8 +pp_data->cap[152]->ReportCount = 1 +pp_data->cap[152]->BytePosition = 0x001D +pp_data->cap[152]->BitCount = 8 +pp_data->cap[152]->BitField = 0x02 +pp_data->cap[152]->NextBytePosition = 0x001E +pp_data->cap[152]->LinkCollection = 0x0003 +pp_data->cap[152]->LinkUsagePage = 0xFF01 +pp_data->cap[152]->LinkUsage = 0x0080 +pp_data->cap[152]->IsMultipleItemsForArray = 0 +pp_data->cap[152]->IsButtonCap = 0 +pp_data->cap[152]->IsPadding = 0 +pp_data->cap[152]->IsAbsolute = 1 +pp_data->cap[152]->IsRange = 0 +pp_data->cap[152]->IsAlias = 0 +pp_data->cap[152]->IsStringRange = 0 +pp_data->cap[152]->IsDesignatorRange = 0 +pp_data->cap[152]->Reserved1 = 0x000000 +pp_data->cap[152]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[152]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[152]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[152]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[152]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[152]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[152]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[152]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[152]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[152]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[152]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[152]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[152]->NotRange.Usage = 0x0081 +pp_data->cap[152]->NotRange.Reserved1 = 0x0081 +pp_data->cap[152]->NotRange.StringIndex = 0 +pp_data->cap[152]->NotRange.Reserved2 = 0 +pp_data->cap[152]->NotRange.DesignatorIndex = 0 +pp_data->cap[152]->NotRange.Reserved3 = 0 +pp_data->cap[152]->NotRange.DataIndex = 65 +pp_data->cap[152]->NotRange.Reserved4 = 65 +pp_data->cap[152]->NotButton.HasNull = 0 +pp_data->cap[152]->NotButton.Reserved4 = 0x000000 +pp_data->cap[152]->NotButton.LogicalMin = 0 +pp_data->cap[152]->NotButton.LogicalMax = 127 +pp_data->cap[152]->NotButton.PhysicalMin = 0 +pp_data->cap[152]->NotButton.PhysicalMax = 0 +pp_data->cap[152]->Units = 0 +pp_data->cap[152]->UnitsExp = 0 + +pp_data->cap[153]->UsagePage = 0xFF01 +pp_data->cap[153]->ReportID = 0x80 +pp_data->cap[153]->BitPosition = 0 +pp_data->cap[153]->BitSize = 8 +pp_data->cap[153]->ReportCount = 1 +pp_data->cap[153]->BytePosition = 0x001C +pp_data->cap[153]->BitCount = 8 +pp_data->cap[153]->BitField = 0x02 +pp_data->cap[153]->NextBytePosition = 0x001D +pp_data->cap[153]->LinkCollection = 0x0003 +pp_data->cap[153]->LinkUsagePage = 0xFF01 +pp_data->cap[153]->LinkUsage = 0x0080 +pp_data->cap[153]->IsMultipleItemsForArray = 0 +pp_data->cap[153]->IsButtonCap = 0 +pp_data->cap[153]->IsPadding = 0 +pp_data->cap[153]->IsAbsolute = 1 +pp_data->cap[153]->IsRange = 0 +pp_data->cap[153]->IsAlias = 0 +pp_data->cap[153]->IsStringRange = 0 +pp_data->cap[153]->IsDesignatorRange = 0 +pp_data->cap[153]->Reserved1 = 0x000000 +pp_data->cap[153]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[153]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[153]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[153]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[153]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[153]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[153]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[153]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[153]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[153]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[153]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[153]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[153]->NotRange.Usage = 0x0081 +pp_data->cap[153]->NotRange.Reserved1 = 0x0081 +pp_data->cap[153]->NotRange.StringIndex = 0 +pp_data->cap[153]->NotRange.Reserved2 = 0 +pp_data->cap[153]->NotRange.DesignatorIndex = 0 +pp_data->cap[153]->NotRange.Reserved3 = 0 +pp_data->cap[153]->NotRange.DataIndex = 66 +pp_data->cap[153]->NotRange.Reserved4 = 66 +pp_data->cap[153]->NotButton.HasNull = 0 +pp_data->cap[153]->NotButton.Reserved4 = 0x000000 +pp_data->cap[153]->NotButton.LogicalMin = 0 +pp_data->cap[153]->NotButton.LogicalMax = 127 +pp_data->cap[153]->NotButton.PhysicalMin = 0 +pp_data->cap[153]->NotButton.PhysicalMax = 0 +pp_data->cap[153]->Units = 0 +pp_data->cap[153]->UnitsExp = 0 + +pp_data->cap[154]->UsagePage = 0xFF01 +pp_data->cap[154]->ReportID = 0x80 +pp_data->cap[154]->BitPosition = 0 +pp_data->cap[154]->BitSize = 8 +pp_data->cap[154]->ReportCount = 1 +pp_data->cap[154]->BytePosition = 0x001B +pp_data->cap[154]->BitCount = 8 +pp_data->cap[154]->BitField = 0x02 +pp_data->cap[154]->NextBytePosition = 0x001C +pp_data->cap[154]->LinkCollection = 0x0003 +pp_data->cap[154]->LinkUsagePage = 0xFF01 +pp_data->cap[154]->LinkUsage = 0x0080 +pp_data->cap[154]->IsMultipleItemsForArray = 0 +pp_data->cap[154]->IsButtonCap = 0 +pp_data->cap[154]->IsPadding = 0 +pp_data->cap[154]->IsAbsolute = 1 +pp_data->cap[154]->IsRange = 0 +pp_data->cap[154]->IsAlias = 0 +pp_data->cap[154]->IsStringRange = 0 +pp_data->cap[154]->IsDesignatorRange = 0 +pp_data->cap[154]->Reserved1 = 0x000000 +pp_data->cap[154]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[154]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[154]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[154]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[154]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[154]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[154]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[154]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[154]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[154]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[154]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[154]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[154]->NotRange.Usage = 0x0081 +pp_data->cap[154]->NotRange.Reserved1 = 0x0081 +pp_data->cap[154]->NotRange.StringIndex = 0 +pp_data->cap[154]->NotRange.Reserved2 = 0 +pp_data->cap[154]->NotRange.DesignatorIndex = 0 +pp_data->cap[154]->NotRange.Reserved3 = 0 +pp_data->cap[154]->NotRange.DataIndex = 67 +pp_data->cap[154]->NotRange.Reserved4 = 67 +pp_data->cap[154]->NotButton.HasNull = 0 +pp_data->cap[154]->NotButton.Reserved4 = 0x000000 +pp_data->cap[154]->NotButton.LogicalMin = 0 +pp_data->cap[154]->NotButton.LogicalMax = 127 +pp_data->cap[154]->NotButton.PhysicalMin = 0 +pp_data->cap[154]->NotButton.PhysicalMax = 0 +pp_data->cap[154]->Units = 0 +pp_data->cap[154]->UnitsExp = 0 + +pp_data->cap[155]->UsagePage = 0xFF01 +pp_data->cap[155]->ReportID = 0x80 +pp_data->cap[155]->BitPosition = 0 +pp_data->cap[155]->BitSize = 8 +pp_data->cap[155]->ReportCount = 1 +pp_data->cap[155]->BytePosition = 0x001A +pp_data->cap[155]->BitCount = 8 +pp_data->cap[155]->BitField = 0x02 +pp_data->cap[155]->NextBytePosition = 0x001B +pp_data->cap[155]->LinkCollection = 0x0003 +pp_data->cap[155]->LinkUsagePage = 0xFF01 +pp_data->cap[155]->LinkUsage = 0x0080 +pp_data->cap[155]->IsMultipleItemsForArray = 0 +pp_data->cap[155]->IsButtonCap = 0 +pp_data->cap[155]->IsPadding = 0 +pp_data->cap[155]->IsAbsolute = 1 +pp_data->cap[155]->IsRange = 0 +pp_data->cap[155]->IsAlias = 0 +pp_data->cap[155]->IsStringRange = 0 +pp_data->cap[155]->IsDesignatorRange = 0 +pp_data->cap[155]->Reserved1 = 0x000000 +pp_data->cap[155]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[155]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[155]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[155]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[155]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[155]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[155]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[155]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[155]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[155]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[155]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[155]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[155]->NotRange.Usage = 0x0081 +pp_data->cap[155]->NotRange.Reserved1 = 0x0081 +pp_data->cap[155]->NotRange.StringIndex = 0 +pp_data->cap[155]->NotRange.Reserved2 = 0 +pp_data->cap[155]->NotRange.DesignatorIndex = 0 +pp_data->cap[155]->NotRange.Reserved3 = 0 +pp_data->cap[155]->NotRange.DataIndex = 68 +pp_data->cap[155]->NotRange.Reserved4 = 68 +pp_data->cap[155]->NotButton.HasNull = 0 +pp_data->cap[155]->NotButton.Reserved4 = 0x000000 +pp_data->cap[155]->NotButton.LogicalMin = 0 +pp_data->cap[155]->NotButton.LogicalMax = 127 +pp_data->cap[155]->NotButton.PhysicalMin = 0 +pp_data->cap[155]->NotButton.PhysicalMax = 0 +pp_data->cap[155]->Units = 0 +pp_data->cap[155]->UnitsExp = 0 + +pp_data->cap[156]->UsagePage = 0xFF01 +pp_data->cap[156]->ReportID = 0x80 +pp_data->cap[156]->BitPosition = 0 +pp_data->cap[156]->BitSize = 8 +pp_data->cap[156]->ReportCount = 1 +pp_data->cap[156]->BytePosition = 0x0019 +pp_data->cap[156]->BitCount = 8 +pp_data->cap[156]->BitField = 0x02 +pp_data->cap[156]->NextBytePosition = 0x001A +pp_data->cap[156]->LinkCollection = 0x0003 +pp_data->cap[156]->LinkUsagePage = 0xFF01 +pp_data->cap[156]->LinkUsage = 0x0080 +pp_data->cap[156]->IsMultipleItemsForArray = 0 +pp_data->cap[156]->IsButtonCap = 0 +pp_data->cap[156]->IsPadding = 0 +pp_data->cap[156]->IsAbsolute = 1 +pp_data->cap[156]->IsRange = 0 +pp_data->cap[156]->IsAlias = 0 +pp_data->cap[156]->IsStringRange = 0 +pp_data->cap[156]->IsDesignatorRange = 0 +pp_data->cap[156]->Reserved1 = 0x000000 +pp_data->cap[156]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[156]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[156]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[156]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[156]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[156]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[156]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[156]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[156]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[156]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[156]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[156]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[156]->NotRange.Usage = 0x0081 +pp_data->cap[156]->NotRange.Reserved1 = 0x0081 +pp_data->cap[156]->NotRange.StringIndex = 0 +pp_data->cap[156]->NotRange.Reserved2 = 0 +pp_data->cap[156]->NotRange.DesignatorIndex = 0 +pp_data->cap[156]->NotRange.Reserved3 = 0 +pp_data->cap[156]->NotRange.DataIndex = 69 +pp_data->cap[156]->NotRange.Reserved4 = 69 +pp_data->cap[156]->NotButton.HasNull = 0 +pp_data->cap[156]->NotButton.Reserved4 = 0x000000 +pp_data->cap[156]->NotButton.LogicalMin = 0 +pp_data->cap[156]->NotButton.LogicalMax = 127 +pp_data->cap[156]->NotButton.PhysicalMin = 0 +pp_data->cap[156]->NotButton.PhysicalMax = 0 +pp_data->cap[156]->Units = 0 +pp_data->cap[156]->UnitsExp = 0 + +pp_data->cap[157]->UsagePage = 0xFF01 +pp_data->cap[157]->ReportID = 0x80 +pp_data->cap[157]->BitPosition = 0 +pp_data->cap[157]->BitSize = 8 +pp_data->cap[157]->ReportCount = 1 +pp_data->cap[157]->BytePosition = 0x0018 +pp_data->cap[157]->BitCount = 8 +pp_data->cap[157]->BitField = 0x02 +pp_data->cap[157]->NextBytePosition = 0x0019 +pp_data->cap[157]->LinkCollection = 0x0003 +pp_data->cap[157]->LinkUsagePage = 0xFF01 +pp_data->cap[157]->LinkUsage = 0x0080 +pp_data->cap[157]->IsMultipleItemsForArray = 0 +pp_data->cap[157]->IsButtonCap = 0 +pp_data->cap[157]->IsPadding = 0 +pp_data->cap[157]->IsAbsolute = 1 +pp_data->cap[157]->IsRange = 0 +pp_data->cap[157]->IsAlias = 0 +pp_data->cap[157]->IsStringRange = 0 +pp_data->cap[157]->IsDesignatorRange = 0 +pp_data->cap[157]->Reserved1 = 0x000000 +pp_data->cap[157]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[157]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[157]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[157]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[157]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[157]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[157]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[157]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[157]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[157]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[157]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[157]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[157]->NotRange.Usage = 0x0081 +pp_data->cap[157]->NotRange.Reserved1 = 0x0081 +pp_data->cap[157]->NotRange.StringIndex = 0 +pp_data->cap[157]->NotRange.Reserved2 = 0 +pp_data->cap[157]->NotRange.DesignatorIndex = 0 +pp_data->cap[157]->NotRange.Reserved3 = 0 +pp_data->cap[157]->NotRange.DataIndex = 70 +pp_data->cap[157]->NotRange.Reserved4 = 70 +pp_data->cap[157]->NotButton.HasNull = 0 +pp_data->cap[157]->NotButton.Reserved4 = 0x000000 +pp_data->cap[157]->NotButton.LogicalMin = 0 +pp_data->cap[157]->NotButton.LogicalMax = 127 +pp_data->cap[157]->NotButton.PhysicalMin = 0 +pp_data->cap[157]->NotButton.PhysicalMax = 0 +pp_data->cap[157]->Units = 0 +pp_data->cap[157]->UnitsExp = 0 + +pp_data->cap[158]->UsagePage = 0xFF01 +pp_data->cap[158]->ReportID = 0x80 +pp_data->cap[158]->BitPosition = 0 +pp_data->cap[158]->BitSize = 8 +pp_data->cap[158]->ReportCount = 1 +pp_data->cap[158]->BytePosition = 0x0017 +pp_data->cap[158]->BitCount = 8 +pp_data->cap[158]->BitField = 0x02 +pp_data->cap[158]->NextBytePosition = 0x0018 +pp_data->cap[158]->LinkCollection = 0x0003 +pp_data->cap[158]->LinkUsagePage = 0xFF01 +pp_data->cap[158]->LinkUsage = 0x0080 +pp_data->cap[158]->IsMultipleItemsForArray = 0 +pp_data->cap[158]->IsButtonCap = 0 +pp_data->cap[158]->IsPadding = 0 +pp_data->cap[158]->IsAbsolute = 1 +pp_data->cap[158]->IsRange = 0 +pp_data->cap[158]->IsAlias = 0 +pp_data->cap[158]->IsStringRange = 0 +pp_data->cap[158]->IsDesignatorRange = 0 +pp_data->cap[158]->Reserved1 = 0x000000 +pp_data->cap[158]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[158]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[158]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[158]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[158]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[158]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[158]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[158]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[158]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[158]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[158]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[158]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[158]->NotRange.Usage = 0x0081 +pp_data->cap[158]->NotRange.Reserved1 = 0x0081 +pp_data->cap[158]->NotRange.StringIndex = 0 +pp_data->cap[158]->NotRange.Reserved2 = 0 +pp_data->cap[158]->NotRange.DesignatorIndex = 0 +pp_data->cap[158]->NotRange.Reserved3 = 0 +pp_data->cap[158]->NotRange.DataIndex = 71 +pp_data->cap[158]->NotRange.Reserved4 = 71 +pp_data->cap[158]->NotButton.HasNull = 0 +pp_data->cap[158]->NotButton.Reserved4 = 0x000000 +pp_data->cap[158]->NotButton.LogicalMin = 0 +pp_data->cap[158]->NotButton.LogicalMax = 127 +pp_data->cap[158]->NotButton.PhysicalMin = 0 +pp_data->cap[158]->NotButton.PhysicalMax = 0 +pp_data->cap[158]->Units = 0 +pp_data->cap[158]->UnitsExp = 0 + +pp_data->cap[159]->UsagePage = 0xFF01 +pp_data->cap[159]->ReportID = 0x80 +pp_data->cap[159]->BitPosition = 0 +pp_data->cap[159]->BitSize = 8 +pp_data->cap[159]->ReportCount = 1 +pp_data->cap[159]->BytePosition = 0x0016 +pp_data->cap[159]->BitCount = 8 +pp_data->cap[159]->BitField = 0x02 +pp_data->cap[159]->NextBytePosition = 0x0017 +pp_data->cap[159]->LinkCollection = 0x0003 +pp_data->cap[159]->LinkUsagePage = 0xFF01 +pp_data->cap[159]->LinkUsage = 0x0080 +pp_data->cap[159]->IsMultipleItemsForArray = 0 +pp_data->cap[159]->IsButtonCap = 0 +pp_data->cap[159]->IsPadding = 0 +pp_data->cap[159]->IsAbsolute = 1 +pp_data->cap[159]->IsRange = 0 +pp_data->cap[159]->IsAlias = 0 +pp_data->cap[159]->IsStringRange = 0 +pp_data->cap[159]->IsDesignatorRange = 0 +pp_data->cap[159]->Reserved1 = 0x000000 +pp_data->cap[159]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[159]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[159]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[159]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[159]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[159]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[159]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[159]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[159]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[159]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[159]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[159]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[159]->NotRange.Usage = 0x0081 +pp_data->cap[159]->NotRange.Reserved1 = 0x0081 +pp_data->cap[159]->NotRange.StringIndex = 0 +pp_data->cap[159]->NotRange.Reserved2 = 0 +pp_data->cap[159]->NotRange.DesignatorIndex = 0 +pp_data->cap[159]->NotRange.Reserved3 = 0 +pp_data->cap[159]->NotRange.DataIndex = 72 +pp_data->cap[159]->NotRange.Reserved4 = 72 +pp_data->cap[159]->NotButton.HasNull = 0 +pp_data->cap[159]->NotButton.Reserved4 = 0x000000 +pp_data->cap[159]->NotButton.LogicalMin = 0 +pp_data->cap[159]->NotButton.LogicalMax = 127 +pp_data->cap[159]->NotButton.PhysicalMin = 0 +pp_data->cap[159]->NotButton.PhysicalMax = 0 +pp_data->cap[159]->Units = 0 +pp_data->cap[159]->UnitsExp = 0 + +pp_data->cap[160]->UsagePage = 0xFF01 +pp_data->cap[160]->ReportID = 0x80 +pp_data->cap[160]->BitPosition = 0 +pp_data->cap[160]->BitSize = 8 +pp_data->cap[160]->ReportCount = 1 +pp_data->cap[160]->BytePosition = 0x0015 +pp_data->cap[160]->BitCount = 8 +pp_data->cap[160]->BitField = 0x02 +pp_data->cap[160]->NextBytePosition = 0x0016 +pp_data->cap[160]->LinkCollection = 0x0003 +pp_data->cap[160]->LinkUsagePage = 0xFF01 +pp_data->cap[160]->LinkUsage = 0x0080 +pp_data->cap[160]->IsMultipleItemsForArray = 0 +pp_data->cap[160]->IsButtonCap = 0 +pp_data->cap[160]->IsPadding = 0 +pp_data->cap[160]->IsAbsolute = 1 +pp_data->cap[160]->IsRange = 0 +pp_data->cap[160]->IsAlias = 0 +pp_data->cap[160]->IsStringRange = 0 +pp_data->cap[160]->IsDesignatorRange = 0 +pp_data->cap[160]->Reserved1 = 0x000000 +pp_data->cap[160]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[160]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[160]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[160]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[160]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[160]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[160]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[160]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[160]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[160]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[160]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[160]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[160]->NotRange.Usage = 0x0081 +pp_data->cap[160]->NotRange.Reserved1 = 0x0081 +pp_data->cap[160]->NotRange.StringIndex = 0 +pp_data->cap[160]->NotRange.Reserved2 = 0 +pp_data->cap[160]->NotRange.DesignatorIndex = 0 +pp_data->cap[160]->NotRange.Reserved3 = 0 +pp_data->cap[160]->NotRange.DataIndex = 73 +pp_data->cap[160]->NotRange.Reserved4 = 73 +pp_data->cap[160]->NotButton.HasNull = 0 +pp_data->cap[160]->NotButton.Reserved4 = 0x000000 +pp_data->cap[160]->NotButton.LogicalMin = 0 +pp_data->cap[160]->NotButton.LogicalMax = 127 +pp_data->cap[160]->NotButton.PhysicalMin = 0 +pp_data->cap[160]->NotButton.PhysicalMax = 0 +pp_data->cap[160]->Units = 0 +pp_data->cap[160]->UnitsExp = 0 + +pp_data->cap[161]->UsagePage = 0xFF01 +pp_data->cap[161]->ReportID = 0x80 +pp_data->cap[161]->BitPosition = 0 +pp_data->cap[161]->BitSize = 8 +pp_data->cap[161]->ReportCount = 1 +pp_data->cap[161]->BytePosition = 0x0014 +pp_data->cap[161]->BitCount = 8 +pp_data->cap[161]->BitField = 0x02 +pp_data->cap[161]->NextBytePosition = 0x0015 +pp_data->cap[161]->LinkCollection = 0x0003 +pp_data->cap[161]->LinkUsagePage = 0xFF01 +pp_data->cap[161]->LinkUsage = 0x0080 +pp_data->cap[161]->IsMultipleItemsForArray = 0 +pp_data->cap[161]->IsButtonCap = 0 +pp_data->cap[161]->IsPadding = 0 +pp_data->cap[161]->IsAbsolute = 1 +pp_data->cap[161]->IsRange = 0 +pp_data->cap[161]->IsAlias = 0 +pp_data->cap[161]->IsStringRange = 0 +pp_data->cap[161]->IsDesignatorRange = 0 +pp_data->cap[161]->Reserved1 = 0x000000 +pp_data->cap[161]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[161]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[161]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[161]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[161]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[161]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[161]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[161]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[161]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[161]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[161]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[161]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[161]->NotRange.Usage = 0x0081 +pp_data->cap[161]->NotRange.Reserved1 = 0x0081 +pp_data->cap[161]->NotRange.StringIndex = 0 +pp_data->cap[161]->NotRange.Reserved2 = 0 +pp_data->cap[161]->NotRange.DesignatorIndex = 0 +pp_data->cap[161]->NotRange.Reserved3 = 0 +pp_data->cap[161]->NotRange.DataIndex = 74 +pp_data->cap[161]->NotRange.Reserved4 = 74 +pp_data->cap[161]->NotButton.HasNull = 0 +pp_data->cap[161]->NotButton.Reserved4 = 0x000000 +pp_data->cap[161]->NotButton.LogicalMin = 0 +pp_data->cap[161]->NotButton.LogicalMax = 127 +pp_data->cap[161]->NotButton.PhysicalMin = 0 +pp_data->cap[161]->NotButton.PhysicalMax = 0 +pp_data->cap[161]->Units = 0 +pp_data->cap[161]->UnitsExp = 0 + +pp_data->cap[162]->UsagePage = 0xFF01 +pp_data->cap[162]->ReportID = 0x80 +pp_data->cap[162]->BitPosition = 0 +pp_data->cap[162]->BitSize = 8 +pp_data->cap[162]->ReportCount = 1 +pp_data->cap[162]->BytePosition = 0x0013 +pp_data->cap[162]->BitCount = 8 +pp_data->cap[162]->BitField = 0x02 +pp_data->cap[162]->NextBytePosition = 0x0014 +pp_data->cap[162]->LinkCollection = 0x0003 +pp_data->cap[162]->LinkUsagePage = 0xFF01 +pp_data->cap[162]->LinkUsage = 0x0080 +pp_data->cap[162]->IsMultipleItemsForArray = 0 +pp_data->cap[162]->IsButtonCap = 0 +pp_data->cap[162]->IsPadding = 0 +pp_data->cap[162]->IsAbsolute = 1 +pp_data->cap[162]->IsRange = 0 +pp_data->cap[162]->IsAlias = 0 +pp_data->cap[162]->IsStringRange = 0 +pp_data->cap[162]->IsDesignatorRange = 0 +pp_data->cap[162]->Reserved1 = 0x000000 +pp_data->cap[162]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[162]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[162]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[162]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[162]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[162]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[162]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[162]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[162]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[162]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[162]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[162]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[162]->NotRange.Usage = 0x0081 +pp_data->cap[162]->NotRange.Reserved1 = 0x0081 +pp_data->cap[162]->NotRange.StringIndex = 0 +pp_data->cap[162]->NotRange.Reserved2 = 0 +pp_data->cap[162]->NotRange.DesignatorIndex = 0 +pp_data->cap[162]->NotRange.Reserved3 = 0 +pp_data->cap[162]->NotRange.DataIndex = 75 +pp_data->cap[162]->NotRange.Reserved4 = 75 +pp_data->cap[162]->NotButton.HasNull = 0 +pp_data->cap[162]->NotButton.Reserved4 = 0x000000 +pp_data->cap[162]->NotButton.LogicalMin = 0 +pp_data->cap[162]->NotButton.LogicalMax = 127 +pp_data->cap[162]->NotButton.PhysicalMin = 0 +pp_data->cap[162]->NotButton.PhysicalMax = 0 +pp_data->cap[162]->Units = 0 +pp_data->cap[162]->UnitsExp = 0 + +pp_data->cap[163]->UsagePage = 0xFF01 +pp_data->cap[163]->ReportID = 0x80 +pp_data->cap[163]->BitPosition = 0 +pp_data->cap[163]->BitSize = 8 +pp_data->cap[163]->ReportCount = 1 +pp_data->cap[163]->BytePosition = 0x0012 +pp_data->cap[163]->BitCount = 8 +pp_data->cap[163]->BitField = 0x02 +pp_data->cap[163]->NextBytePosition = 0x0013 +pp_data->cap[163]->LinkCollection = 0x0003 +pp_data->cap[163]->LinkUsagePage = 0xFF01 +pp_data->cap[163]->LinkUsage = 0x0080 +pp_data->cap[163]->IsMultipleItemsForArray = 0 +pp_data->cap[163]->IsButtonCap = 0 +pp_data->cap[163]->IsPadding = 0 +pp_data->cap[163]->IsAbsolute = 1 +pp_data->cap[163]->IsRange = 0 +pp_data->cap[163]->IsAlias = 0 +pp_data->cap[163]->IsStringRange = 0 +pp_data->cap[163]->IsDesignatorRange = 0 +pp_data->cap[163]->Reserved1 = 0x000000 +pp_data->cap[163]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[163]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[163]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[163]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[163]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[163]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[163]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[163]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[163]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[163]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[163]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[163]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[163]->NotRange.Usage = 0x0081 +pp_data->cap[163]->NotRange.Reserved1 = 0x0081 +pp_data->cap[163]->NotRange.StringIndex = 0 +pp_data->cap[163]->NotRange.Reserved2 = 0 +pp_data->cap[163]->NotRange.DesignatorIndex = 0 +pp_data->cap[163]->NotRange.Reserved3 = 0 +pp_data->cap[163]->NotRange.DataIndex = 76 +pp_data->cap[163]->NotRange.Reserved4 = 76 +pp_data->cap[163]->NotButton.HasNull = 0 +pp_data->cap[163]->NotButton.Reserved4 = 0x000000 +pp_data->cap[163]->NotButton.LogicalMin = 0 +pp_data->cap[163]->NotButton.LogicalMax = 127 +pp_data->cap[163]->NotButton.PhysicalMin = 0 +pp_data->cap[163]->NotButton.PhysicalMax = 0 +pp_data->cap[163]->Units = 0 +pp_data->cap[163]->UnitsExp = 0 + +pp_data->cap[164]->UsagePage = 0xFF01 +pp_data->cap[164]->ReportID = 0x80 +pp_data->cap[164]->BitPosition = 0 +pp_data->cap[164]->BitSize = 8 +pp_data->cap[164]->ReportCount = 1 +pp_data->cap[164]->BytePosition = 0x0011 +pp_data->cap[164]->BitCount = 8 +pp_data->cap[164]->BitField = 0x02 +pp_data->cap[164]->NextBytePosition = 0x0012 +pp_data->cap[164]->LinkCollection = 0x0003 +pp_data->cap[164]->LinkUsagePage = 0xFF01 +pp_data->cap[164]->LinkUsage = 0x0080 +pp_data->cap[164]->IsMultipleItemsForArray = 0 +pp_data->cap[164]->IsButtonCap = 0 +pp_data->cap[164]->IsPadding = 0 +pp_data->cap[164]->IsAbsolute = 1 +pp_data->cap[164]->IsRange = 0 +pp_data->cap[164]->IsAlias = 0 +pp_data->cap[164]->IsStringRange = 0 +pp_data->cap[164]->IsDesignatorRange = 0 +pp_data->cap[164]->Reserved1 = 0x000000 +pp_data->cap[164]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[164]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[164]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[164]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[164]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[164]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[164]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[164]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[164]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[164]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[164]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[164]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[164]->NotRange.Usage = 0x0081 +pp_data->cap[164]->NotRange.Reserved1 = 0x0081 +pp_data->cap[164]->NotRange.StringIndex = 0 +pp_data->cap[164]->NotRange.Reserved2 = 0 +pp_data->cap[164]->NotRange.DesignatorIndex = 0 +pp_data->cap[164]->NotRange.Reserved3 = 0 +pp_data->cap[164]->NotRange.DataIndex = 77 +pp_data->cap[164]->NotRange.Reserved4 = 77 +pp_data->cap[164]->NotButton.HasNull = 0 +pp_data->cap[164]->NotButton.Reserved4 = 0x000000 +pp_data->cap[164]->NotButton.LogicalMin = 0 +pp_data->cap[164]->NotButton.LogicalMax = 127 +pp_data->cap[164]->NotButton.PhysicalMin = 0 +pp_data->cap[164]->NotButton.PhysicalMax = 0 +pp_data->cap[164]->Units = 0 +pp_data->cap[164]->UnitsExp = 0 + +pp_data->cap[165]->UsagePage = 0xFF01 +pp_data->cap[165]->ReportID = 0x80 +pp_data->cap[165]->BitPosition = 0 +pp_data->cap[165]->BitSize = 8 +pp_data->cap[165]->ReportCount = 1 +pp_data->cap[165]->BytePosition = 0x0010 +pp_data->cap[165]->BitCount = 8 +pp_data->cap[165]->BitField = 0x02 +pp_data->cap[165]->NextBytePosition = 0x0011 +pp_data->cap[165]->LinkCollection = 0x0003 +pp_data->cap[165]->LinkUsagePage = 0xFF01 +pp_data->cap[165]->LinkUsage = 0x0080 +pp_data->cap[165]->IsMultipleItemsForArray = 0 +pp_data->cap[165]->IsButtonCap = 0 +pp_data->cap[165]->IsPadding = 0 +pp_data->cap[165]->IsAbsolute = 1 +pp_data->cap[165]->IsRange = 0 +pp_data->cap[165]->IsAlias = 0 +pp_data->cap[165]->IsStringRange = 0 +pp_data->cap[165]->IsDesignatorRange = 0 +pp_data->cap[165]->Reserved1 = 0x000000 +pp_data->cap[165]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[165]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[165]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[165]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[165]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[165]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[165]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[165]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[165]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[165]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[165]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[165]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[165]->NotRange.Usage = 0x0081 +pp_data->cap[165]->NotRange.Reserved1 = 0x0081 +pp_data->cap[165]->NotRange.StringIndex = 0 +pp_data->cap[165]->NotRange.Reserved2 = 0 +pp_data->cap[165]->NotRange.DesignatorIndex = 0 +pp_data->cap[165]->NotRange.Reserved3 = 0 +pp_data->cap[165]->NotRange.DataIndex = 78 +pp_data->cap[165]->NotRange.Reserved4 = 78 +pp_data->cap[165]->NotButton.HasNull = 0 +pp_data->cap[165]->NotButton.Reserved4 = 0x000000 +pp_data->cap[165]->NotButton.LogicalMin = 0 +pp_data->cap[165]->NotButton.LogicalMax = 127 +pp_data->cap[165]->NotButton.PhysicalMin = 0 +pp_data->cap[165]->NotButton.PhysicalMax = 0 +pp_data->cap[165]->Units = 0 +pp_data->cap[165]->UnitsExp = 0 + +pp_data->cap[166]->UsagePage = 0xFF01 +pp_data->cap[166]->ReportID = 0x80 +pp_data->cap[166]->BitPosition = 0 +pp_data->cap[166]->BitSize = 8 +pp_data->cap[166]->ReportCount = 1 +pp_data->cap[166]->BytePosition = 0x000F +pp_data->cap[166]->BitCount = 8 +pp_data->cap[166]->BitField = 0x02 +pp_data->cap[166]->NextBytePosition = 0x0010 +pp_data->cap[166]->LinkCollection = 0x0003 +pp_data->cap[166]->LinkUsagePage = 0xFF01 +pp_data->cap[166]->LinkUsage = 0x0080 +pp_data->cap[166]->IsMultipleItemsForArray = 0 +pp_data->cap[166]->IsButtonCap = 0 +pp_data->cap[166]->IsPadding = 0 +pp_data->cap[166]->IsAbsolute = 1 +pp_data->cap[166]->IsRange = 0 +pp_data->cap[166]->IsAlias = 0 +pp_data->cap[166]->IsStringRange = 0 +pp_data->cap[166]->IsDesignatorRange = 0 +pp_data->cap[166]->Reserved1 = 0x000000 +pp_data->cap[166]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[166]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[166]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[166]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[166]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[166]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[166]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[166]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[166]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[166]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[166]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[166]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[166]->NotRange.Usage = 0x0081 +pp_data->cap[166]->NotRange.Reserved1 = 0x0081 +pp_data->cap[166]->NotRange.StringIndex = 0 +pp_data->cap[166]->NotRange.Reserved2 = 0 +pp_data->cap[166]->NotRange.DesignatorIndex = 0 +pp_data->cap[166]->NotRange.Reserved3 = 0 +pp_data->cap[166]->NotRange.DataIndex = 79 +pp_data->cap[166]->NotRange.Reserved4 = 79 +pp_data->cap[166]->NotButton.HasNull = 0 +pp_data->cap[166]->NotButton.Reserved4 = 0x000000 +pp_data->cap[166]->NotButton.LogicalMin = 0 +pp_data->cap[166]->NotButton.LogicalMax = 127 +pp_data->cap[166]->NotButton.PhysicalMin = 0 +pp_data->cap[166]->NotButton.PhysicalMax = 0 +pp_data->cap[166]->Units = 0 +pp_data->cap[166]->UnitsExp = 0 + +pp_data->cap[167]->UsagePage = 0xFF01 +pp_data->cap[167]->ReportID = 0x80 +pp_data->cap[167]->BitPosition = 0 +pp_data->cap[167]->BitSize = 8 +pp_data->cap[167]->ReportCount = 1 +pp_data->cap[167]->BytePosition = 0x000E +pp_data->cap[167]->BitCount = 8 +pp_data->cap[167]->BitField = 0x02 +pp_data->cap[167]->NextBytePosition = 0x000F +pp_data->cap[167]->LinkCollection = 0x0003 +pp_data->cap[167]->LinkUsagePage = 0xFF01 +pp_data->cap[167]->LinkUsage = 0x0080 +pp_data->cap[167]->IsMultipleItemsForArray = 0 +pp_data->cap[167]->IsButtonCap = 0 +pp_data->cap[167]->IsPadding = 0 +pp_data->cap[167]->IsAbsolute = 1 +pp_data->cap[167]->IsRange = 0 +pp_data->cap[167]->IsAlias = 0 +pp_data->cap[167]->IsStringRange = 0 +pp_data->cap[167]->IsDesignatorRange = 0 +pp_data->cap[167]->Reserved1 = 0x000000 +pp_data->cap[167]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[167]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[167]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[167]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[167]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[167]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[167]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[167]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[167]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[167]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[167]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[167]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[167]->NotRange.Usage = 0x0081 +pp_data->cap[167]->NotRange.Reserved1 = 0x0081 +pp_data->cap[167]->NotRange.StringIndex = 0 +pp_data->cap[167]->NotRange.Reserved2 = 0 +pp_data->cap[167]->NotRange.DesignatorIndex = 0 +pp_data->cap[167]->NotRange.Reserved3 = 0 +pp_data->cap[167]->NotRange.DataIndex = 80 +pp_data->cap[167]->NotRange.Reserved4 = 80 +pp_data->cap[167]->NotButton.HasNull = 0 +pp_data->cap[167]->NotButton.Reserved4 = 0x000000 +pp_data->cap[167]->NotButton.LogicalMin = 0 +pp_data->cap[167]->NotButton.LogicalMax = 127 +pp_data->cap[167]->NotButton.PhysicalMin = 0 +pp_data->cap[167]->NotButton.PhysicalMax = 0 +pp_data->cap[167]->Units = 0 +pp_data->cap[167]->UnitsExp = 0 + +pp_data->cap[168]->UsagePage = 0xFF01 +pp_data->cap[168]->ReportID = 0x80 +pp_data->cap[168]->BitPosition = 0 +pp_data->cap[168]->BitSize = 8 +pp_data->cap[168]->ReportCount = 1 +pp_data->cap[168]->BytePosition = 0x000D +pp_data->cap[168]->BitCount = 8 +pp_data->cap[168]->BitField = 0x02 +pp_data->cap[168]->NextBytePosition = 0x000E +pp_data->cap[168]->LinkCollection = 0x0003 +pp_data->cap[168]->LinkUsagePage = 0xFF01 +pp_data->cap[168]->LinkUsage = 0x0080 +pp_data->cap[168]->IsMultipleItemsForArray = 0 +pp_data->cap[168]->IsButtonCap = 0 +pp_data->cap[168]->IsPadding = 0 +pp_data->cap[168]->IsAbsolute = 1 +pp_data->cap[168]->IsRange = 0 +pp_data->cap[168]->IsAlias = 0 +pp_data->cap[168]->IsStringRange = 0 +pp_data->cap[168]->IsDesignatorRange = 0 +pp_data->cap[168]->Reserved1 = 0x000000 +pp_data->cap[168]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[168]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[168]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[168]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[168]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[168]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[168]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[168]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[168]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[168]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[168]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[168]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[168]->NotRange.Usage = 0x0081 +pp_data->cap[168]->NotRange.Reserved1 = 0x0081 +pp_data->cap[168]->NotRange.StringIndex = 0 +pp_data->cap[168]->NotRange.Reserved2 = 0 +pp_data->cap[168]->NotRange.DesignatorIndex = 0 +pp_data->cap[168]->NotRange.Reserved3 = 0 +pp_data->cap[168]->NotRange.DataIndex = 81 +pp_data->cap[168]->NotRange.Reserved4 = 81 +pp_data->cap[168]->NotButton.HasNull = 0 +pp_data->cap[168]->NotButton.Reserved4 = 0x000000 +pp_data->cap[168]->NotButton.LogicalMin = 0 +pp_data->cap[168]->NotButton.LogicalMax = 127 +pp_data->cap[168]->NotButton.PhysicalMin = 0 +pp_data->cap[168]->NotButton.PhysicalMax = 0 +pp_data->cap[168]->Units = 0 +pp_data->cap[168]->UnitsExp = 0 + +pp_data->cap[169]->UsagePage = 0xFF01 +pp_data->cap[169]->ReportID = 0x80 +pp_data->cap[169]->BitPosition = 0 +pp_data->cap[169]->BitSize = 8 +pp_data->cap[169]->ReportCount = 1 +pp_data->cap[169]->BytePosition = 0x000C +pp_data->cap[169]->BitCount = 8 +pp_data->cap[169]->BitField = 0x02 +pp_data->cap[169]->NextBytePosition = 0x000D +pp_data->cap[169]->LinkCollection = 0x0003 +pp_data->cap[169]->LinkUsagePage = 0xFF01 +pp_data->cap[169]->LinkUsage = 0x0080 +pp_data->cap[169]->IsMultipleItemsForArray = 0 +pp_data->cap[169]->IsButtonCap = 0 +pp_data->cap[169]->IsPadding = 0 +pp_data->cap[169]->IsAbsolute = 1 +pp_data->cap[169]->IsRange = 0 +pp_data->cap[169]->IsAlias = 0 +pp_data->cap[169]->IsStringRange = 0 +pp_data->cap[169]->IsDesignatorRange = 0 +pp_data->cap[169]->Reserved1 = 0x000000 +pp_data->cap[169]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[169]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[169]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[169]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[169]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[169]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[169]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[169]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[169]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[169]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[169]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[169]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[169]->NotRange.Usage = 0x0081 +pp_data->cap[169]->NotRange.Reserved1 = 0x0081 +pp_data->cap[169]->NotRange.StringIndex = 0 +pp_data->cap[169]->NotRange.Reserved2 = 0 +pp_data->cap[169]->NotRange.DesignatorIndex = 0 +pp_data->cap[169]->NotRange.Reserved3 = 0 +pp_data->cap[169]->NotRange.DataIndex = 82 +pp_data->cap[169]->NotRange.Reserved4 = 82 +pp_data->cap[169]->NotButton.HasNull = 0 +pp_data->cap[169]->NotButton.Reserved4 = 0x000000 +pp_data->cap[169]->NotButton.LogicalMin = 0 +pp_data->cap[169]->NotButton.LogicalMax = 127 +pp_data->cap[169]->NotButton.PhysicalMin = 0 +pp_data->cap[169]->NotButton.PhysicalMax = 0 +pp_data->cap[169]->Units = 0 +pp_data->cap[169]->UnitsExp = 0 + +pp_data->cap[170]->UsagePage = 0xFF01 +pp_data->cap[170]->ReportID = 0x80 +pp_data->cap[170]->BitPosition = 0 +pp_data->cap[170]->BitSize = 8 +pp_data->cap[170]->ReportCount = 1 +pp_data->cap[170]->BytePosition = 0x000B +pp_data->cap[170]->BitCount = 8 +pp_data->cap[170]->BitField = 0x02 +pp_data->cap[170]->NextBytePosition = 0x000C +pp_data->cap[170]->LinkCollection = 0x0003 +pp_data->cap[170]->LinkUsagePage = 0xFF01 +pp_data->cap[170]->LinkUsage = 0x0080 +pp_data->cap[170]->IsMultipleItemsForArray = 0 +pp_data->cap[170]->IsButtonCap = 0 +pp_data->cap[170]->IsPadding = 0 +pp_data->cap[170]->IsAbsolute = 1 +pp_data->cap[170]->IsRange = 0 +pp_data->cap[170]->IsAlias = 0 +pp_data->cap[170]->IsStringRange = 0 +pp_data->cap[170]->IsDesignatorRange = 0 +pp_data->cap[170]->Reserved1 = 0x000000 +pp_data->cap[170]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[170]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[170]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[170]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[170]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[170]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[170]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[170]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[170]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[170]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[170]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[170]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[170]->NotRange.Usage = 0x0081 +pp_data->cap[170]->NotRange.Reserved1 = 0x0081 +pp_data->cap[170]->NotRange.StringIndex = 0 +pp_data->cap[170]->NotRange.Reserved2 = 0 +pp_data->cap[170]->NotRange.DesignatorIndex = 0 +pp_data->cap[170]->NotRange.Reserved3 = 0 +pp_data->cap[170]->NotRange.DataIndex = 83 +pp_data->cap[170]->NotRange.Reserved4 = 83 +pp_data->cap[170]->NotButton.HasNull = 0 +pp_data->cap[170]->NotButton.Reserved4 = 0x000000 +pp_data->cap[170]->NotButton.LogicalMin = 0 +pp_data->cap[170]->NotButton.LogicalMax = 127 +pp_data->cap[170]->NotButton.PhysicalMin = 0 +pp_data->cap[170]->NotButton.PhysicalMax = 0 +pp_data->cap[170]->Units = 0 +pp_data->cap[170]->UnitsExp = 0 + +pp_data->cap[171]->UsagePage = 0xFF01 +pp_data->cap[171]->ReportID = 0x80 +pp_data->cap[171]->BitPosition = 0 +pp_data->cap[171]->BitSize = 8 +pp_data->cap[171]->ReportCount = 1 +pp_data->cap[171]->BytePosition = 0x000A +pp_data->cap[171]->BitCount = 8 +pp_data->cap[171]->BitField = 0x02 +pp_data->cap[171]->NextBytePosition = 0x000B +pp_data->cap[171]->LinkCollection = 0x0003 +pp_data->cap[171]->LinkUsagePage = 0xFF01 +pp_data->cap[171]->LinkUsage = 0x0080 +pp_data->cap[171]->IsMultipleItemsForArray = 0 +pp_data->cap[171]->IsButtonCap = 0 +pp_data->cap[171]->IsPadding = 0 +pp_data->cap[171]->IsAbsolute = 1 +pp_data->cap[171]->IsRange = 0 +pp_data->cap[171]->IsAlias = 0 +pp_data->cap[171]->IsStringRange = 0 +pp_data->cap[171]->IsDesignatorRange = 0 +pp_data->cap[171]->Reserved1 = 0x000000 +pp_data->cap[171]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[171]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[171]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[171]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[171]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[171]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[171]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[171]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[171]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[171]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[171]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[171]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[171]->NotRange.Usage = 0x0081 +pp_data->cap[171]->NotRange.Reserved1 = 0x0081 +pp_data->cap[171]->NotRange.StringIndex = 0 +pp_data->cap[171]->NotRange.Reserved2 = 0 +pp_data->cap[171]->NotRange.DesignatorIndex = 0 +pp_data->cap[171]->NotRange.Reserved3 = 0 +pp_data->cap[171]->NotRange.DataIndex = 84 +pp_data->cap[171]->NotRange.Reserved4 = 84 +pp_data->cap[171]->NotButton.HasNull = 0 +pp_data->cap[171]->NotButton.Reserved4 = 0x000000 +pp_data->cap[171]->NotButton.LogicalMin = 0 +pp_data->cap[171]->NotButton.LogicalMax = 127 +pp_data->cap[171]->NotButton.PhysicalMin = 0 +pp_data->cap[171]->NotButton.PhysicalMax = 0 +pp_data->cap[171]->Units = 0 +pp_data->cap[171]->UnitsExp = 0 + +pp_data->cap[172]->UsagePage = 0xFF01 +pp_data->cap[172]->ReportID = 0x80 +pp_data->cap[172]->BitPosition = 0 +pp_data->cap[172]->BitSize = 8 +pp_data->cap[172]->ReportCount = 1 +pp_data->cap[172]->BytePosition = 0x0009 +pp_data->cap[172]->BitCount = 8 +pp_data->cap[172]->BitField = 0x02 +pp_data->cap[172]->NextBytePosition = 0x000A +pp_data->cap[172]->LinkCollection = 0x0003 +pp_data->cap[172]->LinkUsagePage = 0xFF01 +pp_data->cap[172]->LinkUsage = 0x0080 +pp_data->cap[172]->IsMultipleItemsForArray = 0 +pp_data->cap[172]->IsButtonCap = 0 +pp_data->cap[172]->IsPadding = 0 +pp_data->cap[172]->IsAbsolute = 1 +pp_data->cap[172]->IsRange = 0 +pp_data->cap[172]->IsAlias = 0 +pp_data->cap[172]->IsStringRange = 0 +pp_data->cap[172]->IsDesignatorRange = 0 +pp_data->cap[172]->Reserved1 = 0x000000 +pp_data->cap[172]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[172]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[172]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[172]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[172]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[172]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[172]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[172]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[172]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[172]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[172]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[172]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[172]->NotRange.Usage = 0x0081 +pp_data->cap[172]->NotRange.Reserved1 = 0x0081 +pp_data->cap[172]->NotRange.StringIndex = 0 +pp_data->cap[172]->NotRange.Reserved2 = 0 +pp_data->cap[172]->NotRange.DesignatorIndex = 0 +pp_data->cap[172]->NotRange.Reserved3 = 0 +pp_data->cap[172]->NotRange.DataIndex = 85 +pp_data->cap[172]->NotRange.Reserved4 = 85 +pp_data->cap[172]->NotButton.HasNull = 0 +pp_data->cap[172]->NotButton.Reserved4 = 0x000000 +pp_data->cap[172]->NotButton.LogicalMin = 0 +pp_data->cap[172]->NotButton.LogicalMax = 127 +pp_data->cap[172]->NotButton.PhysicalMin = 0 +pp_data->cap[172]->NotButton.PhysicalMax = 0 +pp_data->cap[172]->Units = 0 +pp_data->cap[172]->UnitsExp = 0 + +pp_data->cap[173]->UsagePage = 0xFF01 +pp_data->cap[173]->ReportID = 0x80 +pp_data->cap[173]->BitPosition = 0 +pp_data->cap[173]->BitSize = 8 +pp_data->cap[173]->ReportCount = 1 +pp_data->cap[173]->BytePosition = 0x0008 +pp_data->cap[173]->BitCount = 8 +pp_data->cap[173]->BitField = 0x02 +pp_data->cap[173]->NextBytePosition = 0x0009 +pp_data->cap[173]->LinkCollection = 0x0003 +pp_data->cap[173]->LinkUsagePage = 0xFF01 +pp_data->cap[173]->LinkUsage = 0x0080 +pp_data->cap[173]->IsMultipleItemsForArray = 0 +pp_data->cap[173]->IsButtonCap = 0 +pp_data->cap[173]->IsPadding = 0 +pp_data->cap[173]->IsAbsolute = 1 +pp_data->cap[173]->IsRange = 0 +pp_data->cap[173]->IsAlias = 0 +pp_data->cap[173]->IsStringRange = 0 +pp_data->cap[173]->IsDesignatorRange = 0 +pp_data->cap[173]->Reserved1 = 0x000000 +pp_data->cap[173]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[173]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[173]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[173]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[173]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[173]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[173]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[173]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[173]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[173]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[173]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[173]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[173]->NotRange.Usage = 0x0081 +pp_data->cap[173]->NotRange.Reserved1 = 0x0081 +pp_data->cap[173]->NotRange.StringIndex = 0 +pp_data->cap[173]->NotRange.Reserved2 = 0 +pp_data->cap[173]->NotRange.DesignatorIndex = 0 +pp_data->cap[173]->NotRange.Reserved3 = 0 +pp_data->cap[173]->NotRange.DataIndex = 86 +pp_data->cap[173]->NotRange.Reserved4 = 86 +pp_data->cap[173]->NotButton.HasNull = 0 +pp_data->cap[173]->NotButton.Reserved4 = 0x000000 +pp_data->cap[173]->NotButton.LogicalMin = 0 +pp_data->cap[173]->NotButton.LogicalMax = 127 +pp_data->cap[173]->NotButton.PhysicalMin = 0 +pp_data->cap[173]->NotButton.PhysicalMax = 0 +pp_data->cap[173]->Units = 0 +pp_data->cap[173]->UnitsExp = 0 + +pp_data->cap[174]->UsagePage = 0xFF01 +pp_data->cap[174]->ReportID = 0x80 +pp_data->cap[174]->BitPosition = 0 +pp_data->cap[174]->BitSize = 8 +pp_data->cap[174]->ReportCount = 1 +pp_data->cap[174]->BytePosition = 0x0007 +pp_data->cap[174]->BitCount = 8 +pp_data->cap[174]->BitField = 0x02 +pp_data->cap[174]->NextBytePosition = 0x0008 +pp_data->cap[174]->LinkCollection = 0x0003 +pp_data->cap[174]->LinkUsagePage = 0xFF01 +pp_data->cap[174]->LinkUsage = 0x0080 +pp_data->cap[174]->IsMultipleItemsForArray = 0 +pp_data->cap[174]->IsButtonCap = 0 +pp_data->cap[174]->IsPadding = 0 +pp_data->cap[174]->IsAbsolute = 1 +pp_data->cap[174]->IsRange = 0 +pp_data->cap[174]->IsAlias = 0 +pp_data->cap[174]->IsStringRange = 0 +pp_data->cap[174]->IsDesignatorRange = 0 +pp_data->cap[174]->Reserved1 = 0x000000 +pp_data->cap[174]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[174]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[174]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[174]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[174]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[174]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[174]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[174]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[174]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[174]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[174]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[174]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[174]->NotRange.Usage = 0x0081 +pp_data->cap[174]->NotRange.Reserved1 = 0x0081 +pp_data->cap[174]->NotRange.StringIndex = 0 +pp_data->cap[174]->NotRange.Reserved2 = 0 +pp_data->cap[174]->NotRange.DesignatorIndex = 0 +pp_data->cap[174]->NotRange.Reserved3 = 0 +pp_data->cap[174]->NotRange.DataIndex = 87 +pp_data->cap[174]->NotRange.Reserved4 = 87 +pp_data->cap[174]->NotButton.HasNull = 0 +pp_data->cap[174]->NotButton.Reserved4 = 0x000000 +pp_data->cap[174]->NotButton.LogicalMin = 0 +pp_data->cap[174]->NotButton.LogicalMax = 127 +pp_data->cap[174]->NotButton.PhysicalMin = 0 +pp_data->cap[174]->NotButton.PhysicalMax = 0 +pp_data->cap[174]->Units = 0 +pp_data->cap[174]->UnitsExp = 0 + +pp_data->cap[175]->UsagePage = 0xFF01 +pp_data->cap[175]->ReportID = 0x80 +pp_data->cap[175]->BitPosition = 0 +pp_data->cap[175]->BitSize = 8 +pp_data->cap[175]->ReportCount = 1 +pp_data->cap[175]->BytePosition = 0x0006 +pp_data->cap[175]->BitCount = 8 +pp_data->cap[175]->BitField = 0x02 +pp_data->cap[175]->NextBytePosition = 0x0007 +pp_data->cap[175]->LinkCollection = 0x0003 +pp_data->cap[175]->LinkUsagePage = 0xFF01 +pp_data->cap[175]->LinkUsage = 0x0080 +pp_data->cap[175]->IsMultipleItemsForArray = 0 +pp_data->cap[175]->IsButtonCap = 0 +pp_data->cap[175]->IsPadding = 0 +pp_data->cap[175]->IsAbsolute = 1 +pp_data->cap[175]->IsRange = 0 +pp_data->cap[175]->IsAlias = 0 +pp_data->cap[175]->IsStringRange = 0 +pp_data->cap[175]->IsDesignatorRange = 0 +pp_data->cap[175]->Reserved1 = 0x000000 +pp_data->cap[175]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[175]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[175]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[175]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[175]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[175]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[175]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[175]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[175]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[175]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[175]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[175]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[175]->NotRange.Usage = 0x0081 +pp_data->cap[175]->NotRange.Reserved1 = 0x0081 +pp_data->cap[175]->NotRange.StringIndex = 0 +pp_data->cap[175]->NotRange.Reserved2 = 0 +pp_data->cap[175]->NotRange.DesignatorIndex = 0 +pp_data->cap[175]->NotRange.Reserved3 = 0 +pp_data->cap[175]->NotRange.DataIndex = 88 +pp_data->cap[175]->NotRange.Reserved4 = 88 +pp_data->cap[175]->NotButton.HasNull = 0 +pp_data->cap[175]->NotButton.Reserved4 = 0x000000 +pp_data->cap[175]->NotButton.LogicalMin = 0 +pp_data->cap[175]->NotButton.LogicalMax = 127 +pp_data->cap[175]->NotButton.PhysicalMin = 0 +pp_data->cap[175]->NotButton.PhysicalMax = 0 +pp_data->cap[175]->Units = 0 +pp_data->cap[175]->UnitsExp = 0 + +pp_data->cap[176]->UsagePage = 0xFF01 +pp_data->cap[176]->ReportID = 0x80 +pp_data->cap[176]->BitPosition = 0 +pp_data->cap[176]->BitSize = 8 +pp_data->cap[176]->ReportCount = 1 +pp_data->cap[176]->BytePosition = 0x0005 +pp_data->cap[176]->BitCount = 8 +pp_data->cap[176]->BitField = 0x02 +pp_data->cap[176]->NextBytePosition = 0x0006 +pp_data->cap[176]->LinkCollection = 0x0003 +pp_data->cap[176]->LinkUsagePage = 0xFF01 +pp_data->cap[176]->LinkUsage = 0x0080 +pp_data->cap[176]->IsMultipleItemsForArray = 0 +pp_data->cap[176]->IsButtonCap = 0 +pp_data->cap[176]->IsPadding = 0 +pp_data->cap[176]->IsAbsolute = 1 +pp_data->cap[176]->IsRange = 0 +pp_data->cap[176]->IsAlias = 0 +pp_data->cap[176]->IsStringRange = 0 +pp_data->cap[176]->IsDesignatorRange = 0 +pp_data->cap[176]->Reserved1 = 0x000000 +pp_data->cap[176]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[176]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[176]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[176]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[176]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[176]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[176]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[176]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[176]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[176]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[176]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[176]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[176]->NotRange.Usage = 0x0081 +pp_data->cap[176]->NotRange.Reserved1 = 0x0081 +pp_data->cap[176]->NotRange.StringIndex = 0 +pp_data->cap[176]->NotRange.Reserved2 = 0 +pp_data->cap[176]->NotRange.DesignatorIndex = 0 +pp_data->cap[176]->NotRange.Reserved3 = 0 +pp_data->cap[176]->NotRange.DataIndex = 89 +pp_data->cap[176]->NotRange.Reserved4 = 89 +pp_data->cap[176]->NotButton.HasNull = 0 +pp_data->cap[176]->NotButton.Reserved4 = 0x000000 +pp_data->cap[176]->NotButton.LogicalMin = 0 +pp_data->cap[176]->NotButton.LogicalMax = 127 +pp_data->cap[176]->NotButton.PhysicalMin = 0 +pp_data->cap[176]->NotButton.PhysicalMax = 0 +pp_data->cap[176]->Units = 0 +pp_data->cap[176]->UnitsExp = 0 + +pp_data->cap[177]->UsagePage = 0xFF01 +pp_data->cap[177]->ReportID = 0x80 +pp_data->cap[177]->BitPosition = 0 +pp_data->cap[177]->BitSize = 8 +pp_data->cap[177]->ReportCount = 1 +pp_data->cap[177]->BytePosition = 0x0004 +pp_data->cap[177]->BitCount = 8 +pp_data->cap[177]->BitField = 0x02 +pp_data->cap[177]->NextBytePosition = 0x0005 +pp_data->cap[177]->LinkCollection = 0x0003 +pp_data->cap[177]->LinkUsagePage = 0xFF01 +pp_data->cap[177]->LinkUsage = 0x0080 +pp_data->cap[177]->IsMultipleItemsForArray = 0 +pp_data->cap[177]->IsButtonCap = 0 +pp_data->cap[177]->IsPadding = 0 +pp_data->cap[177]->IsAbsolute = 1 +pp_data->cap[177]->IsRange = 0 +pp_data->cap[177]->IsAlias = 0 +pp_data->cap[177]->IsStringRange = 0 +pp_data->cap[177]->IsDesignatorRange = 0 +pp_data->cap[177]->Reserved1 = 0x000000 +pp_data->cap[177]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[177]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[177]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[177]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[177]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[177]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[177]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[177]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[177]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[177]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[177]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[177]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[177]->NotRange.Usage = 0x0081 +pp_data->cap[177]->NotRange.Reserved1 = 0x0081 +pp_data->cap[177]->NotRange.StringIndex = 0 +pp_data->cap[177]->NotRange.Reserved2 = 0 +pp_data->cap[177]->NotRange.DesignatorIndex = 0 +pp_data->cap[177]->NotRange.Reserved3 = 0 +pp_data->cap[177]->NotRange.DataIndex = 90 +pp_data->cap[177]->NotRange.Reserved4 = 90 +pp_data->cap[177]->NotButton.HasNull = 0 +pp_data->cap[177]->NotButton.Reserved4 = 0x000000 +pp_data->cap[177]->NotButton.LogicalMin = 0 +pp_data->cap[177]->NotButton.LogicalMax = 127 +pp_data->cap[177]->NotButton.PhysicalMin = 0 +pp_data->cap[177]->NotButton.PhysicalMax = 0 +pp_data->cap[177]->Units = 0 +pp_data->cap[177]->UnitsExp = 0 + +pp_data->cap[178]->UsagePage = 0xFF01 +pp_data->cap[178]->ReportID = 0x80 +pp_data->cap[178]->BitPosition = 0 +pp_data->cap[178]->BitSize = 8 +pp_data->cap[178]->ReportCount = 1 +pp_data->cap[178]->BytePosition = 0x0003 +pp_data->cap[178]->BitCount = 8 +pp_data->cap[178]->BitField = 0x02 +pp_data->cap[178]->NextBytePosition = 0x0004 +pp_data->cap[178]->LinkCollection = 0x0003 +pp_data->cap[178]->LinkUsagePage = 0xFF01 +pp_data->cap[178]->LinkUsage = 0x0080 +pp_data->cap[178]->IsMultipleItemsForArray = 0 +pp_data->cap[178]->IsButtonCap = 0 +pp_data->cap[178]->IsPadding = 0 +pp_data->cap[178]->IsAbsolute = 1 +pp_data->cap[178]->IsRange = 0 +pp_data->cap[178]->IsAlias = 0 +pp_data->cap[178]->IsStringRange = 0 +pp_data->cap[178]->IsDesignatorRange = 0 +pp_data->cap[178]->Reserved1 = 0x000000 +pp_data->cap[178]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[178]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[178]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[178]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[178]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[178]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[178]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[178]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[178]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[178]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[178]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[178]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[178]->NotRange.Usage = 0x0081 +pp_data->cap[178]->NotRange.Reserved1 = 0x0081 +pp_data->cap[178]->NotRange.StringIndex = 0 +pp_data->cap[178]->NotRange.Reserved2 = 0 +pp_data->cap[178]->NotRange.DesignatorIndex = 0 +pp_data->cap[178]->NotRange.Reserved3 = 0 +pp_data->cap[178]->NotRange.DataIndex = 91 +pp_data->cap[178]->NotRange.Reserved4 = 91 +pp_data->cap[178]->NotButton.HasNull = 0 +pp_data->cap[178]->NotButton.Reserved4 = 0x000000 +pp_data->cap[178]->NotButton.LogicalMin = 0 +pp_data->cap[178]->NotButton.LogicalMax = 127 +pp_data->cap[178]->NotButton.PhysicalMin = 0 +pp_data->cap[178]->NotButton.PhysicalMax = 0 +pp_data->cap[178]->Units = 0 +pp_data->cap[178]->UnitsExp = 0 + +pp_data->cap[179]->UsagePage = 0xFF01 +pp_data->cap[179]->ReportID = 0x80 +pp_data->cap[179]->BitPosition = 0 +pp_data->cap[179]->BitSize = 8 +pp_data->cap[179]->ReportCount = 1 +pp_data->cap[179]->BytePosition = 0x0002 +pp_data->cap[179]->BitCount = 8 +pp_data->cap[179]->BitField = 0x02 +pp_data->cap[179]->NextBytePosition = 0x0003 +pp_data->cap[179]->LinkCollection = 0x0003 +pp_data->cap[179]->LinkUsagePage = 0xFF01 +pp_data->cap[179]->LinkUsage = 0x0080 +pp_data->cap[179]->IsMultipleItemsForArray = 0 +pp_data->cap[179]->IsButtonCap = 0 +pp_data->cap[179]->IsPadding = 0 +pp_data->cap[179]->IsAbsolute = 1 +pp_data->cap[179]->IsRange = 0 +pp_data->cap[179]->IsAlias = 0 +pp_data->cap[179]->IsStringRange = 0 +pp_data->cap[179]->IsDesignatorRange = 0 +pp_data->cap[179]->Reserved1 = 0x000000 +pp_data->cap[179]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[179]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[179]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[179]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[179]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[179]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[179]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[179]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[179]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[179]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[179]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[179]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[179]->NotRange.Usage = 0x0081 +pp_data->cap[179]->NotRange.Reserved1 = 0x0081 +pp_data->cap[179]->NotRange.StringIndex = 0 +pp_data->cap[179]->NotRange.Reserved2 = 0 +pp_data->cap[179]->NotRange.DesignatorIndex = 0 +pp_data->cap[179]->NotRange.Reserved3 = 0 +pp_data->cap[179]->NotRange.DataIndex = 92 +pp_data->cap[179]->NotRange.Reserved4 = 92 +pp_data->cap[179]->NotButton.HasNull = 0 +pp_data->cap[179]->NotButton.Reserved4 = 0x000000 +pp_data->cap[179]->NotButton.LogicalMin = 0 +pp_data->cap[179]->NotButton.LogicalMax = 127 +pp_data->cap[179]->NotButton.PhysicalMin = 0 +pp_data->cap[179]->NotButton.PhysicalMax = 0 +pp_data->cap[179]->Units = 0 +pp_data->cap[179]->UnitsExp = 0 + +pp_data->cap[180]->UsagePage = 0xFF01 +pp_data->cap[180]->ReportID = 0x80 +pp_data->cap[180]->BitPosition = 0 +pp_data->cap[180]->BitSize = 8 +pp_data->cap[180]->ReportCount = 1 +pp_data->cap[180]->BytePosition = 0x0001 +pp_data->cap[180]->BitCount = 8 +pp_data->cap[180]->BitField = 0x02 +pp_data->cap[180]->NextBytePosition = 0x0002 +pp_data->cap[180]->LinkCollection = 0x0003 +pp_data->cap[180]->LinkUsagePage = 0xFF01 +pp_data->cap[180]->LinkUsage = 0x0080 +pp_data->cap[180]->IsMultipleItemsForArray = 0 +pp_data->cap[180]->IsButtonCap = 0 +pp_data->cap[180]->IsPadding = 0 +pp_data->cap[180]->IsAbsolute = 1 +pp_data->cap[180]->IsRange = 0 +pp_data->cap[180]->IsAlias = 0 +pp_data->cap[180]->IsStringRange = 0 +pp_data->cap[180]->IsDesignatorRange = 0 +pp_data->cap[180]->Reserved1 = 0x000000 +pp_data->cap[180]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[180]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[180]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[180]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[180]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[180]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[180]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[180]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[180]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[180]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[180]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[180]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[180]->NotRange.Usage = 0x0081 +pp_data->cap[180]->NotRange.Reserved1 = 0x0081 +pp_data->cap[180]->NotRange.StringIndex = 0 +pp_data->cap[180]->NotRange.Reserved2 = 0 +pp_data->cap[180]->NotRange.DesignatorIndex = 0 +pp_data->cap[180]->NotRange.Reserved3 = 0 +pp_data->cap[180]->NotRange.DataIndex = 93 +pp_data->cap[180]->NotRange.Reserved4 = 93 +pp_data->cap[180]->NotButton.HasNull = 0 +pp_data->cap[180]->NotButton.Reserved4 = 0x000000 +pp_data->cap[180]->NotButton.LogicalMin = 0 +pp_data->cap[180]->NotButton.LogicalMax = 127 +pp_data->cap[180]->NotButton.PhysicalMin = 0 +pp_data->cap[180]->NotButton.PhysicalMax = 0 +pp_data->cap[180]->Units = 0 +pp_data->cap[180]->UnitsExp = 0 + +pp_data->cap[181]->UsagePage = 0xFF01 +pp_data->cap[181]->ReportID = 0x81 +pp_data->cap[181]->BitPosition = 0 +pp_data->cap[181]->BitSize = 8 +pp_data->cap[181]->ReportCount = 1 +pp_data->cap[181]->BytePosition = 0x0028 +pp_data->cap[181]->BitCount = 8 +pp_data->cap[181]->BitField = 0x02 +pp_data->cap[181]->NextBytePosition = 0x0029 +pp_data->cap[181]->LinkCollection = 0x0004 +pp_data->cap[181]->LinkUsagePage = 0xFF01 +pp_data->cap[181]->LinkUsage = 0x0080 +pp_data->cap[181]->IsMultipleItemsForArray = 0 +pp_data->cap[181]->IsButtonCap = 0 +pp_data->cap[181]->IsPadding = 0 +pp_data->cap[181]->IsAbsolute = 1 +pp_data->cap[181]->IsRange = 0 +pp_data->cap[181]->IsAlias = 0 +pp_data->cap[181]->IsStringRange = 0 +pp_data->cap[181]->IsDesignatorRange = 0 +pp_data->cap[181]->Reserved1 = 0x000000 +pp_data->cap[181]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[181]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[181]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[181]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[181]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[181]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[181]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[181]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[181]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[181]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[181]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[181]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[181]->NotRange.Usage = 0x0081 +pp_data->cap[181]->NotRange.Reserved1 = 0x0081 +pp_data->cap[181]->NotRange.StringIndex = 0 +pp_data->cap[181]->NotRange.Reserved2 = 0 +pp_data->cap[181]->NotRange.DesignatorIndex = 0 +pp_data->cap[181]->NotRange.Reserved3 = 0 +pp_data->cap[181]->NotRange.DataIndex = 94 +pp_data->cap[181]->NotRange.Reserved4 = 94 +pp_data->cap[181]->NotButton.HasNull = 0 +pp_data->cap[181]->NotButton.Reserved4 = 0x000000 +pp_data->cap[181]->NotButton.LogicalMin = 0 +pp_data->cap[181]->NotButton.LogicalMax = 127 +pp_data->cap[181]->NotButton.PhysicalMin = 0 +pp_data->cap[181]->NotButton.PhysicalMax = 0 +pp_data->cap[181]->Units = 0 +pp_data->cap[181]->UnitsExp = 0 + +pp_data->cap[182]->UsagePage = 0xFF01 +pp_data->cap[182]->ReportID = 0x81 +pp_data->cap[182]->BitPosition = 0 +pp_data->cap[182]->BitSize = 8 +pp_data->cap[182]->ReportCount = 1 +pp_data->cap[182]->BytePosition = 0x0027 +pp_data->cap[182]->BitCount = 8 +pp_data->cap[182]->BitField = 0x02 +pp_data->cap[182]->NextBytePosition = 0x0028 +pp_data->cap[182]->LinkCollection = 0x0004 +pp_data->cap[182]->LinkUsagePage = 0xFF01 +pp_data->cap[182]->LinkUsage = 0x0080 +pp_data->cap[182]->IsMultipleItemsForArray = 0 +pp_data->cap[182]->IsButtonCap = 0 +pp_data->cap[182]->IsPadding = 0 +pp_data->cap[182]->IsAbsolute = 1 +pp_data->cap[182]->IsRange = 0 +pp_data->cap[182]->IsAlias = 0 +pp_data->cap[182]->IsStringRange = 0 +pp_data->cap[182]->IsDesignatorRange = 0 +pp_data->cap[182]->Reserved1 = 0x000000 +pp_data->cap[182]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[182]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[182]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[182]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[182]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[182]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[182]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[182]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[182]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[182]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[182]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[182]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[182]->NotRange.Usage = 0x0081 +pp_data->cap[182]->NotRange.Reserved1 = 0x0081 +pp_data->cap[182]->NotRange.StringIndex = 0 +pp_data->cap[182]->NotRange.Reserved2 = 0 +pp_data->cap[182]->NotRange.DesignatorIndex = 0 +pp_data->cap[182]->NotRange.Reserved3 = 0 +pp_data->cap[182]->NotRange.DataIndex = 95 +pp_data->cap[182]->NotRange.Reserved4 = 95 +pp_data->cap[182]->NotButton.HasNull = 0 +pp_data->cap[182]->NotButton.Reserved4 = 0x000000 +pp_data->cap[182]->NotButton.LogicalMin = 0 +pp_data->cap[182]->NotButton.LogicalMax = 127 +pp_data->cap[182]->NotButton.PhysicalMin = 0 +pp_data->cap[182]->NotButton.PhysicalMax = 0 +pp_data->cap[182]->Units = 0 +pp_data->cap[182]->UnitsExp = 0 + +pp_data->cap[183]->UsagePage = 0xFF01 +pp_data->cap[183]->ReportID = 0x81 +pp_data->cap[183]->BitPosition = 0 +pp_data->cap[183]->BitSize = 8 +pp_data->cap[183]->ReportCount = 1 +pp_data->cap[183]->BytePosition = 0x0026 +pp_data->cap[183]->BitCount = 8 +pp_data->cap[183]->BitField = 0x02 +pp_data->cap[183]->NextBytePosition = 0x0027 +pp_data->cap[183]->LinkCollection = 0x0004 +pp_data->cap[183]->LinkUsagePage = 0xFF01 +pp_data->cap[183]->LinkUsage = 0x0080 +pp_data->cap[183]->IsMultipleItemsForArray = 0 +pp_data->cap[183]->IsButtonCap = 0 +pp_data->cap[183]->IsPadding = 0 +pp_data->cap[183]->IsAbsolute = 1 +pp_data->cap[183]->IsRange = 0 +pp_data->cap[183]->IsAlias = 0 +pp_data->cap[183]->IsStringRange = 0 +pp_data->cap[183]->IsDesignatorRange = 0 +pp_data->cap[183]->Reserved1 = 0x000000 +pp_data->cap[183]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[183]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[183]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[183]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[183]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[183]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[183]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[183]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[183]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[183]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[183]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[183]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[183]->NotRange.Usage = 0x0081 +pp_data->cap[183]->NotRange.Reserved1 = 0x0081 +pp_data->cap[183]->NotRange.StringIndex = 0 +pp_data->cap[183]->NotRange.Reserved2 = 0 +pp_data->cap[183]->NotRange.DesignatorIndex = 0 +pp_data->cap[183]->NotRange.Reserved3 = 0 +pp_data->cap[183]->NotRange.DataIndex = 96 +pp_data->cap[183]->NotRange.Reserved4 = 96 +pp_data->cap[183]->NotButton.HasNull = 0 +pp_data->cap[183]->NotButton.Reserved4 = 0x000000 +pp_data->cap[183]->NotButton.LogicalMin = 0 +pp_data->cap[183]->NotButton.LogicalMax = 127 +pp_data->cap[183]->NotButton.PhysicalMin = 0 +pp_data->cap[183]->NotButton.PhysicalMax = 0 +pp_data->cap[183]->Units = 0 +pp_data->cap[183]->UnitsExp = 0 + +pp_data->cap[184]->UsagePage = 0xFF01 +pp_data->cap[184]->ReportID = 0x81 +pp_data->cap[184]->BitPosition = 0 +pp_data->cap[184]->BitSize = 8 +pp_data->cap[184]->ReportCount = 1 +pp_data->cap[184]->BytePosition = 0x0025 +pp_data->cap[184]->BitCount = 8 +pp_data->cap[184]->BitField = 0x02 +pp_data->cap[184]->NextBytePosition = 0x0026 +pp_data->cap[184]->LinkCollection = 0x0004 +pp_data->cap[184]->LinkUsagePage = 0xFF01 +pp_data->cap[184]->LinkUsage = 0x0080 +pp_data->cap[184]->IsMultipleItemsForArray = 0 +pp_data->cap[184]->IsButtonCap = 0 +pp_data->cap[184]->IsPadding = 0 +pp_data->cap[184]->IsAbsolute = 1 +pp_data->cap[184]->IsRange = 0 +pp_data->cap[184]->IsAlias = 0 +pp_data->cap[184]->IsStringRange = 0 +pp_data->cap[184]->IsDesignatorRange = 0 +pp_data->cap[184]->Reserved1 = 0x000000 +pp_data->cap[184]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[184]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[184]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[184]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[184]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[184]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[184]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[184]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[184]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[184]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[184]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[184]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[184]->NotRange.Usage = 0x0081 +pp_data->cap[184]->NotRange.Reserved1 = 0x0081 +pp_data->cap[184]->NotRange.StringIndex = 0 +pp_data->cap[184]->NotRange.Reserved2 = 0 +pp_data->cap[184]->NotRange.DesignatorIndex = 0 +pp_data->cap[184]->NotRange.Reserved3 = 0 +pp_data->cap[184]->NotRange.DataIndex = 97 +pp_data->cap[184]->NotRange.Reserved4 = 97 +pp_data->cap[184]->NotButton.HasNull = 0 +pp_data->cap[184]->NotButton.Reserved4 = 0x000000 +pp_data->cap[184]->NotButton.LogicalMin = 0 +pp_data->cap[184]->NotButton.LogicalMax = 127 +pp_data->cap[184]->NotButton.PhysicalMin = 0 +pp_data->cap[184]->NotButton.PhysicalMax = 0 +pp_data->cap[184]->Units = 0 +pp_data->cap[184]->UnitsExp = 0 + +pp_data->cap[185]->UsagePage = 0xFF01 +pp_data->cap[185]->ReportID = 0x81 +pp_data->cap[185]->BitPosition = 0 +pp_data->cap[185]->BitSize = 8 +pp_data->cap[185]->ReportCount = 1 +pp_data->cap[185]->BytePosition = 0x0024 +pp_data->cap[185]->BitCount = 8 +pp_data->cap[185]->BitField = 0x02 +pp_data->cap[185]->NextBytePosition = 0x0025 +pp_data->cap[185]->LinkCollection = 0x0004 +pp_data->cap[185]->LinkUsagePage = 0xFF01 +pp_data->cap[185]->LinkUsage = 0x0080 +pp_data->cap[185]->IsMultipleItemsForArray = 0 +pp_data->cap[185]->IsButtonCap = 0 +pp_data->cap[185]->IsPadding = 0 +pp_data->cap[185]->IsAbsolute = 1 +pp_data->cap[185]->IsRange = 0 +pp_data->cap[185]->IsAlias = 0 +pp_data->cap[185]->IsStringRange = 0 +pp_data->cap[185]->IsDesignatorRange = 0 +pp_data->cap[185]->Reserved1 = 0x000000 +pp_data->cap[185]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[185]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[185]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[185]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[185]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[185]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[185]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[185]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[185]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[185]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[185]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[185]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[185]->NotRange.Usage = 0x0081 +pp_data->cap[185]->NotRange.Reserved1 = 0x0081 +pp_data->cap[185]->NotRange.StringIndex = 0 +pp_data->cap[185]->NotRange.Reserved2 = 0 +pp_data->cap[185]->NotRange.DesignatorIndex = 0 +pp_data->cap[185]->NotRange.Reserved3 = 0 +pp_data->cap[185]->NotRange.DataIndex = 98 +pp_data->cap[185]->NotRange.Reserved4 = 98 +pp_data->cap[185]->NotButton.HasNull = 0 +pp_data->cap[185]->NotButton.Reserved4 = 0x000000 +pp_data->cap[185]->NotButton.LogicalMin = 0 +pp_data->cap[185]->NotButton.LogicalMax = 127 +pp_data->cap[185]->NotButton.PhysicalMin = 0 +pp_data->cap[185]->NotButton.PhysicalMax = 0 +pp_data->cap[185]->Units = 0 +pp_data->cap[185]->UnitsExp = 0 + +pp_data->cap[186]->UsagePage = 0xFF01 +pp_data->cap[186]->ReportID = 0x81 +pp_data->cap[186]->BitPosition = 0 +pp_data->cap[186]->BitSize = 8 +pp_data->cap[186]->ReportCount = 1 +pp_data->cap[186]->BytePosition = 0x0023 +pp_data->cap[186]->BitCount = 8 +pp_data->cap[186]->BitField = 0x02 +pp_data->cap[186]->NextBytePosition = 0x0024 +pp_data->cap[186]->LinkCollection = 0x0004 +pp_data->cap[186]->LinkUsagePage = 0xFF01 +pp_data->cap[186]->LinkUsage = 0x0080 +pp_data->cap[186]->IsMultipleItemsForArray = 0 +pp_data->cap[186]->IsButtonCap = 0 +pp_data->cap[186]->IsPadding = 0 +pp_data->cap[186]->IsAbsolute = 1 +pp_data->cap[186]->IsRange = 0 +pp_data->cap[186]->IsAlias = 0 +pp_data->cap[186]->IsStringRange = 0 +pp_data->cap[186]->IsDesignatorRange = 0 +pp_data->cap[186]->Reserved1 = 0x000000 +pp_data->cap[186]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[186]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[186]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[186]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[186]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[186]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[186]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[186]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[186]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[186]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[186]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[186]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[186]->NotRange.Usage = 0x0081 +pp_data->cap[186]->NotRange.Reserved1 = 0x0081 +pp_data->cap[186]->NotRange.StringIndex = 0 +pp_data->cap[186]->NotRange.Reserved2 = 0 +pp_data->cap[186]->NotRange.DesignatorIndex = 0 +pp_data->cap[186]->NotRange.Reserved3 = 0 +pp_data->cap[186]->NotRange.DataIndex = 99 +pp_data->cap[186]->NotRange.Reserved4 = 99 +pp_data->cap[186]->NotButton.HasNull = 0 +pp_data->cap[186]->NotButton.Reserved4 = 0x000000 +pp_data->cap[186]->NotButton.LogicalMin = 0 +pp_data->cap[186]->NotButton.LogicalMax = 127 +pp_data->cap[186]->NotButton.PhysicalMin = 0 +pp_data->cap[186]->NotButton.PhysicalMax = 0 +pp_data->cap[186]->Units = 0 +pp_data->cap[186]->UnitsExp = 0 + +pp_data->cap[187]->UsagePage = 0xFF01 +pp_data->cap[187]->ReportID = 0x81 +pp_data->cap[187]->BitPosition = 0 +pp_data->cap[187]->BitSize = 8 +pp_data->cap[187]->ReportCount = 1 +pp_data->cap[187]->BytePosition = 0x0022 +pp_data->cap[187]->BitCount = 8 +pp_data->cap[187]->BitField = 0x02 +pp_data->cap[187]->NextBytePosition = 0x0023 +pp_data->cap[187]->LinkCollection = 0x0004 +pp_data->cap[187]->LinkUsagePage = 0xFF01 +pp_data->cap[187]->LinkUsage = 0x0080 +pp_data->cap[187]->IsMultipleItemsForArray = 0 +pp_data->cap[187]->IsButtonCap = 0 +pp_data->cap[187]->IsPadding = 0 +pp_data->cap[187]->IsAbsolute = 1 +pp_data->cap[187]->IsRange = 0 +pp_data->cap[187]->IsAlias = 0 +pp_data->cap[187]->IsStringRange = 0 +pp_data->cap[187]->IsDesignatorRange = 0 +pp_data->cap[187]->Reserved1 = 0x000000 +pp_data->cap[187]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[187]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[187]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[187]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[187]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[187]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[187]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[187]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[187]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[187]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[187]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[187]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[187]->NotRange.Usage = 0x0081 +pp_data->cap[187]->NotRange.Reserved1 = 0x0081 +pp_data->cap[187]->NotRange.StringIndex = 0 +pp_data->cap[187]->NotRange.Reserved2 = 0 +pp_data->cap[187]->NotRange.DesignatorIndex = 0 +pp_data->cap[187]->NotRange.Reserved3 = 0 +pp_data->cap[187]->NotRange.DataIndex = 100 +pp_data->cap[187]->NotRange.Reserved4 = 100 +pp_data->cap[187]->NotButton.HasNull = 0 +pp_data->cap[187]->NotButton.Reserved4 = 0x000000 +pp_data->cap[187]->NotButton.LogicalMin = 0 +pp_data->cap[187]->NotButton.LogicalMax = 127 +pp_data->cap[187]->NotButton.PhysicalMin = 0 +pp_data->cap[187]->NotButton.PhysicalMax = 0 +pp_data->cap[187]->Units = 0 +pp_data->cap[187]->UnitsExp = 0 + +pp_data->cap[188]->UsagePage = 0xFF01 +pp_data->cap[188]->ReportID = 0x81 +pp_data->cap[188]->BitPosition = 0 +pp_data->cap[188]->BitSize = 8 +pp_data->cap[188]->ReportCount = 1 +pp_data->cap[188]->BytePosition = 0x0021 +pp_data->cap[188]->BitCount = 8 +pp_data->cap[188]->BitField = 0x02 +pp_data->cap[188]->NextBytePosition = 0x0022 +pp_data->cap[188]->LinkCollection = 0x0004 +pp_data->cap[188]->LinkUsagePage = 0xFF01 +pp_data->cap[188]->LinkUsage = 0x0080 +pp_data->cap[188]->IsMultipleItemsForArray = 0 +pp_data->cap[188]->IsButtonCap = 0 +pp_data->cap[188]->IsPadding = 0 +pp_data->cap[188]->IsAbsolute = 1 +pp_data->cap[188]->IsRange = 0 +pp_data->cap[188]->IsAlias = 0 +pp_data->cap[188]->IsStringRange = 0 +pp_data->cap[188]->IsDesignatorRange = 0 +pp_data->cap[188]->Reserved1 = 0x000000 +pp_data->cap[188]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[188]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[188]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[188]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[188]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[188]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[188]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[188]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[188]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[188]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[188]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[188]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[188]->NotRange.Usage = 0x0081 +pp_data->cap[188]->NotRange.Reserved1 = 0x0081 +pp_data->cap[188]->NotRange.StringIndex = 0 +pp_data->cap[188]->NotRange.Reserved2 = 0 +pp_data->cap[188]->NotRange.DesignatorIndex = 0 +pp_data->cap[188]->NotRange.Reserved3 = 0 +pp_data->cap[188]->NotRange.DataIndex = 101 +pp_data->cap[188]->NotRange.Reserved4 = 101 +pp_data->cap[188]->NotButton.HasNull = 0 +pp_data->cap[188]->NotButton.Reserved4 = 0x000000 +pp_data->cap[188]->NotButton.LogicalMin = 0 +pp_data->cap[188]->NotButton.LogicalMax = 127 +pp_data->cap[188]->NotButton.PhysicalMin = 0 +pp_data->cap[188]->NotButton.PhysicalMax = 0 +pp_data->cap[188]->Units = 0 +pp_data->cap[188]->UnitsExp = 0 + +pp_data->cap[189]->UsagePage = 0xFF01 +pp_data->cap[189]->ReportID = 0x81 +pp_data->cap[189]->BitPosition = 0 +pp_data->cap[189]->BitSize = 8 +pp_data->cap[189]->ReportCount = 1 +pp_data->cap[189]->BytePosition = 0x0020 +pp_data->cap[189]->BitCount = 8 +pp_data->cap[189]->BitField = 0x02 +pp_data->cap[189]->NextBytePosition = 0x0021 +pp_data->cap[189]->LinkCollection = 0x0004 +pp_data->cap[189]->LinkUsagePage = 0xFF01 +pp_data->cap[189]->LinkUsage = 0x0080 +pp_data->cap[189]->IsMultipleItemsForArray = 0 +pp_data->cap[189]->IsButtonCap = 0 +pp_data->cap[189]->IsPadding = 0 +pp_data->cap[189]->IsAbsolute = 1 +pp_data->cap[189]->IsRange = 0 +pp_data->cap[189]->IsAlias = 0 +pp_data->cap[189]->IsStringRange = 0 +pp_data->cap[189]->IsDesignatorRange = 0 +pp_data->cap[189]->Reserved1 = 0x000000 +pp_data->cap[189]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[189]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[189]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[189]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[189]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[189]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[189]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[189]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[189]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[189]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[189]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[189]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[189]->NotRange.Usage = 0x0081 +pp_data->cap[189]->NotRange.Reserved1 = 0x0081 +pp_data->cap[189]->NotRange.StringIndex = 0 +pp_data->cap[189]->NotRange.Reserved2 = 0 +pp_data->cap[189]->NotRange.DesignatorIndex = 0 +pp_data->cap[189]->NotRange.Reserved3 = 0 +pp_data->cap[189]->NotRange.DataIndex = 102 +pp_data->cap[189]->NotRange.Reserved4 = 102 +pp_data->cap[189]->NotButton.HasNull = 0 +pp_data->cap[189]->NotButton.Reserved4 = 0x000000 +pp_data->cap[189]->NotButton.LogicalMin = 0 +pp_data->cap[189]->NotButton.LogicalMax = 127 +pp_data->cap[189]->NotButton.PhysicalMin = 0 +pp_data->cap[189]->NotButton.PhysicalMax = 0 +pp_data->cap[189]->Units = 0 +pp_data->cap[189]->UnitsExp = 0 + +pp_data->cap[190]->UsagePage = 0xFF01 +pp_data->cap[190]->ReportID = 0x81 +pp_data->cap[190]->BitPosition = 0 +pp_data->cap[190]->BitSize = 8 +pp_data->cap[190]->ReportCount = 1 +pp_data->cap[190]->BytePosition = 0x001F +pp_data->cap[190]->BitCount = 8 +pp_data->cap[190]->BitField = 0x02 +pp_data->cap[190]->NextBytePosition = 0x0020 +pp_data->cap[190]->LinkCollection = 0x0004 +pp_data->cap[190]->LinkUsagePage = 0xFF01 +pp_data->cap[190]->LinkUsage = 0x0080 +pp_data->cap[190]->IsMultipleItemsForArray = 0 +pp_data->cap[190]->IsButtonCap = 0 +pp_data->cap[190]->IsPadding = 0 +pp_data->cap[190]->IsAbsolute = 1 +pp_data->cap[190]->IsRange = 0 +pp_data->cap[190]->IsAlias = 0 +pp_data->cap[190]->IsStringRange = 0 +pp_data->cap[190]->IsDesignatorRange = 0 +pp_data->cap[190]->Reserved1 = 0x000000 +pp_data->cap[190]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[190]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[190]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[190]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[190]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[190]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[190]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[190]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[190]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[190]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[190]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[190]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[190]->NotRange.Usage = 0x0081 +pp_data->cap[190]->NotRange.Reserved1 = 0x0081 +pp_data->cap[190]->NotRange.StringIndex = 0 +pp_data->cap[190]->NotRange.Reserved2 = 0 +pp_data->cap[190]->NotRange.DesignatorIndex = 0 +pp_data->cap[190]->NotRange.Reserved3 = 0 +pp_data->cap[190]->NotRange.DataIndex = 103 +pp_data->cap[190]->NotRange.Reserved4 = 103 +pp_data->cap[190]->NotButton.HasNull = 0 +pp_data->cap[190]->NotButton.Reserved4 = 0x000000 +pp_data->cap[190]->NotButton.LogicalMin = 0 +pp_data->cap[190]->NotButton.LogicalMax = 127 +pp_data->cap[190]->NotButton.PhysicalMin = 0 +pp_data->cap[190]->NotButton.PhysicalMax = 0 +pp_data->cap[190]->Units = 0 +pp_data->cap[190]->UnitsExp = 0 + +pp_data->cap[191]->UsagePage = 0xFF01 +pp_data->cap[191]->ReportID = 0x81 +pp_data->cap[191]->BitPosition = 0 +pp_data->cap[191]->BitSize = 8 +pp_data->cap[191]->ReportCount = 1 +pp_data->cap[191]->BytePosition = 0x001E +pp_data->cap[191]->BitCount = 8 +pp_data->cap[191]->BitField = 0x02 +pp_data->cap[191]->NextBytePosition = 0x001F +pp_data->cap[191]->LinkCollection = 0x0004 +pp_data->cap[191]->LinkUsagePage = 0xFF01 +pp_data->cap[191]->LinkUsage = 0x0080 +pp_data->cap[191]->IsMultipleItemsForArray = 0 +pp_data->cap[191]->IsButtonCap = 0 +pp_data->cap[191]->IsPadding = 0 +pp_data->cap[191]->IsAbsolute = 1 +pp_data->cap[191]->IsRange = 0 +pp_data->cap[191]->IsAlias = 0 +pp_data->cap[191]->IsStringRange = 0 +pp_data->cap[191]->IsDesignatorRange = 0 +pp_data->cap[191]->Reserved1 = 0x000000 +pp_data->cap[191]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[191]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[191]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[191]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[191]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[191]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[191]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[191]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[191]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[191]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[191]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[191]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[191]->NotRange.Usage = 0x0081 +pp_data->cap[191]->NotRange.Reserved1 = 0x0081 +pp_data->cap[191]->NotRange.StringIndex = 0 +pp_data->cap[191]->NotRange.Reserved2 = 0 +pp_data->cap[191]->NotRange.DesignatorIndex = 0 +pp_data->cap[191]->NotRange.Reserved3 = 0 +pp_data->cap[191]->NotRange.DataIndex = 104 +pp_data->cap[191]->NotRange.Reserved4 = 104 +pp_data->cap[191]->NotButton.HasNull = 0 +pp_data->cap[191]->NotButton.Reserved4 = 0x000000 +pp_data->cap[191]->NotButton.LogicalMin = 0 +pp_data->cap[191]->NotButton.LogicalMax = 127 +pp_data->cap[191]->NotButton.PhysicalMin = 0 +pp_data->cap[191]->NotButton.PhysicalMax = 0 +pp_data->cap[191]->Units = 0 +pp_data->cap[191]->UnitsExp = 0 + +pp_data->cap[192]->UsagePage = 0xFF01 +pp_data->cap[192]->ReportID = 0x81 +pp_data->cap[192]->BitPosition = 0 +pp_data->cap[192]->BitSize = 8 +pp_data->cap[192]->ReportCount = 1 +pp_data->cap[192]->BytePosition = 0x001D +pp_data->cap[192]->BitCount = 8 +pp_data->cap[192]->BitField = 0x02 +pp_data->cap[192]->NextBytePosition = 0x001E +pp_data->cap[192]->LinkCollection = 0x0004 +pp_data->cap[192]->LinkUsagePage = 0xFF01 +pp_data->cap[192]->LinkUsage = 0x0080 +pp_data->cap[192]->IsMultipleItemsForArray = 0 +pp_data->cap[192]->IsButtonCap = 0 +pp_data->cap[192]->IsPadding = 0 +pp_data->cap[192]->IsAbsolute = 1 +pp_data->cap[192]->IsRange = 0 +pp_data->cap[192]->IsAlias = 0 +pp_data->cap[192]->IsStringRange = 0 +pp_data->cap[192]->IsDesignatorRange = 0 +pp_data->cap[192]->Reserved1 = 0x000000 +pp_data->cap[192]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[192]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[192]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[192]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[192]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[192]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[192]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[192]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[192]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[192]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[192]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[192]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[192]->NotRange.Usage = 0x0081 +pp_data->cap[192]->NotRange.Reserved1 = 0x0081 +pp_data->cap[192]->NotRange.StringIndex = 0 +pp_data->cap[192]->NotRange.Reserved2 = 0 +pp_data->cap[192]->NotRange.DesignatorIndex = 0 +pp_data->cap[192]->NotRange.Reserved3 = 0 +pp_data->cap[192]->NotRange.DataIndex = 105 +pp_data->cap[192]->NotRange.Reserved4 = 105 +pp_data->cap[192]->NotButton.HasNull = 0 +pp_data->cap[192]->NotButton.Reserved4 = 0x000000 +pp_data->cap[192]->NotButton.LogicalMin = 0 +pp_data->cap[192]->NotButton.LogicalMax = 127 +pp_data->cap[192]->NotButton.PhysicalMin = 0 +pp_data->cap[192]->NotButton.PhysicalMax = 0 +pp_data->cap[192]->Units = 0 +pp_data->cap[192]->UnitsExp = 0 + +pp_data->cap[193]->UsagePage = 0xFF01 +pp_data->cap[193]->ReportID = 0x81 +pp_data->cap[193]->BitPosition = 0 +pp_data->cap[193]->BitSize = 8 +pp_data->cap[193]->ReportCount = 1 +pp_data->cap[193]->BytePosition = 0x001C +pp_data->cap[193]->BitCount = 8 +pp_data->cap[193]->BitField = 0x02 +pp_data->cap[193]->NextBytePosition = 0x001D +pp_data->cap[193]->LinkCollection = 0x0004 +pp_data->cap[193]->LinkUsagePage = 0xFF01 +pp_data->cap[193]->LinkUsage = 0x0080 +pp_data->cap[193]->IsMultipleItemsForArray = 0 +pp_data->cap[193]->IsButtonCap = 0 +pp_data->cap[193]->IsPadding = 0 +pp_data->cap[193]->IsAbsolute = 1 +pp_data->cap[193]->IsRange = 0 +pp_data->cap[193]->IsAlias = 0 +pp_data->cap[193]->IsStringRange = 0 +pp_data->cap[193]->IsDesignatorRange = 0 +pp_data->cap[193]->Reserved1 = 0x000000 +pp_data->cap[193]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[193]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[193]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[193]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[193]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[193]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[193]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[193]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[193]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[193]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[193]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[193]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[193]->NotRange.Usage = 0x0081 +pp_data->cap[193]->NotRange.Reserved1 = 0x0081 +pp_data->cap[193]->NotRange.StringIndex = 0 +pp_data->cap[193]->NotRange.Reserved2 = 0 +pp_data->cap[193]->NotRange.DesignatorIndex = 0 +pp_data->cap[193]->NotRange.Reserved3 = 0 +pp_data->cap[193]->NotRange.DataIndex = 106 +pp_data->cap[193]->NotRange.Reserved4 = 106 +pp_data->cap[193]->NotButton.HasNull = 0 +pp_data->cap[193]->NotButton.Reserved4 = 0x000000 +pp_data->cap[193]->NotButton.LogicalMin = 0 +pp_data->cap[193]->NotButton.LogicalMax = 127 +pp_data->cap[193]->NotButton.PhysicalMin = 0 +pp_data->cap[193]->NotButton.PhysicalMax = 0 +pp_data->cap[193]->Units = 0 +pp_data->cap[193]->UnitsExp = 0 + +pp_data->cap[194]->UsagePage = 0xFF01 +pp_data->cap[194]->ReportID = 0x81 +pp_data->cap[194]->BitPosition = 0 +pp_data->cap[194]->BitSize = 8 +pp_data->cap[194]->ReportCount = 1 +pp_data->cap[194]->BytePosition = 0x001B +pp_data->cap[194]->BitCount = 8 +pp_data->cap[194]->BitField = 0x02 +pp_data->cap[194]->NextBytePosition = 0x001C +pp_data->cap[194]->LinkCollection = 0x0004 +pp_data->cap[194]->LinkUsagePage = 0xFF01 +pp_data->cap[194]->LinkUsage = 0x0080 +pp_data->cap[194]->IsMultipleItemsForArray = 0 +pp_data->cap[194]->IsButtonCap = 0 +pp_data->cap[194]->IsPadding = 0 +pp_data->cap[194]->IsAbsolute = 1 +pp_data->cap[194]->IsRange = 0 +pp_data->cap[194]->IsAlias = 0 +pp_data->cap[194]->IsStringRange = 0 +pp_data->cap[194]->IsDesignatorRange = 0 +pp_data->cap[194]->Reserved1 = 0x000000 +pp_data->cap[194]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[194]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[194]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[194]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[194]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[194]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[194]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[194]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[194]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[194]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[194]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[194]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[194]->NotRange.Usage = 0x0081 +pp_data->cap[194]->NotRange.Reserved1 = 0x0081 +pp_data->cap[194]->NotRange.StringIndex = 0 +pp_data->cap[194]->NotRange.Reserved2 = 0 +pp_data->cap[194]->NotRange.DesignatorIndex = 0 +pp_data->cap[194]->NotRange.Reserved3 = 0 +pp_data->cap[194]->NotRange.DataIndex = 107 +pp_data->cap[194]->NotRange.Reserved4 = 107 +pp_data->cap[194]->NotButton.HasNull = 0 +pp_data->cap[194]->NotButton.Reserved4 = 0x000000 +pp_data->cap[194]->NotButton.LogicalMin = 0 +pp_data->cap[194]->NotButton.LogicalMax = 127 +pp_data->cap[194]->NotButton.PhysicalMin = 0 +pp_data->cap[194]->NotButton.PhysicalMax = 0 +pp_data->cap[194]->Units = 0 +pp_data->cap[194]->UnitsExp = 0 + +pp_data->cap[195]->UsagePage = 0xFF01 +pp_data->cap[195]->ReportID = 0x81 +pp_data->cap[195]->BitPosition = 0 +pp_data->cap[195]->BitSize = 8 +pp_data->cap[195]->ReportCount = 1 +pp_data->cap[195]->BytePosition = 0x001A +pp_data->cap[195]->BitCount = 8 +pp_data->cap[195]->BitField = 0x02 +pp_data->cap[195]->NextBytePosition = 0x001B +pp_data->cap[195]->LinkCollection = 0x0004 +pp_data->cap[195]->LinkUsagePage = 0xFF01 +pp_data->cap[195]->LinkUsage = 0x0080 +pp_data->cap[195]->IsMultipleItemsForArray = 0 +pp_data->cap[195]->IsButtonCap = 0 +pp_data->cap[195]->IsPadding = 0 +pp_data->cap[195]->IsAbsolute = 1 +pp_data->cap[195]->IsRange = 0 +pp_data->cap[195]->IsAlias = 0 +pp_data->cap[195]->IsStringRange = 0 +pp_data->cap[195]->IsDesignatorRange = 0 +pp_data->cap[195]->Reserved1 = 0x000000 +pp_data->cap[195]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[195]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[195]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[195]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[195]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[195]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[195]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[195]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[195]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[195]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[195]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[195]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[195]->NotRange.Usage = 0x0081 +pp_data->cap[195]->NotRange.Reserved1 = 0x0081 +pp_data->cap[195]->NotRange.StringIndex = 0 +pp_data->cap[195]->NotRange.Reserved2 = 0 +pp_data->cap[195]->NotRange.DesignatorIndex = 0 +pp_data->cap[195]->NotRange.Reserved3 = 0 +pp_data->cap[195]->NotRange.DataIndex = 108 +pp_data->cap[195]->NotRange.Reserved4 = 108 +pp_data->cap[195]->NotButton.HasNull = 0 +pp_data->cap[195]->NotButton.Reserved4 = 0x000000 +pp_data->cap[195]->NotButton.LogicalMin = 0 +pp_data->cap[195]->NotButton.LogicalMax = 127 +pp_data->cap[195]->NotButton.PhysicalMin = 0 +pp_data->cap[195]->NotButton.PhysicalMax = 0 +pp_data->cap[195]->Units = 0 +pp_data->cap[195]->UnitsExp = 0 + +pp_data->cap[196]->UsagePage = 0xFF01 +pp_data->cap[196]->ReportID = 0x81 +pp_data->cap[196]->BitPosition = 0 +pp_data->cap[196]->BitSize = 8 +pp_data->cap[196]->ReportCount = 1 +pp_data->cap[196]->BytePosition = 0x0019 +pp_data->cap[196]->BitCount = 8 +pp_data->cap[196]->BitField = 0x02 +pp_data->cap[196]->NextBytePosition = 0x001A +pp_data->cap[196]->LinkCollection = 0x0004 +pp_data->cap[196]->LinkUsagePage = 0xFF01 +pp_data->cap[196]->LinkUsage = 0x0080 +pp_data->cap[196]->IsMultipleItemsForArray = 0 +pp_data->cap[196]->IsButtonCap = 0 +pp_data->cap[196]->IsPadding = 0 +pp_data->cap[196]->IsAbsolute = 1 +pp_data->cap[196]->IsRange = 0 +pp_data->cap[196]->IsAlias = 0 +pp_data->cap[196]->IsStringRange = 0 +pp_data->cap[196]->IsDesignatorRange = 0 +pp_data->cap[196]->Reserved1 = 0x000000 +pp_data->cap[196]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[196]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[196]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[196]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[196]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[196]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[196]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[196]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[196]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[196]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[196]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[196]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[196]->NotRange.Usage = 0x0081 +pp_data->cap[196]->NotRange.Reserved1 = 0x0081 +pp_data->cap[196]->NotRange.StringIndex = 0 +pp_data->cap[196]->NotRange.Reserved2 = 0 +pp_data->cap[196]->NotRange.DesignatorIndex = 0 +pp_data->cap[196]->NotRange.Reserved3 = 0 +pp_data->cap[196]->NotRange.DataIndex = 109 +pp_data->cap[196]->NotRange.Reserved4 = 109 +pp_data->cap[196]->NotButton.HasNull = 0 +pp_data->cap[196]->NotButton.Reserved4 = 0x000000 +pp_data->cap[196]->NotButton.LogicalMin = 0 +pp_data->cap[196]->NotButton.LogicalMax = 127 +pp_data->cap[196]->NotButton.PhysicalMin = 0 +pp_data->cap[196]->NotButton.PhysicalMax = 0 +pp_data->cap[196]->Units = 0 +pp_data->cap[196]->UnitsExp = 0 + +pp_data->cap[197]->UsagePage = 0xFF01 +pp_data->cap[197]->ReportID = 0x81 +pp_data->cap[197]->BitPosition = 0 +pp_data->cap[197]->BitSize = 8 +pp_data->cap[197]->ReportCount = 1 +pp_data->cap[197]->BytePosition = 0x0018 +pp_data->cap[197]->BitCount = 8 +pp_data->cap[197]->BitField = 0x02 +pp_data->cap[197]->NextBytePosition = 0x0019 +pp_data->cap[197]->LinkCollection = 0x0004 +pp_data->cap[197]->LinkUsagePage = 0xFF01 +pp_data->cap[197]->LinkUsage = 0x0080 +pp_data->cap[197]->IsMultipleItemsForArray = 0 +pp_data->cap[197]->IsButtonCap = 0 +pp_data->cap[197]->IsPadding = 0 +pp_data->cap[197]->IsAbsolute = 1 +pp_data->cap[197]->IsRange = 0 +pp_data->cap[197]->IsAlias = 0 +pp_data->cap[197]->IsStringRange = 0 +pp_data->cap[197]->IsDesignatorRange = 0 +pp_data->cap[197]->Reserved1 = 0x000000 +pp_data->cap[197]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[197]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[197]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[197]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[197]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[197]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[197]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[197]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[197]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[197]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[197]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[197]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[197]->NotRange.Usage = 0x0081 +pp_data->cap[197]->NotRange.Reserved1 = 0x0081 +pp_data->cap[197]->NotRange.StringIndex = 0 +pp_data->cap[197]->NotRange.Reserved2 = 0 +pp_data->cap[197]->NotRange.DesignatorIndex = 0 +pp_data->cap[197]->NotRange.Reserved3 = 0 +pp_data->cap[197]->NotRange.DataIndex = 110 +pp_data->cap[197]->NotRange.Reserved4 = 110 +pp_data->cap[197]->NotButton.HasNull = 0 +pp_data->cap[197]->NotButton.Reserved4 = 0x000000 +pp_data->cap[197]->NotButton.LogicalMin = 0 +pp_data->cap[197]->NotButton.LogicalMax = 127 +pp_data->cap[197]->NotButton.PhysicalMin = 0 +pp_data->cap[197]->NotButton.PhysicalMax = 0 +pp_data->cap[197]->Units = 0 +pp_data->cap[197]->UnitsExp = 0 + +pp_data->cap[198]->UsagePage = 0xFF01 +pp_data->cap[198]->ReportID = 0x81 +pp_data->cap[198]->BitPosition = 0 +pp_data->cap[198]->BitSize = 8 +pp_data->cap[198]->ReportCount = 1 +pp_data->cap[198]->BytePosition = 0x0017 +pp_data->cap[198]->BitCount = 8 +pp_data->cap[198]->BitField = 0x02 +pp_data->cap[198]->NextBytePosition = 0x0018 +pp_data->cap[198]->LinkCollection = 0x0004 +pp_data->cap[198]->LinkUsagePage = 0xFF01 +pp_data->cap[198]->LinkUsage = 0x0080 +pp_data->cap[198]->IsMultipleItemsForArray = 0 +pp_data->cap[198]->IsButtonCap = 0 +pp_data->cap[198]->IsPadding = 0 +pp_data->cap[198]->IsAbsolute = 1 +pp_data->cap[198]->IsRange = 0 +pp_data->cap[198]->IsAlias = 0 +pp_data->cap[198]->IsStringRange = 0 +pp_data->cap[198]->IsDesignatorRange = 0 +pp_data->cap[198]->Reserved1 = 0x000000 +pp_data->cap[198]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[198]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[198]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[198]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[198]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[198]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[198]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[198]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[198]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[198]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[198]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[198]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[198]->NotRange.Usage = 0x0081 +pp_data->cap[198]->NotRange.Reserved1 = 0x0081 +pp_data->cap[198]->NotRange.StringIndex = 0 +pp_data->cap[198]->NotRange.Reserved2 = 0 +pp_data->cap[198]->NotRange.DesignatorIndex = 0 +pp_data->cap[198]->NotRange.Reserved3 = 0 +pp_data->cap[198]->NotRange.DataIndex = 111 +pp_data->cap[198]->NotRange.Reserved4 = 111 +pp_data->cap[198]->NotButton.HasNull = 0 +pp_data->cap[198]->NotButton.Reserved4 = 0x000000 +pp_data->cap[198]->NotButton.LogicalMin = 0 +pp_data->cap[198]->NotButton.LogicalMax = 127 +pp_data->cap[198]->NotButton.PhysicalMin = 0 +pp_data->cap[198]->NotButton.PhysicalMax = 0 +pp_data->cap[198]->Units = 0 +pp_data->cap[198]->UnitsExp = 0 + +pp_data->cap[199]->UsagePage = 0xFF01 +pp_data->cap[199]->ReportID = 0x81 +pp_data->cap[199]->BitPosition = 0 +pp_data->cap[199]->BitSize = 8 +pp_data->cap[199]->ReportCount = 1 +pp_data->cap[199]->BytePosition = 0x0016 +pp_data->cap[199]->BitCount = 8 +pp_data->cap[199]->BitField = 0x02 +pp_data->cap[199]->NextBytePosition = 0x0017 +pp_data->cap[199]->LinkCollection = 0x0004 +pp_data->cap[199]->LinkUsagePage = 0xFF01 +pp_data->cap[199]->LinkUsage = 0x0080 +pp_data->cap[199]->IsMultipleItemsForArray = 0 +pp_data->cap[199]->IsButtonCap = 0 +pp_data->cap[199]->IsPadding = 0 +pp_data->cap[199]->IsAbsolute = 1 +pp_data->cap[199]->IsRange = 0 +pp_data->cap[199]->IsAlias = 0 +pp_data->cap[199]->IsStringRange = 0 +pp_data->cap[199]->IsDesignatorRange = 0 +pp_data->cap[199]->Reserved1 = 0x000000 +pp_data->cap[199]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[199]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[199]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[199]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[199]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[199]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[199]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[199]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[199]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[199]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[199]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[199]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[199]->NotRange.Usage = 0x0081 +pp_data->cap[199]->NotRange.Reserved1 = 0x0081 +pp_data->cap[199]->NotRange.StringIndex = 0 +pp_data->cap[199]->NotRange.Reserved2 = 0 +pp_data->cap[199]->NotRange.DesignatorIndex = 0 +pp_data->cap[199]->NotRange.Reserved3 = 0 +pp_data->cap[199]->NotRange.DataIndex = 112 +pp_data->cap[199]->NotRange.Reserved4 = 112 +pp_data->cap[199]->NotButton.HasNull = 0 +pp_data->cap[199]->NotButton.Reserved4 = 0x000000 +pp_data->cap[199]->NotButton.LogicalMin = 0 +pp_data->cap[199]->NotButton.LogicalMax = 127 +pp_data->cap[199]->NotButton.PhysicalMin = 0 +pp_data->cap[199]->NotButton.PhysicalMax = 0 +pp_data->cap[199]->Units = 0 +pp_data->cap[199]->UnitsExp = 0 + +pp_data->cap[200]->UsagePage = 0xFF01 +pp_data->cap[200]->ReportID = 0x81 +pp_data->cap[200]->BitPosition = 0 +pp_data->cap[200]->BitSize = 8 +pp_data->cap[200]->ReportCount = 1 +pp_data->cap[200]->BytePosition = 0x0015 +pp_data->cap[200]->BitCount = 8 +pp_data->cap[200]->BitField = 0x02 +pp_data->cap[200]->NextBytePosition = 0x0016 +pp_data->cap[200]->LinkCollection = 0x0004 +pp_data->cap[200]->LinkUsagePage = 0xFF01 +pp_data->cap[200]->LinkUsage = 0x0080 +pp_data->cap[200]->IsMultipleItemsForArray = 0 +pp_data->cap[200]->IsButtonCap = 0 +pp_data->cap[200]->IsPadding = 0 +pp_data->cap[200]->IsAbsolute = 1 +pp_data->cap[200]->IsRange = 0 +pp_data->cap[200]->IsAlias = 0 +pp_data->cap[200]->IsStringRange = 0 +pp_data->cap[200]->IsDesignatorRange = 0 +pp_data->cap[200]->Reserved1 = 0x000000 +pp_data->cap[200]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[200]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[200]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[200]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[200]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[200]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[200]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[200]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[200]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[200]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[200]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[200]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[200]->NotRange.Usage = 0x0081 +pp_data->cap[200]->NotRange.Reserved1 = 0x0081 +pp_data->cap[200]->NotRange.StringIndex = 0 +pp_data->cap[200]->NotRange.Reserved2 = 0 +pp_data->cap[200]->NotRange.DesignatorIndex = 0 +pp_data->cap[200]->NotRange.Reserved3 = 0 +pp_data->cap[200]->NotRange.DataIndex = 113 +pp_data->cap[200]->NotRange.Reserved4 = 113 +pp_data->cap[200]->NotButton.HasNull = 0 +pp_data->cap[200]->NotButton.Reserved4 = 0x000000 +pp_data->cap[200]->NotButton.LogicalMin = 0 +pp_data->cap[200]->NotButton.LogicalMax = 127 +pp_data->cap[200]->NotButton.PhysicalMin = 0 +pp_data->cap[200]->NotButton.PhysicalMax = 0 +pp_data->cap[200]->Units = 0 +pp_data->cap[200]->UnitsExp = 0 + +pp_data->cap[201]->UsagePage = 0xFF01 +pp_data->cap[201]->ReportID = 0x81 +pp_data->cap[201]->BitPosition = 0 +pp_data->cap[201]->BitSize = 8 +pp_data->cap[201]->ReportCount = 1 +pp_data->cap[201]->BytePosition = 0x0014 +pp_data->cap[201]->BitCount = 8 +pp_data->cap[201]->BitField = 0x02 +pp_data->cap[201]->NextBytePosition = 0x0015 +pp_data->cap[201]->LinkCollection = 0x0004 +pp_data->cap[201]->LinkUsagePage = 0xFF01 +pp_data->cap[201]->LinkUsage = 0x0080 +pp_data->cap[201]->IsMultipleItemsForArray = 0 +pp_data->cap[201]->IsButtonCap = 0 +pp_data->cap[201]->IsPadding = 0 +pp_data->cap[201]->IsAbsolute = 1 +pp_data->cap[201]->IsRange = 0 +pp_data->cap[201]->IsAlias = 0 +pp_data->cap[201]->IsStringRange = 0 +pp_data->cap[201]->IsDesignatorRange = 0 +pp_data->cap[201]->Reserved1 = 0x000000 +pp_data->cap[201]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[201]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[201]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[201]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[201]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[201]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[201]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[201]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[201]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[201]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[201]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[201]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[201]->NotRange.Usage = 0x0081 +pp_data->cap[201]->NotRange.Reserved1 = 0x0081 +pp_data->cap[201]->NotRange.StringIndex = 0 +pp_data->cap[201]->NotRange.Reserved2 = 0 +pp_data->cap[201]->NotRange.DesignatorIndex = 0 +pp_data->cap[201]->NotRange.Reserved3 = 0 +pp_data->cap[201]->NotRange.DataIndex = 114 +pp_data->cap[201]->NotRange.Reserved4 = 114 +pp_data->cap[201]->NotButton.HasNull = 0 +pp_data->cap[201]->NotButton.Reserved4 = 0x000000 +pp_data->cap[201]->NotButton.LogicalMin = 0 +pp_data->cap[201]->NotButton.LogicalMax = 127 +pp_data->cap[201]->NotButton.PhysicalMin = 0 +pp_data->cap[201]->NotButton.PhysicalMax = 0 +pp_data->cap[201]->Units = 0 +pp_data->cap[201]->UnitsExp = 0 + +pp_data->cap[202]->UsagePage = 0xFF01 +pp_data->cap[202]->ReportID = 0x81 +pp_data->cap[202]->BitPosition = 0 +pp_data->cap[202]->BitSize = 8 +pp_data->cap[202]->ReportCount = 1 +pp_data->cap[202]->BytePosition = 0x0013 +pp_data->cap[202]->BitCount = 8 +pp_data->cap[202]->BitField = 0x02 +pp_data->cap[202]->NextBytePosition = 0x0014 +pp_data->cap[202]->LinkCollection = 0x0004 +pp_data->cap[202]->LinkUsagePage = 0xFF01 +pp_data->cap[202]->LinkUsage = 0x0080 +pp_data->cap[202]->IsMultipleItemsForArray = 0 +pp_data->cap[202]->IsButtonCap = 0 +pp_data->cap[202]->IsPadding = 0 +pp_data->cap[202]->IsAbsolute = 1 +pp_data->cap[202]->IsRange = 0 +pp_data->cap[202]->IsAlias = 0 +pp_data->cap[202]->IsStringRange = 0 +pp_data->cap[202]->IsDesignatorRange = 0 +pp_data->cap[202]->Reserved1 = 0x000000 +pp_data->cap[202]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[202]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[202]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[202]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[202]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[202]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[202]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[202]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[202]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[202]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[202]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[202]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[202]->NotRange.Usage = 0x0081 +pp_data->cap[202]->NotRange.Reserved1 = 0x0081 +pp_data->cap[202]->NotRange.StringIndex = 0 +pp_data->cap[202]->NotRange.Reserved2 = 0 +pp_data->cap[202]->NotRange.DesignatorIndex = 0 +pp_data->cap[202]->NotRange.Reserved3 = 0 +pp_data->cap[202]->NotRange.DataIndex = 115 +pp_data->cap[202]->NotRange.Reserved4 = 115 +pp_data->cap[202]->NotButton.HasNull = 0 +pp_data->cap[202]->NotButton.Reserved4 = 0x000000 +pp_data->cap[202]->NotButton.LogicalMin = 0 +pp_data->cap[202]->NotButton.LogicalMax = 127 +pp_data->cap[202]->NotButton.PhysicalMin = 0 +pp_data->cap[202]->NotButton.PhysicalMax = 0 +pp_data->cap[202]->Units = 0 +pp_data->cap[202]->UnitsExp = 0 + +pp_data->cap[203]->UsagePage = 0xFF01 +pp_data->cap[203]->ReportID = 0x81 +pp_data->cap[203]->BitPosition = 0 +pp_data->cap[203]->BitSize = 8 +pp_data->cap[203]->ReportCount = 1 +pp_data->cap[203]->BytePosition = 0x0012 +pp_data->cap[203]->BitCount = 8 +pp_data->cap[203]->BitField = 0x02 +pp_data->cap[203]->NextBytePosition = 0x0013 +pp_data->cap[203]->LinkCollection = 0x0004 +pp_data->cap[203]->LinkUsagePage = 0xFF01 +pp_data->cap[203]->LinkUsage = 0x0080 +pp_data->cap[203]->IsMultipleItemsForArray = 0 +pp_data->cap[203]->IsButtonCap = 0 +pp_data->cap[203]->IsPadding = 0 +pp_data->cap[203]->IsAbsolute = 1 +pp_data->cap[203]->IsRange = 0 +pp_data->cap[203]->IsAlias = 0 +pp_data->cap[203]->IsStringRange = 0 +pp_data->cap[203]->IsDesignatorRange = 0 +pp_data->cap[203]->Reserved1 = 0x000000 +pp_data->cap[203]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[203]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[203]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[203]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[203]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[203]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[203]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[203]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[203]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[203]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[203]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[203]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[203]->NotRange.Usage = 0x0081 +pp_data->cap[203]->NotRange.Reserved1 = 0x0081 +pp_data->cap[203]->NotRange.StringIndex = 0 +pp_data->cap[203]->NotRange.Reserved2 = 0 +pp_data->cap[203]->NotRange.DesignatorIndex = 0 +pp_data->cap[203]->NotRange.Reserved3 = 0 +pp_data->cap[203]->NotRange.DataIndex = 116 +pp_data->cap[203]->NotRange.Reserved4 = 116 +pp_data->cap[203]->NotButton.HasNull = 0 +pp_data->cap[203]->NotButton.Reserved4 = 0x000000 +pp_data->cap[203]->NotButton.LogicalMin = 0 +pp_data->cap[203]->NotButton.LogicalMax = 127 +pp_data->cap[203]->NotButton.PhysicalMin = 0 +pp_data->cap[203]->NotButton.PhysicalMax = 0 +pp_data->cap[203]->Units = 0 +pp_data->cap[203]->UnitsExp = 0 + +pp_data->cap[204]->UsagePage = 0xFF01 +pp_data->cap[204]->ReportID = 0x81 +pp_data->cap[204]->BitPosition = 0 +pp_data->cap[204]->BitSize = 8 +pp_data->cap[204]->ReportCount = 1 +pp_data->cap[204]->BytePosition = 0x0011 +pp_data->cap[204]->BitCount = 8 +pp_data->cap[204]->BitField = 0x02 +pp_data->cap[204]->NextBytePosition = 0x0012 +pp_data->cap[204]->LinkCollection = 0x0004 +pp_data->cap[204]->LinkUsagePage = 0xFF01 +pp_data->cap[204]->LinkUsage = 0x0080 +pp_data->cap[204]->IsMultipleItemsForArray = 0 +pp_data->cap[204]->IsButtonCap = 0 +pp_data->cap[204]->IsPadding = 0 +pp_data->cap[204]->IsAbsolute = 1 +pp_data->cap[204]->IsRange = 0 +pp_data->cap[204]->IsAlias = 0 +pp_data->cap[204]->IsStringRange = 0 +pp_data->cap[204]->IsDesignatorRange = 0 +pp_data->cap[204]->Reserved1 = 0x000000 +pp_data->cap[204]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[204]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[204]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[204]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[204]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[204]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[204]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[204]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[204]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[204]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[204]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[204]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[204]->NotRange.Usage = 0x0081 +pp_data->cap[204]->NotRange.Reserved1 = 0x0081 +pp_data->cap[204]->NotRange.StringIndex = 0 +pp_data->cap[204]->NotRange.Reserved2 = 0 +pp_data->cap[204]->NotRange.DesignatorIndex = 0 +pp_data->cap[204]->NotRange.Reserved3 = 0 +pp_data->cap[204]->NotRange.DataIndex = 117 +pp_data->cap[204]->NotRange.Reserved4 = 117 +pp_data->cap[204]->NotButton.HasNull = 0 +pp_data->cap[204]->NotButton.Reserved4 = 0x000000 +pp_data->cap[204]->NotButton.LogicalMin = 0 +pp_data->cap[204]->NotButton.LogicalMax = 127 +pp_data->cap[204]->NotButton.PhysicalMin = 0 +pp_data->cap[204]->NotButton.PhysicalMax = 0 +pp_data->cap[204]->Units = 0 +pp_data->cap[204]->UnitsExp = 0 + +pp_data->cap[205]->UsagePage = 0xFF01 +pp_data->cap[205]->ReportID = 0x81 +pp_data->cap[205]->BitPosition = 0 +pp_data->cap[205]->BitSize = 8 +pp_data->cap[205]->ReportCount = 1 +pp_data->cap[205]->BytePosition = 0x0010 +pp_data->cap[205]->BitCount = 8 +pp_data->cap[205]->BitField = 0x02 +pp_data->cap[205]->NextBytePosition = 0x0011 +pp_data->cap[205]->LinkCollection = 0x0004 +pp_data->cap[205]->LinkUsagePage = 0xFF01 +pp_data->cap[205]->LinkUsage = 0x0080 +pp_data->cap[205]->IsMultipleItemsForArray = 0 +pp_data->cap[205]->IsButtonCap = 0 +pp_data->cap[205]->IsPadding = 0 +pp_data->cap[205]->IsAbsolute = 1 +pp_data->cap[205]->IsRange = 0 +pp_data->cap[205]->IsAlias = 0 +pp_data->cap[205]->IsStringRange = 0 +pp_data->cap[205]->IsDesignatorRange = 0 +pp_data->cap[205]->Reserved1 = 0x000000 +pp_data->cap[205]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[205]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[205]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[205]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[205]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[205]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[205]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[205]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[205]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[205]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[205]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[205]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[205]->NotRange.Usage = 0x0081 +pp_data->cap[205]->NotRange.Reserved1 = 0x0081 +pp_data->cap[205]->NotRange.StringIndex = 0 +pp_data->cap[205]->NotRange.Reserved2 = 0 +pp_data->cap[205]->NotRange.DesignatorIndex = 0 +pp_data->cap[205]->NotRange.Reserved3 = 0 +pp_data->cap[205]->NotRange.DataIndex = 118 +pp_data->cap[205]->NotRange.Reserved4 = 118 +pp_data->cap[205]->NotButton.HasNull = 0 +pp_data->cap[205]->NotButton.Reserved4 = 0x000000 +pp_data->cap[205]->NotButton.LogicalMin = 0 +pp_data->cap[205]->NotButton.LogicalMax = 127 +pp_data->cap[205]->NotButton.PhysicalMin = 0 +pp_data->cap[205]->NotButton.PhysicalMax = 0 +pp_data->cap[205]->Units = 0 +pp_data->cap[205]->UnitsExp = 0 + +pp_data->cap[206]->UsagePage = 0xFF01 +pp_data->cap[206]->ReportID = 0x81 +pp_data->cap[206]->BitPosition = 0 +pp_data->cap[206]->BitSize = 8 +pp_data->cap[206]->ReportCount = 1 +pp_data->cap[206]->BytePosition = 0x000F +pp_data->cap[206]->BitCount = 8 +pp_data->cap[206]->BitField = 0x02 +pp_data->cap[206]->NextBytePosition = 0x0010 +pp_data->cap[206]->LinkCollection = 0x0004 +pp_data->cap[206]->LinkUsagePage = 0xFF01 +pp_data->cap[206]->LinkUsage = 0x0080 +pp_data->cap[206]->IsMultipleItemsForArray = 0 +pp_data->cap[206]->IsButtonCap = 0 +pp_data->cap[206]->IsPadding = 0 +pp_data->cap[206]->IsAbsolute = 1 +pp_data->cap[206]->IsRange = 0 +pp_data->cap[206]->IsAlias = 0 +pp_data->cap[206]->IsStringRange = 0 +pp_data->cap[206]->IsDesignatorRange = 0 +pp_data->cap[206]->Reserved1 = 0x000000 +pp_data->cap[206]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[206]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[206]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[206]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[206]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[206]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[206]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[206]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[206]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[206]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[206]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[206]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[206]->NotRange.Usage = 0x0081 +pp_data->cap[206]->NotRange.Reserved1 = 0x0081 +pp_data->cap[206]->NotRange.StringIndex = 0 +pp_data->cap[206]->NotRange.Reserved2 = 0 +pp_data->cap[206]->NotRange.DesignatorIndex = 0 +pp_data->cap[206]->NotRange.Reserved3 = 0 +pp_data->cap[206]->NotRange.DataIndex = 119 +pp_data->cap[206]->NotRange.Reserved4 = 119 +pp_data->cap[206]->NotButton.HasNull = 0 +pp_data->cap[206]->NotButton.Reserved4 = 0x000000 +pp_data->cap[206]->NotButton.LogicalMin = 0 +pp_data->cap[206]->NotButton.LogicalMax = 127 +pp_data->cap[206]->NotButton.PhysicalMin = 0 +pp_data->cap[206]->NotButton.PhysicalMax = 0 +pp_data->cap[206]->Units = 0 +pp_data->cap[206]->UnitsExp = 0 + +pp_data->cap[207]->UsagePage = 0xFF01 +pp_data->cap[207]->ReportID = 0x81 +pp_data->cap[207]->BitPosition = 0 +pp_data->cap[207]->BitSize = 8 +pp_data->cap[207]->ReportCount = 1 +pp_data->cap[207]->BytePosition = 0x000E +pp_data->cap[207]->BitCount = 8 +pp_data->cap[207]->BitField = 0x02 +pp_data->cap[207]->NextBytePosition = 0x000F +pp_data->cap[207]->LinkCollection = 0x0004 +pp_data->cap[207]->LinkUsagePage = 0xFF01 +pp_data->cap[207]->LinkUsage = 0x0080 +pp_data->cap[207]->IsMultipleItemsForArray = 0 +pp_data->cap[207]->IsButtonCap = 0 +pp_data->cap[207]->IsPadding = 0 +pp_data->cap[207]->IsAbsolute = 1 +pp_data->cap[207]->IsRange = 0 +pp_data->cap[207]->IsAlias = 0 +pp_data->cap[207]->IsStringRange = 0 +pp_data->cap[207]->IsDesignatorRange = 0 +pp_data->cap[207]->Reserved1 = 0x000000 +pp_data->cap[207]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[207]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[207]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[207]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[207]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[207]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[207]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[207]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[207]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[207]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[207]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[207]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[207]->NotRange.Usage = 0x0081 +pp_data->cap[207]->NotRange.Reserved1 = 0x0081 +pp_data->cap[207]->NotRange.StringIndex = 0 +pp_data->cap[207]->NotRange.Reserved2 = 0 +pp_data->cap[207]->NotRange.DesignatorIndex = 0 +pp_data->cap[207]->NotRange.Reserved3 = 0 +pp_data->cap[207]->NotRange.DataIndex = 120 +pp_data->cap[207]->NotRange.Reserved4 = 120 +pp_data->cap[207]->NotButton.HasNull = 0 +pp_data->cap[207]->NotButton.Reserved4 = 0x000000 +pp_data->cap[207]->NotButton.LogicalMin = 0 +pp_data->cap[207]->NotButton.LogicalMax = 127 +pp_data->cap[207]->NotButton.PhysicalMin = 0 +pp_data->cap[207]->NotButton.PhysicalMax = 0 +pp_data->cap[207]->Units = 0 +pp_data->cap[207]->UnitsExp = 0 + +pp_data->cap[208]->UsagePage = 0xFF01 +pp_data->cap[208]->ReportID = 0x81 +pp_data->cap[208]->BitPosition = 0 +pp_data->cap[208]->BitSize = 8 +pp_data->cap[208]->ReportCount = 1 +pp_data->cap[208]->BytePosition = 0x000D +pp_data->cap[208]->BitCount = 8 +pp_data->cap[208]->BitField = 0x02 +pp_data->cap[208]->NextBytePosition = 0x000E +pp_data->cap[208]->LinkCollection = 0x0004 +pp_data->cap[208]->LinkUsagePage = 0xFF01 +pp_data->cap[208]->LinkUsage = 0x0080 +pp_data->cap[208]->IsMultipleItemsForArray = 0 +pp_data->cap[208]->IsButtonCap = 0 +pp_data->cap[208]->IsPadding = 0 +pp_data->cap[208]->IsAbsolute = 1 +pp_data->cap[208]->IsRange = 0 +pp_data->cap[208]->IsAlias = 0 +pp_data->cap[208]->IsStringRange = 0 +pp_data->cap[208]->IsDesignatorRange = 0 +pp_data->cap[208]->Reserved1 = 0x000000 +pp_data->cap[208]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[208]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[208]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[208]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[208]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[208]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[208]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[208]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[208]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[208]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[208]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[208]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[208]->NotRange.Usage = 0x0081 +pp_data->cap[208]->NotRange.Reserved1 = 0x0081 +pp_data->cap[208]->NotRange.StringIndex = 0 +pp_data->cap[208]->NotRange.Reserved2 = 0 +pp_data->cap[208]->NotRange.DesignatorIndex = 0 +pp_data->cap[208]->NotRange.Reserved3 = 0 +pp_data->cap[208]->NotRange.DataIndex = 121 +pp_data->cap[208]->NotRange.Reserved4 = 121 +pp_data->cap[208]->NotButton.HasNull = 0 +pp_data->cap[208]->NotButton.Reserved4 = 0x000000 +pp_data->cap[208]->NotButton.LogicalMin = 0 +pp_data->cap[208]->NotButton.LogicalMax = 127 +pp_data->cap[208]->NotButton.PhysicalMin = 0 +pp_data->cap[208]->NotButton.PhysicalMax = 0 +pp_data->cap[208]->Units = 0 +pp_data->cap[208]->UnitsExp = 0 + +pp_data->cap[209]->UsagePage = 0xFF01 +pp_data->cap[209]->ReportID = 0x81 +pp_data->cap[209]->BitPosition = 0 +pp_data->cap[209]->BitSize = 8 +pp_data->cap[209]->ReportCount = 1 +pp_data->cap[209]->BytePosition = 0x000C +pp_data->cap[209]->BitCount = 8 +pp_data->cap[209]->BitField = 0x02 +pp_data->cap[209]->NextBytePosition = 0x000D +pp_data->cap[209]->LinkCollection = 0x0004 +pp_data->cap[209]->LinkUsagePage = 0xFF01 +pp_data->cap[209]->LinkUsage = 0x0080 +pp_data->cap[209]->IsMultipleItemsForArray = 0 +pp_data->cap[209]->IsButtonCap = 0 +pp_data->cap[209]->IsPadding = 0 +pp_data->cap[209]->IsAbsolute = 1 +pp_data->cap[209]->IsRange = 0 +pp_data->cap[209]->IsAlias = 0 +pp_data->cap[209]->IsStringRange = 0 +pp_data->cap[209]->IsDesignatorRange = 0 +pp_data->cap[209]->Reserved1 = 0x000000 +pp_data->cap[209]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[209]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[209]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[209]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[209]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[209]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[209]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[209]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[209]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[209]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[209]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[209]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[209]->NotRange.Usage = 0x0081 +pp_data->cap[209]->NotRange.Reserved1 = 0x0081 +pp_data->cap[209]->NotRange.StringIndex = 0 +pp_data->cap[209]->NotRange.Reserved2 = 0 +pp_data->cap[209]->NotRange.DesignatorIndex = 0 +pp_data->cap[209]->NotRange.Reserved3 = 0 +pp_data->cap[209]->NotRange.DataIndex = 122 +pp_data->cap[209]->NotRange.Reserved4 = 122 +pp_data->cap[209]->NotButton.HasNull = 0 +pp_data->cap[209]->NotButton.Reserved4 = 0x000000 +pp_data->cap[209]->NotButton.LogicalMin = 0 +pp_data->cap[209]->NotButton.LogicalMax = 127 +pp_data->cap[209]->NotButton.PhysicalMin = 0 +pp_data->cap[209]->NotButton.PhysicalMax = 0 +pp_data->cap[209]->Units = 0 +pp_data->cap[209]->UnitsExp = 0 + +pp_data->cap[210]->UsagePage = 0xFF01 +pp_data->cap[210]->ReportID = 0x81 +pp_data->cap[210]->BitPosition = 0 +pp_data->cap[210]->BitSize = 8 +pp_data->cap[210]->ReportCount = 1 +pp_data->cap[210]->BytePosition = 0x000B +pp_data->cap[210]->BitCount = 8 +pp_data->cap[210]->BitField = 0x02 +pp_data->cap[210]->NextBytePosition = 0x000C +pp_data->cap[210]->LinkCollection = 0x0004 +pp_data->cap[210]->LinkUsagePage = 0xFF01 +pp_data->cap[210]->LinkUsage = 0x0080 +pp_data->cap[210]->IsMultipleItemsForArray = 0 +pp_data->cap[210]->IsButtonCap = 0 +pp_data->cap[210]->IsPadding = 0 +pp_data->cap[210]->IsAbsolute = 1 +pp_data->cap[210]->IsRange = 0 +pp_data->cap[210]->IsAlias = 0 +pp_data->cap[210]->IsStringRange = 0 +pp_data->cap[210]->IsDesignatorRange = 0 +pp_data->cap[210]->Reserved1 = 0x000000 +pp_data->cap[210]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[210]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[210]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[210]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[210]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[210]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[210]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[210]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[210]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[210]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[210]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[210]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[210]->NotRange.Usage = 0x0081 +pp_data->cap[210]->NotRange.Reserved1 = 0x0081 +pp_data->cap[210]->NotRange.StringIndex = 0 +pp_data->cap[210]->NotRange.Reserved2 = 0 +pp_data->cap[210]->NotRange.DesignatorIndex = 0 +pp_data->cap[210]->NotRange.Reserved3 = 0 +pp_data->cap[210]->NotRange.DataIndex = 123 +pp_data->cap[210]->NotRange.Reserved4 = 123 +pp_data->cap[210]->NotButton.HasNull = 0 +pp_data->cap[210]->NotButton.Reserved4 = 0x000000 +pp_data->cap[210]->NotButton.LogicalMin = 0 +pp_data->cap[210]->NotButton.LogicalMax = 127 +pp_data->cap[210]->NotButton.PhysicalMin = 0 +pp_data->cap[210]->NotButton.PhysicalMax = 0 +pp_data->cap[210]->Units = 0 +pp_data->cap[210]->UnitsExp = 0 + +pp_data->cap[211]->UsagePage = 0xFF01 +pp_data->cap[211]->ReportID = 0x81 +pp_data->cap[211]->BitPosition = 0 +pp_data->cap[211]->BitSize = 8 +pp_data->cap[211]->ReportCount = 1 +pp_data->cap[211]->BytePosition = 0x000A +pp_data->cap[211]->BitCount = 8 +pp_data->cap[211]->BitField = 0x02 +pp_data->cap[211]->NextBytePosition = 0x000B +pp_data->cap[211]->LinkCollection = 0x0004 +pp_data->cap[211]->LinkUsagePage = 0xFF01 +pp_data->cap[211]->LinkUsage = 0x0080 +pp_data->cap[211]->IsMultipleItemsForArray = 0 +pp_data->cap[211]->IsButtonCap = 0 +pp_data->cap[211]->IsPadding = 0 +pp_data->cap[211]->IsAbsolute = 1 +pp_data->cap[211]->IsRange = 0 +pp_data->cap[211]->IsAlias = 0 +pp_data->cap[211]->IsStringRange = 0 +pp_data->cap[211]->IsDesignatorRange = 0 +pp_data->cap[211]->Reserved1 = 0x000000 +pp_data->cap[211]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[211]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[211]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[211]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[211]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[211]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[211]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[211]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[211]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[211]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[211]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[211]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[211]->NotRange.Usage = 0x0081 +pp_data->cap[211]->NotRange.Reserved1 = 0x0081 +pp_data->cap[211]->NotRange.StringIndex = 0 +pp_data->cap[211]->NotRange.Reserved2 = 0 +pp_data->cap[211]->NotRange.DesignatorIndex = 0 +pp_data->cap[211]->NotRange.Reserved3 = 0 +pp_data->cap[211]->NotRange.DataIndex = 124 +pp_data->cap[211]->NotRange.Reserved4 = 124 +pp_data->cap[211]->NotButton.HasNull = 0 +pp_data->cap[211]->NotButton.Reserved4 = 0x000000 +pp_data->cap[211]->NotButton.LogicalMin = 0 +pp_data->cap[211]->NotButton.LogicalMax = 127 +pp_data->cap[211]->NotButton.PhysicalMin = 0 +pp_data->cap[211]->NotButton.PhysicalMax = 0 +pp_data->cap[211]->Units = 0 +pp_data->cap[211]->UnitsExp = 0 + +pp_data->cap[212]->UsagePage = 0xFF01 +pp_data->cap[212]->ReportID = 0x81 +pp_data->cap[212]->BitPosition = 0 +pp_data->cap[212]->BitSize = 8 +pp_data->cap[212]->ReportCount = 1 +pp_data->cap[212]->BytePosition = 0x0009 +pp_data->cap[212]->BitCount = 8 +pp_data->cap[212]->BitField = 0x02 +pp_data->cap[212]->NextBytePosition = 0x000A +pp_data->cap[212]->LinkCollection = 0x0004 +pp_data->cap[212]->LinkUsagePage = 0xFF01 +pp_data->cap[212]->LinkUsage = 0x0080 +pp_data->cap[212]->IsMultipleItemsForArray = 0 +pp_data->cap[212]->IsButtonCap = 0 +pp_data->cap[212]->IsPadding = 0 +pp_data->cap[212]->IsAbsolute = 1 +pp_data->cap[212]->IsRange = 0 +pp_data->cap[212]->IsAlias = 0 +pp_data->cap[212]->IsStringRange = 0 +pp_data->cap[212]->IsDesignatorRange = 0 +pp_data->cap[212]->Reserved1 = 0x000000 +pp_data->cap[212]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[212]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[212]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[212]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[212]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[212]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[212]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[212]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[212]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[212]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[212]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[212]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[212]->NotRange.Usage = 0x0081 +pp_data->cap[212]->NotRange.Reserved1 = 0x0081 +pp_data->cap[212]->NotRange.StringIndex = 0 +pp_data->cap[212]->NotRange.Reserved2 = 0 +pp_data->cap[212]->NotRange.DesignatorIndex = 0 +pp_data->cap[212]->NotRange.Reserved3 = 0 +pp_data->cap[212]->NotRange.DataIndex = 125 +pp_data->cap[212]->NotRange.Reserved4 = 125 +pp_data->cap[212]->NotButton.HasNull = 0 +pp_data->cap[212]->NotButton.Reserved4 = 0x000000 +pp_data->cap[212]->NotButton.LogicalMin = 0 +pp_data->cap[212]->NotButton.LogicalMax = 127 +pp_data->cap[212]->NotButton.PhysicalMin = 0 +pp_data->cap[212]->NotButton.PhysicalMax = 0 +pp_data->cap[212]->Units = 0 +pp_data->cap[212]->UnitsExp = 0 + +pp_data->cap[213]->UsagePage = 0xFF01 +pp_data->cap[213]->ReportID = 0x81 +pp_data->cap[213]->BitPosition = 0 +pp_data->cap[213]->BitSize = 8 +pp_data->cap[213]->ReportCount = 1 +pp_data->cap[213]->BytePosition = 0x0008 +pp_data->cap[213]->BitCount = 8 +pp_data->cap[213]->BitField = 0x02 +pp_data->cap[213]->NextBytePosition = 0x0009 +pp_data->cap[213]->LinkCollection = 0x0004 +pp_data->cap[213]->LinkUsagePage = 0xFF01 +pp_data->cap[213]->LinkUsage = 0x0080 +pp_data->cap[213]->IsMultipleItemsForArray = 0 +pp_data->cap[213]->IsButtonCap = 0 +pp_data->cap[213]->IsPadding = 0 +pp_data->cap[213]->IsAbsolute = 1 +pp_data->cap[213]->IsRange = 0 +pp_data->cap[213]->IsAlias = 0 +pp_data->cap[213]->IsStringRange = 0 +pp_data->cap[213]->IsDesignatorRange = 0 +pp_data->cap[213]->Reserved1 = 0x000000 +pp_data->cap[213]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[213]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[213]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[213]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[213]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[213]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[213]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[213]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[213]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[213]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[213]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[213]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[213]->NotRange.Usage = 0x0081 +pp_data->cap[213]->NotRange.Reserved1 = 0x0081 +pp_data->cap[213]->NotRange.StringIndex = 0 +pp_data->cap[213]->NotRange.Reserved2 = 0 +pp_data->cap[213]->NotRange.DesignatorIndex = 0 +pp_data->cap[213]->NotRange.Reserved3 = 0 +pp_data->cap[213]->NotRange.DataIndex = 126 +pp_data->cap[213]->NotRange.Reserved4 = 126 +pp_data->cap[213]->NotButton.HasNull = 0 +pp_data->cap[213]->NotButton.Reserved4 = 0x000000 +pp_data->cap[213]->NotButton.LogicalMin = 0 +pp_data->cap[213]->NotButton.LogicalMax = 127 +pp_data->cap[213]->NotButton.PhysicalMin = 0 +pp_data->cap[213]->NotButton.PhysicalMax = 0 +pp_data->cap[213]->Units = 0 +pp_data->cap[213]->UnitsExp = 0 + +pp_data->cap[214]->UsagePage = 0xFF01 +pp_data->cap[214]->ReportID = 0x81 +pp_data->cap[214]->BitPosition = 0 +pp_data->cap[214]->BitSize = 8 +pp_data->cap[214]->ReportCount = 1 +pp_data->cap[214]->BytePosition = 0x0007 +pp_data->cap[214]->BitCount = 8 +pp_data->cap[214]->BitField = 0x02 +pp_data->cap[214]->NextBytePosition = 0x0008 +pp_data->cap[214]->LinkCollection = 0x0004 +pp_data->cap[214]->LinkUsagePage = 0xFF01 +pp_data->cap[214]->LinkUsage = 0x0080 +pp_data->cap[214]->IsMultipleItemsForArray = 0 +pp_data->cap[214]->IsButtonCap = 0 +pp_data->cap[214]->IsPadding = 0 +pp_data->cap[214]->IsAbsolute = 1 +pp_data->cap[214]->IsRange = 0 +pp_data->cap[214]->IsAlias = 0 +pp_data->cap[214]->IsStringRange = 0 +pp_data->cap[214]->IsDesignatorRange = 0 +pp_data->cap[214]->Reserved1 = 0x000000 +pp_data->cap[214]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[214]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[214]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[214]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[214]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[214]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[214]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[214]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[214]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[214]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[214]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[214]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[214]->NotRange.Usage = 0x0081 +pp_data->cap[214]->NotRange.Reserved1 = 0x0081 +pp_data->cap[214]->NotRange.StringIndex = 0 +pp_data->cap[214]->NotRange.Reserved2 = 0 +pp_data->cap[214]->NotRange.DesignatorIndex = 0 +pp_data->cap[214]->NotRange.Reserved3 = 0 +pp_data->cap[214]->NotRange.DataIndex = 127 +pp_data->cap[214]->NotRange.Reserved4 = 127 +pp_data->cap[214]->NotButton.HasNull = 0 +pp_data->cap[214]->NotButton.Reserved4 = 0x000000 +pp_data->cap[214]->NotButton.LogicalMin = 0 +pp_data->cap[214]->NotButton.LogicalMax = 127 +pp_data->cap[214]->NotButton.PhysicalMin = 0 +pp_data->cap[214]->NotButton.PhysicalMax = 0 +pp_data->cap[214]->Units = 0 +pp_data->cap[214]->UnitsExp = 0 + +pp_data->cap[215]->UsagePage = 0xFF01 +pp_data->cap[215]->ReportID = 0x81 +pp_data->cap[215]->BitPosition = 0 +pp_data->cap[215]->BitSize = 8 +pp_data->cap[215]->ReportCount = 1 +pp_data->cap[215]->BytePosition = 0x0006 +pp_data->cap[215]->BitCount = 8 +pp_data->cap[215]->BitField = 0x02 +pp_data->cap[215]->NextBytePosition = 0x0007 +pp_data->cap[215]->LinkCollection = 0x0004 +pp_data->cap[215]->LinkUsagePage = 0xFF01 +pp_data->cap[215]->LinkUsage = 0x0080 +pp_data->cap[215]->IsMultipleItemsForArray = 0 +pp_data->cap[215]->IsButtonCap = 0 +pp_data->cap[215]->IsPadding = 0 +pp_data->cap[215]->IsAbsolute = 1 +pp_data->cap[215]->IsRange = 0 +pp_data->cap[215]->IsAlias = 0 +pp_data->cap[215]->IsStringRange = 0 +pp_data->cap[215]->IsDesignatorRange = 0 +pp_data->cap[215]->Reserved1 = 0x000000 +pp_data->cap[215]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[215]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[215]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[215]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[215]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[215]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[215]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[215]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[215]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[215]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[215]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[215]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[215]->NotRange.Usage = 0x0081 +pp_data->cap[215]->NotRange.Reserved1 = 0x0081 +pp_data->cap[215]->NotRange.StringIndex = 0 +pp_data->cap[215]->NotRange.Reserved2 = 0 +pp_data->cap[215]->NotRange.DesignatorIndex = 0 +pp_data->cap[215]->NotRange.Reserved3 = 0 +pp_data->cap[215]->NotRange.DataIndex = 128 +pp_data->cap[215]->NotRange.Reserved4 = 128 +pp_data->cap[215]->NotButton.HasNull = 0 +pp_data->cap[215]->NotButton.Reserved4 = 0x000000 +pp_data->cap[215]->NotButton.LogicalMin = 0 +pp_data->cap[215]->NotButton.LogicalMax = 127 +pp_data->cap[215]->NotButton.PhysicalMin = 0 +pp_data->cap[215]->NotButton.PhysicalMax = 0 +pp_data->cap[215]->Units = 0 +pp_data->cap[215]->UnitsExp = 0 + +pp_data->cap[216]->UsagePage = 0xFF01 +pp_data->cap[216]->ReportID = 0x81 +pp_data->cap[216]->BitPosition = 0 +pp_data->cap[216]->BitSize = 8 +pp_data->cap[216]->ReportCount = 1 +pp_data->cap[216]->BytePosition = 0x0005 +pp_data->cap[216]->BitCount = 8 +pp_data->cap[216]->BitField = 0x02 +pp_data->cap[216]->NextBytePosition = 0x0006 +pp_data->cap[216]->LinkCollection = 0x0004 +pp_data->cap[216]->LinkUsagePage = 0xFF01 +pp_data->cap[216]->LinkUsage = 0x0080 +pp_data->cap[216]->IsMultipleItemsForArray = 0 +pp_data->cap[216]->IsButtonCap = 0 +pp_data->cap[216]->IsPadding = 0 +pp_data->cap[216]->IsAbsolute = 1 +pp_data->cap[216]->IsRange = 0 +pp_data->cap[216]->IsAlias = 0 +pp_data->cap[216]->IsStringRange = 0 +pp_data->cap[216]->IsDesignatorRange = 0 +pp_data->cap[216]->Reserved1 = 0x000000 +pp_data->cap[216]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[216]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[216]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[216]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[216]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[216]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[216]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[216]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[216]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[216]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[216]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[216]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[216]->NotRange.Usage = 0x0081 +pp_data->cap[216]->NotRange.Reserved1 = 0x0081 +pp_data->cap[216]->NotRange.StringIndex = 0 +pp_data->cap[216]->NotRange.Reserved2 = 0 +pp_data->cap[216]->NotRange.DesignatorIndex = 0 +pp_data->cap[216]->NotRange.Reserved3 = 0 +pp_data->cap[216]->NotRange.DataIndex = 129 +pp_data->cap[216]->NotRange.Reserved4 = 129 +pp_data->cap[216]->NotButton.HasNull = 0 +pp_data->cap[216]->NotButton.Reserved4 = 0x000000 +pp_data->cap[216]->NotButton.LogicalMin = 0 +pp_data->cap[216]->NotButton.LogicalMax = 127 +pp_data->cap[216]->NotButton.PhysicalMin = 0 +pp_data->cap[216]->NotButton.PhysicalMax = 0 +pp_data->cap[216]->Units = 0 +pp_data->cap[216]->UnitsExp = 0 + +pp_data->cap[217]->UsagePage = 0xFF01 +pp_data->cap[217]->ReportID = 0x81 +pp_data->cap[217]->BitPosition = 0 +pp_data->cap[217]->BitSize = 8 +pp_data->cap[217]->ReportCount = 1 +pp_data->cap[217]->BytePosition = 0x0004 +pp_data->cap[217]->BitCount = 8 +pp_data->cap[217]->BitField = 0x02 +pp_data->cap[217]->NextBytePosition = 0x0005 +pp_data->cap[217]->LinkCollection = 0x0004 +pp_data->cap[217]->LinkUsagePage = 0xFF01 +pp_data->cap[217]->LinkUsage = 0x0080 +pp_data->cap[217]->IsMultipleItemsForArray = 0 +pp_data->cap[217]->IsButtonCap = 0 +pp_data->cap[217]->IsPadding = 0 +pp_data->cap[217]->IsAbsolute = 1 +pp_data->cap[217]->IsRange = 0 +pp_data->cap[217]->IsAlias = 0 +pp_data->cap[217]->IsStringRange = 0 +pp_data->cap[217]->IsDesignatorRange = 0 +pp_data->cap[217]->Reserved1 = 0x000000 +pp_data->cap[217]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[217]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[217]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[217]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[217]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[217]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[217]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[217]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[217]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[217]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[217]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[217]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[217]->NotRange.Usage = 0x0081 +pp_data->cap[217]->NotRange.Reserved1 = 0x0081 +pp_data->cap[217]->NotRange.StringIndex = 0 +pp_data->cap[217]->NotRange.Reserved2 = 0 +pp_data->cap[217]->NotRange.DesignatorIndex = 0 +pp_data->cap[217]->NotRange.Reserved3 = 0 +pp_data->cap[217]->NotRange.DataIndex = 130 +pp_data->cap[217]->NotRange.Reserved4 = 130 +pp_data->cap[217]->NotButton.HasNull = 0 +pp_data->cap[217]->NotButton.Reserved4 = 0x000000 +pp_data->cap[217]->NotButton.LogicalMin = 0 +pp_data->cap[217]->NotButton.LogicalMax = 127 +pp_data->cap[217]->NotButton.PhysicalMin = 0 +pp_data->cap[217]->NotButton.PhysicalMax = 0 +pp_data->cap[217]->Units = 0 +pp_data->cap[217]->UnitsExp = 0 + +pp_data->cap[218]->UsagePage = 0xFF01 +pp_data->cap[218]->ReportID = 0x81 +pp_data->cap[218]->BitPosition = 0 +pp_data->cap[218]->BitSize = 8 +pp_data->cap[218]->ReportCount = 1 +pp_data->cap[218]->BytePosition = 0x0003 +pp_data->cap[218]->BitCount = 8 +pp_data->cap[218]->BitField = 0x02 +pp_data->cap[218]->NextBytePosition = 0x0004 +pp_data->cap[218]->LinkCollection = 0x0004 +pp_data->cap[218]->LinkUsagePage = 0xFF01 +pp_data->cap[218]->LinkUsage = 0x0080 +pp_data->cap[218]->IsMultipleItemsForArray = 0 +pp_data->cap[218]->IsButtonCap = 0 +pp_data->cap[218]->IsPadding = 0 +pp_data->cap[218]->IsAbsolute = 1 +pp_data->cap[218]->IsRange = 0 +pp_data->cap[218]->IsAlias = 0 +pp_data->cap[218]->IsStringRange = 0 +pp_data->cap[218]->IsDesignatorRange = 0 +pp_data->cap[218]->Reserved1 = 0x000000 +pp_data->cap[218]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[218]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[218]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[218]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[218]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[218]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[218]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[218]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[218]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[218]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[218]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[218]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[218]->NotRange.Usage = 0x0081 +pp_data->cap[218]->NotRange.Reserved1 = 0x0081 +pp_data->cap[218]->NotRange.StringIndex = 0 +pp_data->cap[218]->NotRange.Reserved2 = 0 +pp_data->cap[218]->NotRange.DesignatorIndex = 0 +pp_data->cap[218]->NotRange.Reserved3 = 0 +pp_data->cap[218]->NotRange.DataIndex = 131 +pp_data->cap[218]->NotRange.Reserved4 = 131 +pp_data->cap[218]->NotButton.HasNull = 0 +pp_data->cap[218]->NotButton.Reserved4 = 0x000000 +pp_data->cap[218]->NotButton.LogicalMin = 0 +pp_data->cap[218]->NotButton.LogicalMax = 127 +pp_data->cap[218]->NotButton.PhysicalMin = 0 +pp_data->cap[218]->NotButton.PhysicalMax = 0 +pp_data->cap[218]->Units = 0 +pp_data->cap[218]->UnitsExp = 0 + +pp_data->cap[219]->UsagePage = 0xFF01 +pp_data->cap[219]->ReportID = 0x81 +pp_data->cap[219]->BitPosition = 0 +pp_data->cap[219]->BitSize = 8 +pp_data->cap[219]->ReportCount = 1 +pp_data->cap[219]->BytePosition = 0x0002 +pp_data->cap[219]->BitCount = 8 +pp_data->cap[219]->BitField = 0x02 +pp_data->cap[219]->NextBytePosition = 0x0003 +pp_data->cap[219]->LinkCollection = 0x0004 +pp_data->cap[219]->LinkUsagePage = 0xFF01 +pp_data->cap[219]->LinkUsage = 0x0080 +pp_data->cap[219]->IsMultipleItemsForArray = 0 +pp_data->cap[219]->IsButtonCap = 0 +pp_data->cap[219]->IsPadding = 0 +pp_data->cap[219]->IsAbsolute = 1 +pp_data->cap[219]->IsRange = 0 +pp_data->cap[219]->IsAlias = 0 +pp_data->cap[219]->IsStringRange = 0 +pp_data->cap[219]->IsDesignatorRange = 0 +pp_data->cap[219]->Reserved1 = 0x000000 +pp_data->cap[219]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[219]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[219]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[219]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[219]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[219]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[219]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[219]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[219]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[219]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[219]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[219]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[219]->NotRange.Usage = 0x0081 +pp_data->cap[219]->NotRange.Reserved1 = 0x0081 +pp_data->cap[219]->NotRange.StringIndex = 0 +pp_data->cap[219]->NotRange.Reserved2 = 0 +pp_data->cap[219]->NotRange.DesignatorIndex = 0 +pp_data->cap[219]->NotRange.Reserved3 = 0 +pp_data->cap[219]->NotRange.DataIndex = 132 +pp_data->cap[219]->NotRange.Reserved4 = 132 +pp_data->cap[219]->NotButton.HasNull = 0 +pp_data->cap[219]->NotButton.Reserved4 = 0x000000 +pp_data->cap[219]->NotButton.LogicalMin = 0 +pp_data->cap[219]->NotButton.LogicalMax = 127 +pp_data->cap[219]->NotButton.PhysicalMin = 0 +pp_data->cap[219]->NotButton.PhysicalMax = 0 +pp_data->cap[219]->Units = 0 +pp_data->cap[219]->UnitsExp = 0 + +pp_data->cap[220]->UsagePage = 0xFF01 +pp_data->cap[220]->ReportID = 0x81 +pp_data->cap[220]->BitPosition = 0 +pp_data->cap[220]->BitSize = 8 +pp_data->cap[220]->ReportCount = 1 +pp_data->cap[220]->BytePosition = 0x0001 +pp_data->cap[220]->BitCount = 8 +pp_data->cap[220]->BitField = 0x02 +pp_data->cap[220]->NextBytePosition = 0x0002 +pp_data->cap[220]->LinkCollection = 0x0004 +pp_data->cap[220]->LinkUsagePage = 0xFF01 +pp_data->cap[220]->LinkUsage = 0x0080 +pp_data->cap[220]->IsMultipleItemsForArray = 0 +pp_data->cap[220]->IsButtonCap = 0 +pp_data->cap[220]->IsPadding = 0 +pp_data->cap[220]->IsAbsolute = 1 +pp_data->cap[220]->IsRange = 0 +pp_data->cap[220]->IsAlias = 0 +pp_data->cap[220]->IsStringRange = 0 +pp_data->cap[220]->IsDesignatorRange = 0 +pp_data->cap[220]->Reserved1 = 0x000000 +pp_data->cap[220]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[220]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[220]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[220]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[220]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[220]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[220]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[220]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[220]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[220]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[220]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[220]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[220]->NotRange.Usage = 0x0081 +pp_data->cap[220]->NotRange.Reserved1 = 0x0081 +pp_data->cap[220]->NotRange.StringIndex = 0 +pp_data->cap[220]->NotRange.Reserved2 = 0 +pp_data->cap[220]->NotRange.DesignatorIndex = 0 +pp_data->cap[220]->NotRange.Reserved3 = 0 +pp_data->cap[220]->NotRange.DataIndex = 133 +pp_data->cap[220]->NotRange.Reserved4 = 133 +pp_data->cap[220]->NotButton.HasNull = 0 +pp_data->cap[220]->NotButton.Reserved4 = 0x000000 +pp_data->cap[220]->NotButton.LogicalMin = 0 +pp_data->cap[220]->NotButton.LogicalMax = 127 +pp_data->cap[220]->NotButton.PhysicalMin = 0 +pp_data->cap[220]->NotButton.PhysicalMax = 0 +pp_data->cap[220]->Units = 0 +pp_data->cap[220]->UnitsExp = 0 + +# Feature hid_pp_cap struct: +pp_data->cap[221]->UsagePage = 0xFF01 +pp_data->cap[221]->ReportID = 0xD0 +pp_data->cap[221]->BitPosition = 0 +pp_data->cap[221]->BitSize = 8 +pp_data->cap[221]->ReportCount = 32 +pp_data->cap[221]->BytePosition = 0x0001 +pp_data->cap[221]->BitCount = 256 +pp_data->cap[221]->BitField = 0x82 +pp_data->cap[221]->NextBytePosition = 0x0021 +pp_data->cap[221]->LinkCollection = 0x0005 +pp_data->cap[221]->LinkUsagePage = 0xFF01 +pp_data->cap[221]->LinkUsage = 0x00D0 +pp_data->cap[221]->IsMultipleItemsForArray = 0 +pp_data->cap[221]->IsButtonCap = 0 +pp_data->cap[221]->IsPadding = 0 +pp_data->cap[221]->IsAbsolute = 1 +pp_data->cap[221]->IsRange = 0 +pp_data->cap[221]->IsAlias = 0 +pp_data->cap[221]->IsStringRange = 0 +pp_data->cap[221]->IsDesignatorRange = 0 +pp_data->cap[221]->Reserved1 = 0x000000 +pp_data->cap[221]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[221]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[221]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[221]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[221]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[221]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[221]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[221]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[221]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[221]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[221]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[221]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[221]->NotRange.Usage = 0x00D1 +pp_data->cap[221]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[221]->NotRange.StringIndex = 0 +pp_data->cap[221]->NotRange.Reserved2 = 0 +pp_data->cap[221]->NotRange.DesignatorIndex = 0 +pp_data->cap[221]->NotRange.Reserved3 = 0 +pp_data->cap[221]->NotRange.DataIndex = 0 +pp_data->cap[221]->NotRange.Reserved4 = 0 +pp_data->cap[221]->NotButton.HasNull = 0 +pp_data->cap[221]->NotButton.Reserved4 = 0x000000 +pp_data->cap[221]->NotButton.LogicalMin = 0 +pp_data->cap[221]->NotButton.LogicalMax = 255 +pp_data->cap[221]->NotButton.PhysicalMin = 0 +pp_data->cap[221]->NotButton.PhysicalMax = 0 +pp_data->cap[221]->Units = 0 +pp_data->cap[221]->UnitsExp = 0 + +pp_data->cap[222]->UsagePage = 0xFF01 +pp_data->cap[222]->ReportID = 0xD1 +pp_data->cap[222]->BitPosition = 0 +pp_data->cap[222]->BitSize = 8 +pp_data->cap[222]->ReportCount = 32 +pp_data->cap[222]->BytePosition = 0x0001 +pp_data->cap[222]->BitCount = 256 +pp_data->cap[222]->BitField = 0x82 +pp_data->cap[222]->NextBytePosition = 0x0021 +pp_data->cap[222]->LinkCollection = 0x0006 +pp_data->cap[222]->LinkUsagePage = 0xFF01 +pp_data->cap[222]->LinkUsage = 0x00D0 +pp_data->cap[222]->IsMultipleItemsForArray = 0 +pp_data->cap[222]->IsButtonCap = 0 +pp_data->cap[222]->IsPadding = 0 +pp_data->cap[222]->IsAbsolute = 1 +pp_data->cap[222]->IsRange = 0 +pp_data->cap[222]->IsAlias = 0 +pp_data->cap[222]->IsStringRange = 0 +pp_data->cap[222]->IsDesignatorRange = 0 +pp_data->cap[222]->Reserved1 = 0x000000 +pp_data->cap[222]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[222]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[222]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[222]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[222]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[222]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[222]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[222]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[222]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[222]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[222]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[222]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[222]->NotRange.Usage = 0x00D1 +pp_data->cap[222]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[222]->NotRange.StringIndex = 0 +pp_data->cap[222]->NotRange.Reserved2 = 0 +pp_data->cap[222]->NotRange.DesignatorIndex = 0 +pp_data->cap[222]->NotRange.Reserved3 = 0 +pp_data->cap[222]->NotRange.DataIndex = 1 +pp_data->cap[222]->NotRange.Reserved4 = 1 +pp_data->cap[222]->NotButton.HasNull = 0 +pp_data->cap[222]->NotButton.Reserved4 = 0x000000 +pp_data->cap[222]->NotButton.LogicalMin = 0 +pp_data->cap[222]->NotButton.LogicalMax = 255 +pp_data->cap[222]->NotButton.PhysicalMin = 0 +pp_data->cap[222]->NotButton.PhysicalMax = 0 +pp_data->cap[222]->Units = 0 +pp_data->cap[222]->UnitsExp = 0 + +pp_data->cap[223]->UsagePage = 0xFF01 +pp_data->cap[223]->ReportID = 0xD2 +pp_data->cap[223]->BitPosition = 0 +pp_data->cap[223]->BitSize = 8 +pp_data->cap[223]->ReportCount = 32 +pp_data->cap[223]->BytePosition = 0x0001 +pp_data->cap[223]->BitCount = 256 +pp_data->cap[223]->BitField = 0x82 +pp_data->cap[223]->NextBytePosition = 0x0021 +pp_data->cap[223]->LinkCollection = 0x0007 +pp_data->cap[223]->LinkUsagePage = 0xFF01 +pp_data->cap[223]->LinkUsage = 0x00D0 +pp_data->cap[223]->IsMultipleItemsForArray = 0 +pp_data->cap[223]->IsButtonCap = 0 +pp_data->cap[223]->IsPadding = 0 +pp_data->cap[223]->IsAbsolute = 1 +pp_data->cap[223]->IsRange = 0 +pp_data->cap[223]->IsAlias = 0 +pp_data->cap[223]->IsStringRange = 0 +pp_data->cap[223]->IsDesignatorRange = 0 +pp_data->cap[223]->Reserved1 = 0x000000 +pp_data->cap[223]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[223]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[223]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[223]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[223]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[223]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[223]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[223]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[223]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[223]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[223]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[223]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[223]->NotRange.Usage = 0x00D1 +pp_data->cap[223]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[223]->NotRange.StringIndex = 0 +pp_data->cap[223]->NotRange.Reserved2 = 0 +pp_data->cap[223]->NotRange.DesignatorIndex = 0 +pp_data->cap[223]->NotRange.Reserved3 = 0 +pp_data->cap[223]->NotRange.DataIndex = 2 +pp_data->cap[223]->NotRange.Reserved4 = 2 +pp_data->cap[223]->NotButton.HasNull = 0 +pp_data->cap[223]->NotButton.Reserved4 = 0x000000 +pp_data->cap[223]->NotButton.LogicalMin = 0 +pp_data->cap[223]->NotButton.LogicalMax = 255 +pp_data->cap[223]->NotButton.PhysicalMin = 0 +pp_data->cap[223]->NotButton.PhysicalMax = 0 +pp_data->cap[223]->Units = 0 +pp_data->cap[223]->UnitsExp = 0 + +pp_data->cap[224]->UsagePage = 0xFF01 +pp_data->cap[224]->ReportID = 0xD3 +pp_data->cap[224]->BitPosition = 0 +pp_data->cap[224]->BitSize = 8 +pp_data->cap[224]->ReportCount = 32 +pp_data->cap[224]->BytePosition = 0x0001 +pp_data->cap[224]->BitCount = 256 +pp_data->cap[224]->BitField = 0x82 +pp_data->cap[224]->NextBytePosition = 0x0021 +pp_data->cap[224]->LinkCollection = 0x0008 +pp_data->cap[224]->LinkUsagePage = 0xFF01 +pp_data->cap[224]->LinkUsage = 0x00D0 +pp_data->cap[224]->IsMultipleItemsForArray = 0 +pp_data->cap[224]->IsButtonCap = 0 +pp_data->cap[224]->IsPadding = 0 +pp_data->cap[224]->IsAbsolute = 1 +pp_data->cap[224]->IsRange = 0 +pp_data->cap[224]->IsAlias = 0 +pp_data->cap[224]->IsStringRange = 0 +pp_data->cap[224]->IsDesignatorRange = 0 +pp_data->cap[224]->Reserved1 = 0x000000 +pp_data->cap[224]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[224]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[224]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[224]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[224]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[224]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[224]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[224]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[224]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[224]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[224]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[224]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[224]->NotRange.Usage = 0x00D1 +pp_data->cap[224]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[224]->NotRange.StringIndex = 0 +pp_data->cap[224]->NotRange.Reserved2 = 0 +pp_data->cap[224]->NotRange.DesignatorIndex = 0 +pp_data->cap[224]->NotRange.Reserved3 = 0 +pp_data->cap[224]->NotRange.DataIndex = 3 +pp_data->cap[224]->NotRange.Reserved4 = 3 +pp_data->cap[224]->NotButton.HasNull = 0 +pp_data->cap[224]->NotButton.Reserved4 = 0x000000 +pp_data->cap[224]->NotButton.LogicalMin = 0 +pp_data->cap[224]->NotButton.LogicalMax = 255 +pp_data->cap[224]->NotButton.PhysicalMin = 0 +pp_data->cap[224]->NotButton.PhysicalMax = 0 +pp_data->cap[224]->Units = 0 +pp_data->cap[224]->UnitsExp = 0 + +pp_data->cap[225]->UsagePage = 0xFF01 +pp_data->cap[225]->ReportID = 0xD4 +pp_data->cap[225]->BitPosition = 0 +pp_data->cap[225]->BitSize = 8 +pp_data->cap[225]->ReportCount = 32 +pp_data->cap[225]->BytePosition = 0x0001 +pp_data->cap[225]->BitCount = 256 +pp_data->cap[225]->BitField = 0x82 +pp_data->cap[225]->NextBytePosition = 0x0021 +pp_data->cap[225]->LinkCollection = 0x0009 +pp_data->cap[225]->LinkUsagePage = 0xFF01 +pp_data->cap[225]->LinkUsage = 0x00D0 +pp_data->cap[225]->IsMultipleItemsForArray = 0 +pp_data->cap[225]->IsButtonCap = 0 +pp_data->cap[225]->IsPadding = 0 +pp_data->cap[225]->IsAbsolute = 1 +pp_data->cap[225]->IsRange = 0 +pp_data->cap[225]->IsAlias = 0 +pp_data->cap[225]->IsStringRange = 0 +pp_data->cap[225]->IsDesignatorRange = 0 +pp_data->cap[225]->Reserved1 = 0x000000 +pp_data->cap[225]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[225]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[225]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[225]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[225]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[225]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[225]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[225]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[225]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[225]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[225]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[225]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[225]->NotRange.Usage = 0x00D1 +pp_data->cap[225]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[225]->NotRange.StringIndex = 0 +pp_data->cap[225]->NotRange.Reserved2 = 0 +pp_data->cap[225]->NotRange.DesignatorIndex = 0 +pp_data->cap[225]->NotRange.Reserved3 = 0 +pp_data->cap[225]->NotRange.DataIndex = 4 +pp_data->cap[225]->NotRange.Reserved4 = 4 +pp_data->cap[225]->NotButton.HasNull = 0 +pp_data->cap[225]->NotButton.Reserved4 = 0x000000 +pp_data->cap[225]->NotButton.LogicalMin = 0 +pp_data->cap[225]->NotButton.LogicalMax = 255 +pp_data->cap[225]->NotButton.PhysicalMin = 0 +pp_data->cap[225]->NotButton.PhysicalMax = 0 +pp_data->cap[225]->Units = 0 +pp_data->cap[225]->UnitsExp = 0 + +pp_data->cap[226]->UsagePage = 0xFF01 +pp_data->cap[226]->ReportID = 0xD5 +pp_data->cap[226]->BitPosition = 0 +pp_data->cap[226]->BitSize = 8 +pp_data->cap[226]->ReportCount = 32 +pp_data->cap[226]->BytePosition = 0x0001 +pp_data->cap[226]->BitCount = 256 +pp_data->cap[226]->BitField = 0x82 +pp_data->cap[226]->NextBytePosition = 0x0021 +pp_data->cap[226]->LinkCollection = 0x000A +pp_data->cap[226]->LinkUsagePage = 0xFF01 +pp_data->cap[226]->LinkUsage = 0x00D0 +pp_data->cap[226]->IsMultipleItemsForArray = 0 +pp_data->cap[226]->IsButtonCap = 0 +pp_data->cap[226]->IsPadding = 0 +pp_data->cap[226]->IsAbsolute = 1 +pp_data->cap[226]->IsRange = 0 +pp_data->cap[226]->IsAlias = 0 +pp_data->cap[226]->IsStringRange = 0 +pp_data->cap[226]->IsDesignatorRange = 0 +pp_data->cap[226]->Reserved1 = 0x000000 +pp_data->cap[226]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[226]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[226]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[226]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[226]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[226]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[226]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[226]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[226]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[226]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[226]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[226]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[226]->NotRange.Usage = 0x00D1 +pp_data->cap[226]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[226]->NotRange.StringIndex = 0 +pp_data->cap[226]->NotRange.Reserved2 = 0 +pp_data->cap[226]->NotRange.DesignatorIndex = 0 +pp_data->cap[226]->NotRange.Reserved3 = 0 +pp_data->cap[226]->NotRange.DataIndex = 5 +pp_data->cap[226]->NotRange.Reserved4 = 5 +pp_data->cap[226]->NotButton.HasNull = 0 +pp_data->cap[226]->NotButton.Reserved4 = 0x000000 +pp_data->cap[226]->NotButton.LogicalMin = 0 +pp_data->cap[226]->NotButton.LogicalMax = 255 +pp_data->cap[226]->NotButton.PhysicalMin = 0 +pp_data->cap[226]->NotButton.PhysicalMax = 0 +pp_data->cap[226]->Units = 0 +pp_data->cap[226]->UnitsExp = 0 + +pp_data->cap[227]->UsagePage = 0xFF01 +pp_data->cap[227]->ReportID = 0xD6 +pp_data->cap[227]->BitPosition = 0 +pp_data->cap[227]->BitSize = 8 +pp_data->cap[227]->ReportCount = 32 +pp_data->cap[227]->BytePosition = 0x0001 +pp_data->cap[227]->BitCount = 256 +pp_data->cap[227]->BitField = 0x82 +pp_data->cap[227]->NextBytePosition = 0x0021 +pp_data->cap[227]->LinkCollection = 0x000B +pp_data->cap[227]->LinkUsagePage = 0xFF01 +pp_data->cap[227]->LinkUsage = 0x00D0 +pp_data->cap[227]->IsMultipleItemsForArray = 0 +pp_data->cap[227]->IsButtonCap = 0 +pp_data->cap[227]->IsPadding = 0 +pp_data->cap[227]->IsAbsolute = 1 +pp_data->cap[227]->IsRange = 0 +pp_data->cap[227]->IsAlias = 0 +pp_data->cap[227]->IsStringRange = 0 +pp_data->cap[227]->IsDesignatorRange = 0 +pp_data->cap[227]->Reserved1 = 0x000000 +pp_data->cap[227]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[227]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[227]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[227]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[227]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[227]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[227]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[227]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[227]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[227]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[227]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[227]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[227]->NotRange.Usage = 0x00D1 +pp_data->cap[227]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[227]->NotRange.StringIndex = 0 +pp_data->cap[227]->NotRange.Reserved2 = 0 +pp_data->cap[227]->NotRange.DesignatorIndex = 0 +pp_data->cap[227]->NotRange.Reserved3 = 0 +pp_data->cap[227]->NotRange.DataIndex = 6 +pp_data->cap[227]->NotRange.Reserved4 = 6 +pp_data->cap[227]->NotButton.HasNull = 0 +pp_data->cap[227]->NotButton.Reserved4 = 0x000000 +pp_data->cap[227]->NotButton.LogicalMin = 0 +pp_data->cap[227]->NotButton.LogicalMax = 255 +pp_data->cap[227]->NotButton.PhysicalMin = 0 +pp_data->cap[227]->NotButton.PhysicalMax = 0 +pp_data->cap[227]->Units = 0 +pp_data->cap[227]->UnitsExp = 0 + +pp_data->cap[228]->UsagePage = 0xFF01 +pp_data->cap[228]->ReportID = 0xD8 +pp_data->cap[228]->BitPosition = 0 +pp_data->cap[228]->BitSize = 8 +pp_data->cap[228]->ReportCount = 32 +pp_data->cap[228]->BytePosition = 0x0001 +pp_data->cap[228]->BitCount = 256 +pp_data->cap[228]->BitField = 0x82 +pp_data->cap[228]->NextBytePosition = 0x0021 +pp_data->cap[228]->LinkCollection = 0x000C +pp_data->cap[228]->LinkUsagePage = 0xFF01 +pp_data->cap[228]->LinkUsage = 0x00D0 +pp_data->cap[228]->IsMultipleItemsForArray = 0 +pp_data->cap[228]->IsButtonCap = 0 +pp_data->cap[228]->IsPadding = 0 +pp_data->cap[228]->IsAbsolute = 1 +pp_data->cap[228]->IsRange = 0 +pp_data->cap[228]->IsAlias = 0 +pp_data->cap[228]->IsStringRange = 0 +pp_data->cap[228]->IsDesignatorRange = 0 +pp_data->cap[228]->Reserved1 = 0x000000 +pp_data->cap[228]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[228]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[228]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[228]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[228]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[228]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[228]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[228]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[228]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[228]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[228]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[228]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[228]->NotRange.Usage = 0x00D1 +pp_data->cap[228]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[228]->NotRange.StringIndex = 0 +pp_data->cap[228]->NotRange.Reserved2 = 0 +pp_data->cap[228]->NotRange.DesignatorIndex = 0 +pp_data->cap[228]->NotRange.Reserved3 = 0 +pp_data->cap[228]->NotRange.DataIndex = 7 +pp_data->cap[228]->NotRange.Reserved4 = 7 +pp_data->cap[228]->NotButton.HasNull = 0 +pp_data->cap[228]->NotButton.Reserved4 = 0x000000 +pp_data->cap[228]->NotButton.LogicalMin = 0 +pp_data->cap[228]->NotButton.LogicalMax = 255 +pp_data->cap[228]->NotButton.PhysicalMin = 0 +pp_data->cap[228]->NotButton.PhysicalMax = 0 +pp_data->cap[228]->Units = 0 +pp_data->cap[228]->UnitsExp = 0 + +pp_data->cap[229]->UsagePage = 0xFF01 +pp_data->cap[229]->ReportID = 0xD9 +pp_data->cap[229]->BitPosition = 0 +pp_data->cap[229]->BitSize = 8 +pp_data->cap[229]->ReportCount = 32 +pp_data->cap[229]->BytePosition = 0x0001 +pp_data->cap[229]->BitCount = 256 +pp_data->cap[229]->BitField = 0x82 +pp_data->cap[229]->NextBytePosition = 0x0021 +pp_data->cap[229]->LinkCollection = 0x000D +pp_data->cap[229]->LinkUsagePage = 0xFF01 +pp_data->cap[229]->LinkUsage = 0x00D0 +pp_data->cap[229]->IsMultipleItemsForArray = 0 +pp_data->cap[229]->IsButtonCap = 0 +pp_data->cap[229]->IsPadding = 0 +pp_data->cap[229]->IsAbsolute = 1 +pp_data->cap[229]->IsRange = 0 +pp_data->cap[229]->IsAlias = 0 +pp_data->cap[229]->IsStringRange = 0 +pp_data->cap[229]->IsDesignatorRange = 0 +pp_data->cap[229]->Reserved1 = 0x000000 +pp_data->cap[229]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[229]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[229]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[229]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[229]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[229]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[229]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[229]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[229]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[229]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[229]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[229]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[229]->NotRange.Usage = 0x00D1 +pp_data->cap[229]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[229]->NotRange.StringIndex = 0 +pp_data->cap[229]->NotRange.Reserved2 = 0 +pp_data->cap[229]->NotRange.DesignatorIndex = 0 +pp_data->cap[229]->NotRange.Reserved3 = 0 +pp_data->cap[229]->NotRange.DataIndex = 8 +pp_data->cap[229]->NotRange.Reserved4 = 8 +pp_data->cap[229]->NotButton.HasNull = 0 +pp_data->cap[229]->NotButton.Reserved4 = 0x000000 +pp_data->cap[229]->NotButton.LogicalMin = 0 +pp_data->cap[229]->NotButton.LogicalMax = 255 +pp_data->cap[229]->NotButton.PhysicalMin = 0 +pp_data->cap[229]->NotButton.PhysicalMax = 0 +pp_data->cap[229]->Units = 0 +pp_data->cap[229]->UnitsExp = 0 + +pp_data->cap[230]->UsagePage = 0xFF01 +pp_data->cap[230]->ReportID = 0xF1 +pp_data->cap[230]->BitPosition = 0 +pp_data->cap[230]->BitSize = 8 +pp_data->cap[230]->ReportCount = 2 +pp_data->cap[230]->BytePosition = 0x0001 +pp_data->cap[230]->BitCount = 16 +pp_data->cap[230]->BitField = 0x82 +pp_data->cap[230]->NextBytePosition = 0x0003 +pp_data->cap[230]->LinkCollection = 0x000E +pp_data->cap[230]->LinkUsagePage = 0xFF01 +pp_data->cap[230]->LinkUsage = 0x00D0 +pp_data->cap[230]->IsMultipleItemsForArray = 0 +pp_data->cap[230]->IsButtonCap = 0 +pp_data->cap[230]->IsPadding = 0 +pp_data->cap[230]->IsAbsolute = 1 +pp_data->cap[230]->IsRange = 0 +pp_data->cap[230]->IsAlias = 0 +pp_data->cap[230]->IsStringRange = 0 +pp_data->cap[230]->IsDesignatorRange = 0 +pp_data->cap[230]->Reserved1 = 0x000000 +pp_data->cap[230]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[230]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[230]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[230]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[230]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[230]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[230]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[230]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[230]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[230]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[230]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[230]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[230]->NotRange.Usage = 0x00D1 +pp_data->cap[230]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[230]->NotRange.StringIndex = 0 +pp_data->cap[230]->NotRange.Reserved2 = 0 +pp_data->cap[230]->NotRange.DesignatorIndex = 0 +pp_data->cap[230]->NotRange.Reserved3 = 0 +pp_data->cap[230]->NotRange.DataIndex = 9 +pp_data->cap[230]->NotRange.Reserved4 = 9 +pp_data->cap[230]->NotButton.HasNull = 0 +pp_data->cap[230]->NotButton.Reserved4 = 0x000000 +pp_data->cap[230]->NotButton.LogicalMin = 0 +pp_data->cap[230]->NotButton.LogicalMax = 255 +pp_data->cap[230]->NotButton.PhysicalMin = 0 +pp_data->cap[230]->NotButton.PhysicalMax = 0 +pp_data->cap[230]->Units = 0 +pp_data->cap[230]->UnitsExp = 0 + +pp_data->cap[231]->UsagePage = 0xFF01 +pp_data->cap[231]->ReportID = 0xF3 +pp_data->cap[231]->BitPosition = 0 +pp_data->cap[231]->BitSize = 8 +pp_data->cap[231]->ReportCount = 2 +pp_data->cap[231]->BytePosition = 0x0001 +pp_data->cap[231]->BitCount = 16 +pp_data->cap[231]->BitField = 0x82 +pp_data->cap[231]->NextBytePosition = 0x0003 +pp_data->cap[231]->LinkCollection = 0x000F +pp_data->cap[231]->LinkUsagePage = 0xFF01 +pp_data->cap[231]->LinkUsage = 0x00D0 +pp_data->cap[231]->IsMultipleItemsForArray = 0 +pp_data->cap[231]->IsButtonCap = 0 +pp_data->cap[231]->IsPadding = 0 +pp_data->cap[231]->IsAbsolute = 1 +pp_data->cap[231]->IsRange = 0 +pp_data->cap[231]->IsAlias = 0 +pp_data->cap[231]->IsStringRange = 0 +pp_data->cap[231]->IsDesignatorRange = 0 +pp_data->cap[231]->Reserved1 = 0x000000 +pp_data->cap[231]->pp_cap->UnknownTokens[0].Token = 0x00 +pp_data->cap[231]->pp_cap->UnknownTokens[0].Reserved = 0x000000 +pp_data->cap[231]->pp_cap->UnknownTokens[0].BitField = 0x00000000 +pp_data->cap[231]->pp_cap->UnknownTokens[1].Token = 0x00 +pp_data->cap[231]->pp_cap->UnknownTokens[1].Reserved = 0x000000 +pp_data->cap[231]->pp_cap->UnknownTokens[1].BitField = 0x00000000 +pp_data->cap[231]->pp_cap->UnknownTokens[2].Token = 0x00 +pp_data->cap[231]->pp_cap->UnknownTokens[2].Reserved = 0x000000 +pp_data->cap[231]->pp_cap->UnknownTokens[2].BitField = 0x00000000 +pp_data->cap[231]->pp_cap->UnknownTokens[3].Token = 0x00 +pp_data->cap[231]->pp_cap->UnknownTokens[3].Reserved = 0x000000 +pp_data->cap[231]->pp_cap->UnknownTokens[3].BitField = 0x00000000 +pp_data->cap[231]->NotRange.Usage = 0x00D1 +pp_data->cap[231]->NotRange.Reserved1 = 0x00D1 +pp_data->cap[231]->NotRange.StringIndex = 0 +pp_data->cap[231]->NotRange.Reserved2 = 0 +pp_data->cap[231]->NotRange.DesignatorIndex = 0 +pp_data->cap[231]->NotRange.Reserved3 = 0 +pp_data->cap[231]->NotRange.DataIndex = 10 +pp_data->cap[231]->NotRange.Reserved4 = 10 +pp_data->cap[231]->NotButton.HasNull = 0 +pp_data->cap[231]->NotButton.Reserved4 = 0x000000 +pp_data->cap[231]->NotButton.LogicalMin = 0 +pp_data->cap[231]->NotButton.LogicalMax = 127 +pp_data->cap[231]->NotButton.PhysicalMin = 0 +pp_data->cap[231]->NotButton.PhysicalMax = 0 +pp_data->cap[231]->Units = 0 +pp_data->cap[231]->UnitsExp = 0 + +# Link Collections: +pp_data->LinkCollectionArray[0]->LinkUsage = 0x0000 +pp_data->LinkCollectionArray[0]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[0]->Parent = 0 +pp_data->LinkCollectionArray[0]->NumberOfChildren = 15 +pp_data->LinkCollectionArray[0]->NextSibling = 0 +pp_data->LinkCollectionArray[0]->FirstChild = 15 +pp_data->LinkCollectionArray[0]->CollectionType = 1 +pp_data->LinkCollectionArray[0]->IsAlias = 0 +pp_data->LinkCollectionArray[0]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[1]->LinkUsage = 0x0001 +pp_data->LinkCollectionArray[1]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[1]->Parent = 0 +pp_data->LinkCollectionArray[1]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[1]->NextSibling = 0 +pp_data->LinkCollectionArray[1]->FirstChild = 0 +pp_data->LinkCollectionArray[1]->CollectionType = 2 +pp_data->LinkCollectionArray[1]->IsAlias = 0 +pp_data->LinkCollectionArray[1]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[2]->LinkUsage = 0x0002 +pp_data->LinkCollectionArray[2]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[2]->Parent = 0 +pp_data->LinkCollectionArray[2]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[2]->NextSibling = 1 +pp_data->LinkCollectionArray[2]->FirstChild = 0 +pp_data->LinkCollectionArray[2]->CollectionType = 2 +pp_data->LinkCollectionArray[2]->IsAlias = 0 +pp_data->LinkCollectionArray[2]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[3]->LinkUsage = 0x0080 +pp_data->LinkCollectionArray[3]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[3]->Parent = 0 +pp_data->LinkCollectionArray[3]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[3]->NextSibling = 2 +pp_data->LinkCollectionArray[3]->FirstChild = 0 +pp_data->LinkCollectionArray[3]->CollectionType = 2 +pp_data->LinkCollectionArray[3]->IsAlias = 0 +pp_data->LinkCollectionArray[3]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[4]->LinkUsage = 0x0080 +pp_data->LinkCollectionArray[4]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[4]->Parent = 0 +pp_data->LinkCollectionArray[4]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[4]->NextSibling = 3 +pp_data->LinkCollectionArray[4]->FirstChild = 0 +pp_data->LinkCollectionArray[4]->CollectionType = 2 +pp_data->LinkCollectionArray[4]->IsAlias = 0 +pp_data->LinkCollectionArray[4]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[5]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[5]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[5]->Parent = 0 +pp_data->LinkCollectionArray[5]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[5]->NextSibling = 4 +pp_data->LinkCollectionArray[5]->FirstChild = 0 +pp_data->LinkCollectionArray[5]->CollectionType = 2 +pp_data->LinkCollectionArray[5]->IsAlias = 0 +pp_data->LinkCollectionArray[5]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[6]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[6]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[6]->Parent = 0 +pp_data->LinkCollectionArray[6]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[6]->NextSibling = 5 +pp_data->LinkCollectionArray[6]->FirstChild = 0 +pp_data->LinkCollectionArray[6]->CollectionType = 2 +pp_data->LinkCollectionArray[6]->IsAlias = 0 +pp_data->LinkCollectionArray[6]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[7]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[7]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[7]->Parent = 0 +pp_data->LinkCollectionArray[7]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[7]->NextSibling = 6 +pp_data->LinkCollectionArray[7]->FirstChild = 0 +pp_data->LinkCollectionArray[7]->CollectionType = 2 +pp_data->LinkCollectionArray[7]->IsAlias = 0 +pp_data->LinkCollectionArray[7]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[8]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[8]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[8]->Parent = 0 +pp_data->LinkCollectionArray[8]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[8]->NextSibling = 7 +pp_data->LinkCollectionArray[8]->FirstChild = 0 +pp_data->LinkCollectionArray[8]->CollectionType = 2 +pp_data->LinkCollectionArray[8]->IsAlias = 0 +pp_data->LinkCollectionArray[8]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[9]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[9]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[9]->Parent = 0 +pp_data->LinkCollectionArray[9]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[9]->NextSibling = 8 +pp_data->LinkCollectionArray[9]->FirstChild = 0 +pp_data->LinkCollectionArray[9]->CollectionType = 2 +pp_data->LinkCollectionArray[9]->IsAlias = 0 +pp_data->LinkCollectionArray[9]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[10]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[10]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[10]->Parent = 0 +pp_data->LinkCollectionArray[10]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[10]->NextSibling = 9 +pp_data->LinkCollectionArray[10]->FirstChild = 0 +pp_data->LinkCollectionArray[10]->CollectionType = 2 +pp_data->LinkCollectionArray[10]->IsAlias = 0 +pp_data->LinkCollectionArray[10]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[11]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[11]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[11]->Parent = 0 +pp_data->LinkCollectionArray[11]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[11]->NextSibling = 10 +pp_data->LinkCollectionArray[11]->FirstChild = 0 +pp_data->LinkCollectionArray[11]->CollectionType = 2 +pp_data->LinkCollectionArray[11]->IsAlias = 0 +pp_data->LinkCollectionArray[11]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[12]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[12]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[12]->Parent = 0 +pp_data->LinkCollectionArray[12]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[12]->NextSibling = 11 +pp_data->LinkCollectionArray[12]->FirstChild = 0 +pp_data->LinkCollectionArray[12]->CollectionType = 2 +pp_data->LinkCollectionArray[12]->IsAlias = 0 +pp_data->LinkCollectionArray[12]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[13]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[13]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[13]->Parent = 0 +pp_data->LinkCollectionArray[13]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[13]->NextSibling = 12 +pp_data->LinkCollectionArray[13]->FirstChild = 0 +pp_data->LinkCollectionArray[13]->CollectionType = 2 +pp_data->LinkCollectionArray[13]->IsAlias = 0 +pp_data->LinkCollectionArray[13]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[14]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[14]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[14]->Parent = 0 +pp_data->LinkCollectionArray[14]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[14]->NextSibling = 13 +pp_data->LinkCollectionArray[14]->FirstChild = 0 +pp_data->LinkCollectionArray[14]->CollectionType = 2 +pp_data->LinkCollectionArray[14]->IsAlias = 0 +pp_data->LinkCollectionArray[14]->Reserved = 0x00000000 +pp_data->LinkCollectionArray[15]->LinkUsage = 0x00D0 +pp_data->LinkCollectionArray[15]->LinkUsagePage = 0xFF01 +pp_data->LinkCollectionArray[15]->Parent = 0 +pp_data->LinkCollectionArray[15]->NumberOfChildren = 0 +pp_data->LinkCollectionArray[15]->NextSibling = 14 +pp_data->LinkCollectionArray[15]->FirstChild = 0 +pp_data->LinkCollectionArray[15]->CollectionType = 2 +pp_data->LinkCollectionArray[15]->IsAlias = 0 +pp_data->LinkCollectionArray[15]->Reserved = 0x00000000 diff --git a/windows/test/data/17CC_1130_0000_FF01_expected.rpt_desc b/windows/test/data/17CC_1130_0000_FF01_expected.rpt_desc new file mode 100644 index 000000000..9bcc814aa --- /dev/null +++ b/windows/test/data/17CC_1130_0000_FF01_expected.rpt_desc @@ -0,0 +1,75 @@ +0x06, 0x01, 0xFF, 0x09, 0x00, 0xA1, 0x01, 0x09, 0x01, 0xA1, +0x02, 0x85, 0x01, 0x09, 0x03, 0x09, 0x03, 0x09, 0x03, 0x09, +0x03, 0x15, 0x00, 0x25, 0x0F, 0x75, 0x04, 0x95, 0x04, 0x81, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, +0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x02, 0x09, 0x0B, 0x09, +0x0B, 0x09, 0x0B, 0x09, 0x0B, 0x09, 0x0B, 0x09, 0x0B, 0x09, +0x0B, 0x09, 0x0B, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, +0x38, 0x81, 0x02, 0xC0, 0x09, 0x02, 0xA1, 0x02, 0x85, 0x02, +0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, +0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, +0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, +0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, +0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, +0x09, 0x04, 0x15, 0x00, 0x26, 0xFF, 0x0F, 0x75, 0x10, 0x95, +0x1A, 0x81, 0x02, 0xC0, 0x09, 0x80, 0xA1, 0x02, 0x85, 0x80, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, +0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x15, 0x00, +0x25, 0x7F, 0x75, 0x08, 0x95, 0x5E, 0x91, 0x02, 0xC0, 0x09, +0x80, 0xA1, 0x02, 0x85, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, 0x81, 0x09, +0x81, 0x09, 0x81, 0x09, 0x81, 0x15, 0x00, 0x25, 0x7F, 0x75, +0x08, 0x95, 0x28, 0x91, 0x02, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD0, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD1, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD2, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD3, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD4, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD5, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD6, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD8, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xD9, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x20, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xF1, 0x09, 0xD1, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x75, +0x08, 0x95, 0x02, 0xB1, 0x82, 0xC0, 0x09, 0xD0, 0xA1, 0x02, +0x85, 0xF3, 0x09, 0xD1, 0x15, 0x00, 0x25, 0x7F, 0x75, 0x08, +0x95, 0x02, 0xB1, 0x82, 0xC0, 0xC0, \ No newline at end of file diff --git a/windows/test/data/17CC_1130_0000_FF01_real.rpt_desc b/windows/test/data/17CC_1130_0000_FF01_real.rpt_desc new file mode 100644 index 000000000..7f908f8fa --- /dev/null +++ b/windows/test/data/17CC_1130_0000_FF01_real.rpt_desc @@ -0,0 +1,381 @@ +Usage Page (Vendor-Defined 2) 06 01 FF +Usage (Undefined) 09 00 +Collection (Application) A1 01 + Usage (Vendor-Defined 1) 09 01 + Collection (Logical) A1 02 + Report ID (1) 85 01 + Usage (Vendor-Defined 3) 09 03 + Usage (Vendor-Defined 3) 09 03 + Usage (Vendor-Defined 3) 09 03 + Usage (Vendor-Defined 3) 09 03 + Logical Minimum (0) 15 00 + Logical Maximum (15) 25 0F + Report Size (4) 75 04 + Report Count (4) 95 04 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Usage (Vendor-Defined 2) 09 02 + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Report Size (1) 75 01 + Report Count (48) 95 30 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Usage (Vendor-Defined 11) 09 0B + Logical Minimum (0) 15 00 + Logical Maximum (1) 25 01 + Report Size (1) 75 01 + Report Count (8) 95 08 + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + End Collection C0 + Usage (Vendor-Defined 2) 09 02 + Collection (Logical) A1 02 + Report ID (2) 85 02 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Usage (Vendor-Defined 4) 09 04 + Logical Minimum (0) 15 00 + Logical Maximum (4095) 26 FF 0F + Report Size (16) 75 10 + Report Count (26) 95 1A + Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02 + End Collection C0 + Usage (Vendor-Defined 128) 09 80 + Collection (Logical) A1 02 + Report ID (128) 85 80 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Logical Minimum (0) 15 00 + Logical Maximum (127) 25 7F + Report Count (94) 95 5E + Report Size (8) 75 08 + Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02 + End Collection C0 + Usage (Vendor-Defined 128) 09 80 + Collection (Logical) A1 02 + Report ID (129) 85 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Usage (Vendor-Defined 129) 09 81 + Logical Minimum (0) 15 00 + Logical Maximum (127) 25 7F + Report Count (40) 95 28 + Report Size (8) 75 08 + Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (208) 85 D0 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (209) 85 D1 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (210) 85 D2 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (211) 85 D3 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (212) 85 D4 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (213) 85 D5 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (214) 85 D6 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (216) 85 D8 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (217) 85 D9 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (32) 95 20 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (241) 85 F1 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (255) 26 FF 00 + Report Size (8) 75 08 + Report Count (2) 95 02 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 + Usage (Vendor-Defined 208) 09 D0 + Collection (Logical) A1 02 + Report ID (243) 85 F3 + Usage (Vendor-Defined 209) 09 D1 + Logical Minimum (0) 15 00 + Logical Maximum (127) 25 7F + Report Size (8) 75 08 + Report Count (2) 95 02 + Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,Vol,Bit) B1 82 + End Collection C0 +End Collection C0 diff --git a/windows/test/hid_report_reconstructor_test.c b/windows/test/hid_report_reconstructor_test.c new file mode 100644 index 000000000..a7adeb54d --- /dev/null +++ b/windows/test/hid_report_reconstructor_test.c @@ -0,0 +1,563 @@ +#if defined(__MINGW32__) + // Needed for %zu + #define __USE_MINGW_ANSI_STDIO 1 +#endif + +#include "../hidapi_descriptor_reconstruct.h" + +#include +#include +#include + +static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) +{ + FILE* file; + errno_t err = fopen_s(&file, filename, "r"); + + if (err != 0) { + fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(err)); + return NULL; + } + + char line[256]; + + { + unsigned short vendor_id = 0; + unsigned short product_id = 0; + unsigned short usage = 0; + unsigned short usage_page = 0; + unsigned short release_number = 0; + int interface_number = -1; + BOOLEAN header_read_success = FALSE; + char manufacturer_string[128]; + manufacturer_string[0] = '\0'; + char product_string[128]; + product_string[0] = '\0'; + // char path[128]; + // path[0] = '\0'; + + while (fgets(line, sizeof(line), file) != NULL) { + if (line[0] == '\r' || line[0] == '\n') { + line[0] = '\0'; + } + if (line[0] == '\0') { + // read the 'metadata' only until the first empty line + header_read_success = TRUE; + break; + } + if (sscanf(line, "dev->vendor_id = 0x%04hX\n", &vendor_id)) continue; + if (sscanf(line, "dev->product_id = 0x%04hX\n", &product_id)) continue; + if (sscanf(line, "dev->usage_page = 0x%04hX\n", &usage_page)) continue; + if (sscanf(line, "dev->usage = 0x%04hX\n", &usage)) continue; + if (sscanf(line, "dev->manufacturer_string = \"%127[^\"\n]", manufacturer_string)) continue; + if (sscanf(line, "dev->product_string = \"%127[^\"\n]", product_string)) continue; + if (sscanf(line, "dev->release_number = 0x%04hX\n", &release_number)) continue; + if (sscanf(line, "dev->interface_number = %d\n", &interface_number)) continue; + // if (sscanf(line, "dev->path = \"%127[^\"]\n", path)) continue; + } + if (!header_read_success) { + fprintf(stderr, "ERROR: Couldn't read PP Data header (missing newline)\n"); + fclose(file); + return NULL; + } + printf("'Virtual' Device Read: %04hx %04hx\n", vendor_id, product_id); + if (manufacturer_string[0] != '\0') { + printf(" Manufacturer: %s\n", manufacturer_string); + } + if (product_string[0] != '\0') { + printf(" Product: %s\n", product_string); + } + printf(" Release: %hx\n", release_number); + printf(" Interface: %d\n", interface_number); + printf(" Usage (page): 0x%hx (0x%hx)\n", usage, usage_page); + } + + hidp_preparsed_data static_pp_data; + memset(&static_pp_data, 0, sizeof(static_pp_data)); + hidp_preparsed_data *pp_data = &static_pp_data; + + unsigned int rt_idx; + unsigned int caps_idx; + unsigned int token_idx; + unsigned int coll_idx; + USAGE temp_usage; + BOOLEAN temp_boolean[3]; + UCHAR temp_uchar[3]; + USHORT temp_ushort; + ULONG temp_ulong; + LONG temp_long; + + USHORT FirstByteOfLinkCollectionArray = 0; + USHORT NumberLinkCollectionNodes = 0; + + while (fgets(line, sizeof(line), file) != NULL) { + if (line[0] == '#') + continue; + + if (FirstByteOfLinkCollectionArray != 0 && NumberLinkCollectionNodes != 0) { + size_t size_of_preparsed_data = offsetof(hidp_preparsed_data, caps) + FirstByteOfLinkCollectionArray + (NumberLinkCollectionNodes * sizeof(hid_pp_link_collection_node)); + pp_data->FirstByteOfLinkCollectionArray = FirstByteOfLinkCollectionArray; + pp_data->NumberLinkCollectionNodes = NumberLinkCollectionNodes; + FirstByteOfLinkCollectionArray = 0; + NumberLinkCollectionNodes = 0; + pp_data = malloc(size_of_preparsed_data); + memcpy(pp_data, &static_pp_data, sizeof(static_pp_data)); + } + + if (sscanf(line, "pp_data->MagicKey = 0x%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX\n", &pp_data->MagicKey[0], &pp_data->MagicKey[1], &pp_data->MagicKey[2], &pp_data->MagicKey[3], &pp_data->MagicKey[4], &pp_data->MagicKey[5], &pp_data->MagicKey[6], &pp_data->MagicKey[7])) continue; + if (sscanf(line, "pp_data->Usage = 0x%04hX\n", &pp_data->Usage)) continue; + if (sscanf(line, "pp_data->UsagePage = 0x%04hX\n", &pp_data->UsagePage)) continue; + if (sscanf(line, "pp_data->Reserved = 0x%04hX%04hX\n", &pp_data->Reserved[0], &pp_data->Reserved[1])) continue; + + if (sscanf(line, "pp_data->caps_info[%u]", &rt_idx) == 1) { + const size_t caps_info_count = sizeof(pp_data->caps_info) / sizeof(pp_data->caps_info[0]); + if (rt_idx >= caps_info_count) { + fprintf(stderr, "Broken pp_data file, pp_data->caps_info[] can have at most %zu elements, accessing %ud, (%s)", caps_info_count, rt_idx, line); + continue; + } + if (sscanf(line, "pp_data->caps_info[%u]->FirstCap = %hu\n", &rt_idx, &temp_ushort) == 2) { + pp_data->caps_info[rt_idx].FirstCap = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->caps_info[%u]->LastCap = %hu\n", &rt_idx, &temp_ushort) == 2) { + pp_data->caps_info[rt_idx].LastCap = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->caps_info[%u]->NumberOfCaps = %hu\n", &rt_idx, &temp_ushort) == 2) { + pp_data->caps_info[rt_idx].NumberOfCaps = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->caps_info[%u]->ReportByteLength = %hu\n", &rt_idx, &temp_ushort) == 2) { + pp_data->caps_info[rt_idx].ReportByteLength = temp_ushort; + continue; + } + fprintf(stderr, "Ignoring unimplemented caps_info field: %s", line); + continue; + } + + if (sscanf(line, "pp_data->FirstByteOfLinkCollectionArray = 0x%04hX\n", &FirstByteOfLinkCollectionArray)) { + continue; + } + if (sscanf(line, "pp_data->NumberLinkCollectionNodes = %hu\n", &NumberLinkCollectionNodes)) { + continue; + } + + if (sscanf(line, "pp_data->cap[%u]", &caps_idx) == 1) { + if (pp_data->FirstByteOfLinkCollectionArray == 0) { + fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray is 0 or not reported yet\n", line); + continue; + } + if ((caps_idx + 1) * sizeof(hid_pp_cap) > pp_data->FirstByteOfLinkCollectionArray) { + fprintf(stderr, "Error reading pp_data file (%s): the caps index (%u) is out of pp_data bytes boundary (%hu vs %hu)\n", line, caps_idx, (unsigned short) ((caps_idx + 1) * sizeof(hid_pp_cap)), pp_data->FirstByteOfLinkCollectionArray); + continue; + } + if (sscanf(line, "pp_data->cap[%u]->UsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].UsagePage = temp_usage; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->ReportID = 0x%02hhX\n", &caps_idx, &temp_uchar[0]) == 2) { + pp_data->caps[caps_idx].ReportID = temp_uchar[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->BitPosition = %hhu\n", &caps_idx, &temp_uchar[0]) == 2) { + pp_data->caps[caps_idx].BitPosition = temp_uchar[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->BitSize = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].ReportSize = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->ReportCount = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].ReportCount = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->BytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].BytePosition = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->BitCount = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].BitCount = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->BitField = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) { + pp_data->caps[caps_idx].BitField = temp_ulong; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NextBytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NextBytePosition = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->LinkCollection = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].LinkCollection = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->LinkUsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].LinkUsagePage = temp_usage; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->LinkUsage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].LinkUsage = temp_usage; + continue; + } + + // 8 Flags in one byte + if (sscanf(line, "pp_data->cap[%u]->IsMultipleItemsForArray = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsMultipleItemsForArray = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsButtonCap = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsButtonCap = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsPadding = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsPadding = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsAbsolute = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsAbsolute = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsRange = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsAlias = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsAlias = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsStringRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsStringRange = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->IsDesignatorRange = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].IsDesignatorRange = temp_boolean[0]; + continue; + } + + if (sscanf(line, "pp_data->cap[%u]->Reserved1 = 0x%hhu%hhu%hhu\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { + pp_data->caps[caps_idx].Reserved1[0] = temp_uchar[0]; + pp_data->caps[caps_idx].Reserved1[1] = temp_uchar[1]; + pp_data->caps[caps_idx].Reserved1[2] = temp_uchar[2]; + continue; + } + + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u]", &caps_idx, &token_idx) == 2) { + const size_t unknown_tokens_count = sizeof(pp_data->caps[0].UnknownTokens) / sizeof(pp_data->caps[0].UnknownTokens[0]); + if (token_idx >= unknown_tokens_count) { + fprintf(stderr, "Broken pp_data file, pp_data->caps[].UnknownTokens[] can have at most %zu elements, accessing %ud, (%s)", unknown_tokens_count, token_idx, line); + continue; + } + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].Token = 0x%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0]) == 3) { + pp_data->caps[caps_idx].UnknownTokens[token_idx].Token = temp_uchar[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].Reserved = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &token_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 5) { + pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[0] = temp_uchar[0]; + pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[1] = temp_uchar[1]; + pp_data->caps[caps_idx].UnknownTokens[token_idx].Reserved[2] = temp_uchar[2]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->pp_cap->UnknownTokens[%u].BitField = 0x%08lX\n", &caps_idx, &token_idx, &temp_ulong) == 3) { + pp_data->caps[caps_idx].UnknownTokens[token_idx].BitField = temp_ulong; + continue; + } + fprintf(stderr, "Ignoring unimplemented pp_data->cap[]->pp_cap->UnknownTokens field: %s", line); + continue; + } + + // Range + if (sscanf(line, "pp_data->cap[%u]->Range.UsageMin = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].Range.UsageMin = temp_usage; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.UsageMax = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].Range.UsageMax = temp_usage; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.StringMin = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].Range.StringMin = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.StringMax = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].Range.StringMax = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.DesignatorMin = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].Range.DesignatorMin = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.DesignatorMax = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].Range.DesignatorMax = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.DataIndexMin = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].Range.DataIndexMin = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Range.DataIndexMax = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].Range.DataIndexMax = temp_ushort; + continue; + } + + // NotRange + if (sscanf(line, "pp_data->cap[%u]->NotRange.Usage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].NotRange.Usage = temp_usage; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved1 = 0x%04hX\n", &caps_idx, &temp_usage) == 2) { + pp_data->caps[caps_idx].NotRange.Reserved1 = temp_usage; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.StringIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NotRange.StringIndex = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved2 = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NotRange.Reserved2 = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.DesignatorIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NotRange.DesignatorIndex = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved3 = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NotRange.Reserved3 = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.DataIndex = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NotRange.DataIndex = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotRange.Reserved4 = %hu\n", &caps_idx, &temp_ushort) == 2) { + pp_data->caps[caps_idx].NotRange.Reserved4 = temp_ushort; + continue; + } + + // Button + if (sscanf(line, "pp_data->cap[%u]->Button.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { + pp_data->caps[caps_idx].Button.LogicalMin = temp_long; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Button.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { + pp_data->caps[caps_idx].Button.LogicalMax = temp_long; + continue; + } + + // NotButton + if (sscanf(line, "pp_data->cap[%u]->NotButton.HasNull = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) { + pp_data->caps[caps_idx].NotButton.HasNull = temp_boolean[0]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotButton.Reserved4 = 0x%02hhX%02hhX%02hhX\n", &caps_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { + pp_data->caps[caps_idx].NotButton.Reserved4[0] = temp_uchar[0]; + pp_data->caps[caps_idx].NotButton.Reserved4[1] = temp_uchar[1]; + pp_data->caps[caps_idx].NotButton.Reserved4[2] = temp_uchar[2]; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotButton.LogicalMin = %ld\n", &caps_idx, &temp_long) == 2) { + pp_data->caps[caps_idx].NotButton.LogicalMin = temp_long; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotButton.LogicalMax = %ld\n", &caps_idx, &temp_long) == 2) { + pp_data->caps[caps_idx].NotButton.LogicalMax = temp_long; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotButton.PhysicalMin = %ld\n", &caps_idx, &temp_long) == 2) { + pp_data->caps[caps_idx].NotButton.PhysicalMin = temp_long; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->NotButton.PhysicalMax = %ld\n", &caps_idx, &temp_long) == 2) { + pp_data->caps[caps_idx].NotButton.PhysicalMax = temp_long; + continue; + } + + if (sscanf(line, "pp_data->cap[%u]->Units = %lu\n", &caps_idx, &temp_ulong) == 2) { + pp_data->caps[caps_idx].Units = temp_ulong; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->UnitsExp = %lu\n", &caps_idx, &temp_ulong) == 2) { + pp_data->caps[caps_idx].UnitsExp = temp_ulong; + continue; + } + if (sscanf(line, "pp_data->cap[%u]->Reserved1 = 0x%02hhu%02hhu%02hhu\n", &coll_idx, &temp_uchar[0], &temp_uchar[1], &temp_uchar[2]) == 4) { + pp_data->caps[caps_idx].Reserved1[0] = temp_uchar[0]; + pp_data->caps[caps_idx].Reserved1[1] = temp_uchar[1]; + pp_data->caps[caps_idx].Reserved1[2] = temp_uchar[2]; + continue; + } + fprintf(stderr, "Ignoring unimplemented cap field: %s", line); + continue; + } + + if (sscanf(line, "pp_data->LinkCollectionArray[%u]", &coll_idx) == 1) { + if (pp_data->FirstByteOfLinkCollectionArray == 0 || pp_data->NumberLinkCollectionNodes == 0) { + fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray or NumberLinkCollectionNodes is 0 or not reported yet\n", line); + continue; + } + if (coll_idx >= pp_data->NumberLinkCollectionNodes) { + fprintf(stderr, "Error reading pp_data file (%s): the LinkCollection index (%u) is out of boundary (%hu)\n", line, coll_idx, pp_data->NumberLinkCollectionNodes); + continue; + } + phid_pp_link_collection_node pcoll = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray); + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->LinkUsage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { + pcoll[coll_idx].LinkUsage = temp_usage; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->LinkUsagePage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) { + pcoll[coll_idx].LinkUsagePage = temp_usage; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->Parent = %hu\n", &coll_idx, &temp_ushort) == 2) { + pcoll[coll_idx].Parent = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->NumberOfChildren = %hu\n", &coll_idx, &temp_ushort) == 2) { + pcoll[coll_idx].NumberOfChildren = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->NextSibling = %hu\n", &coll_idx, &temp_ushort) == 2) { + pcoll[coll_idx].NextSibling = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->FirstChild = %hu\n", &coll_idx, &temp_ushort) == 2) { + pcoll[coll_idx].FirstChild = temp_ushort; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->CollectionType = %lu\n", &coll_idx, &temp_ulong) == 2) { + pcoll[coll_idx].CollectionType = temp_ulong; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->IsAlias = %lu\n", &coll_idx, &temp_ulong) == 2) { + pcoll[coll_idx].IsAlias = temp_ulong; + continue; + } + if (sscanf(line, "pp_data->LinkCollectionArray[%u]->Reserved = %lu\n", &coll_idx, &temp_ulong) == 2) { + pcoll[coll_idx].Reserved = temp_ulong; + continue; + } + fprintf(stderr, "Ignoring unimplemented LinkCollectionArray field: %s", line); + continue; + } + } + +//end: + fclose(file); + + if (pp_data == &static_pp_data) { + return NULL; + } + + return pp_data; +} + +static BOOLEAN read_hex_data_from_text_file(const char *filename, unsigned char *data_out, size_t data_size, size_t *actual_read) +{ + size_t read_index = 0; + FILE* file = NULL; + errno_t err = fopen_s(&file, filename, "r"); + if (err != 0) { + fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(err)); + return FALSE; + } + + BOOLEAN result = TRUE; + unsigned int val; + char buf[16]; + while (fscanf(file, "%15s", buf) == 1) { + if (sscanf(buf, "0x%X", &val) != 1) { + fprintf(stderr, "Invalid HEX text ('%s') file, got %s\n", filename, buf); + result = FALSE; + goto end; + } + + if (read_index >= data_size) { + fprintf(stderr, "Buffer for file read is too small. Got only %zu bytes to read '%s'\n", data_size, filename); + result = FALSE; + goto end; + } + + if (val > (unsigned char)-1) { + fprintf(stderr, "Invalid HEX text ('%s') file, got a value of: %u\n", filename, val); + result = FALSE; + goto end; + } + + data_out[read_index] = (unsigned char) val; + + read_index++; + } + + if (!feof(file)) { + fprintf(stderr, "Invalid HEX text ('%s') file - failed to read all values\n", filename); + result = FALSE; + goto end; + } + + *actual_read = read_index; + +end: + fclose(file); + return result; +} + + +int main(int argc, char* argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Expected 2 arguments for the test ('<>.pp_data' and '<>_expected.rpt_desc'), got: %d\n", argc - 1); + return EXIT_FAILURE; + } + + printf("Checking: '%s' / '%s'\n", argv[1], argv[2]); + + hidp_preparsed_data *pp_data = alloc_preparsed_data_from_file(argv[1]); + if (pp_data == NULL) { + return EXIT_FAILURE; + } + + int result = EXIT_SUCCESS; + + unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + + int res = hid_winapi_descriptor_reconstruct_pp_data(pp_data, report_descriptor, sizeof(report_descriptor)); + + if (res < 0) { + result = EXIT_FAILURE; + fprintf(stderr, "Failed to reconstruct descriptor"); + goto end; + } + size_t report_descriptor_size = (size_t) res; + + unsigned char expected_report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + size_t expected_report_descriptor_size = 0; + if (!read_hex_data_from_text_file(argv[2], expected_report_descriptor, sizeof(expected_report_descriptor), &expected_report_descriptor_size)) { + result = EXIT_FAILURE; + goto end; + } + + if (report_descriptor_size == expected_report_descriptor_size) { + if (memcmp(report_descriptor, expected_report_descriptor, report_descriptor_size) == 0) { + printf("Reconstructed Report Descriptor matches the expected descriptor\n"); + goto end; + } + else { + result = EXIT_FAILURE; + fprintf(stderr, "Reconstructed Report Descriptor has different content than expected\n"); + } + } + else { + result = EXIT_FAILURE; + fprintf(stderr, "Reconstructed Report Descriptor has different size: %zu when expected %zu\n", report_descriptor_size, expected_report_descriptor_size); + } + + printf(" Reconstructed Report Descriptor:\n"); + for (int i = 0; i < res; i++) { + printf("0x%02X, ", report_descriptor[i]); + } + printf("\n"); + fflush(stdout); + +end: + free(pp_data); + return result; +}