RFC: add hid_get_report_descriptor API function (#451)

- native implementations for hidraw/libusb/macOS;
- HID Report Descriptor reconstruction from HIDP_PREPARSED_DATA on Windows;
- unit-tests for some known devices for `hid_winapi_descriptor_reconstruct_pp_data`;
- support for ASAN builds (mainly to check the `hid_winapi_descriptor_reconstruct_pp_data`/its unit-tests;
This commit is contained in:
Ihor Dutchak
2023-03-12 14:45:30 +02:00
committed by GitHub
parent 88a0f029b7
commit 26b5bb0ccf
92 changed files with 22107 additions and 20 deletions
+19 -9
View File
@@ -42,9 +42,9 @@ jobs:
- 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/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
@@ -110,8 +110,8 @@ jobs:
- 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=${NIX_COMPILE_FLAGS}"
cmake -B build/static -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install/static -DBUILD_SHARED_LIBS=FALSE -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=${NIX_COMPILE_FLAGS}"
- name: Build CMake Shared
working-directory: build/shared
run: make install
@@ -173,10 +173,10 @@ jobs:
- 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
run: cmake --build . --config RelWithDebInfo --target install
- name: Check artifacts MSVC
uses: andstor/file-existence-action@v2
with:
@@ -196,12 +196,16 @@ jobs:
"-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
cd build\msvc_test
cmake --build . --target install
- name: Run CTest MSVC
shell: cmd
working-directory: build/msvc
run: ctest -C RelWithDebInfo --rerun-failed --output-on-failure
- name: Configure CMake NMake
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cmake -G"NMake Makefiles" -B build\nmake -S hidapisrc -DCMAKE_INSTALL_PREFIX=install\nmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
cmake -G"NMake Makefiles" -B build\nmake -S hidapisrc -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHIDAPI_WITH_TESTS=ON -DHIDAPI_BUILD_PP_DATA_DUMP=ON -DHIDAPI_ENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=install\nmake -DHIDAPI_BUILD_HIDTEST=ON "-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
- name: Build CMake NMake
working-directory: build\nmake
shell: cmd
@@ -229,11 +233,14 @@ jobs:
"-DCMAKE_C_FLAGS=%MSVC_COMPILE_FLAGS%"
cd build\nmake_test
nmake install
- name: Run CTest NMake
working-directory: build\nmake
run: ctest --rerun-failed --output-on-failure
- name: Configure CMake MinGW
shell: cmd
run: |
cmake -G"MinGW Makefiles" -B build\mingw -S hidapisrc -DCMAKE_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=%NIX_COMPILE_FLAGS%"
- name: Build CMake MinGW
working-directory: build\mingw
run: cmake --build . --target install
@@ -257,6 +264,9 @@ jobs:
"-DCMAKE_C_FLAGS=%NIX_COMPILE_FLAGS%"
cd build\mingw_test
cmake --build . --target install
- name: Run CTest MinGW
working-directory: build\mingw
run: ctest --rerun-failed --output-on-failure
- name: Check Meson build
shell: cmd
+2
View File
@@ -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;
<details>
<summary>Linux-specific variables</summary>
+49 -5
View File
@@ -49,13 +49,57 @@ option(BUILD_SHARED_LIBS "Build shared version of the libraries, otherwise build
set(HIDAPI_INSTALL_TARGETS ON)
set(HIDAPI_PRINT_VERSION ON)
set(IS_DEBUG_BUILD OFF)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(IS_DEBUG_BUILD ON)
endif()
option(HIDAPI_ENABLE_ASAN "Build HIDAPI with ASAN address sanitizer instrumentation" OFF)
if(HIDAPI_ENABLE_ASAN)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
if(MSVC)
# the default is to have "/INCREMENTAL" which causes a warning when "-fsanitize=address" is present
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /INCREMENTAL:NO")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /INCREMENTAL:NO")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO")
set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /INCREMENTAL:NO")
endif()
endif()
if(WIN32)
# so far only Windows has tests
option(HIDAPI_WITH_TESTS "Build HIDAPI (unit-)tests" ${IS_DEBUG_BUILD})
else()
set(HIDAPI_WITH_TESTS OFF)
endif()
if(HIDAPI_WITH_TESTS)
enable_testing()
endif()
if(WIN32)
option(HIDAPI_BUILD_PP_DATA_DUMP "Build small Windows console application pp_data_dump.exe" ${IS_DEBUG_BUILD})
endif()
add_subdirectory(src)
set(BUILD_HIDTEST_DEFAULT OFF)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(BUILD_HIDTEST_DEFAULT ON)
endif()
option(HIDAPI_BUILD_HIDTEST "Build small console test application hidtest" ${BUILD_HIDTEST_DEFAULT})
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()
+15
View File
@@ -550,6 +550,21 @@ extern "C" {
*/
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.
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.
This function is intended for logging/debugging purposes.
+44 -5
View File
@@ -64,10 +64,48 @@ void print_device(struct hid_device_info *cur_dev) {
printf("\n");
}
void print_hid_report_descriptor_from_device(hid_device *device) {
unsigned char descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE];
int res = 0;
printf(" Report Descriptor: ");
res = hid_get_report_descriptor(device, descriptor, sizeof(descriptor));
if (res < 0) {
printf("error getting: %ls", hid_error(device));
}
else {
printf("(%d bytes)", res);
}
for (int i = 0; i < res; i++) {
if (i % 10 == 0) {
printf("\n");
}
printf("0x%02x, ", descriptor[i]);
}
printf("\n");
}
void print_hid_report_descriptor_from_path(const char *path) {
hid_device *device = hid_open_path(path);
if (device) {
print_hid_report_descriptor_from_device(device);
hid_close(device);
}
else {
printf(" Report Descriptor: Unable to open device by path\n");
}
}
void print_devices(struct hid_device_info *cur_dev) {
while (cur_dev) {
for (; cur_dev; cur_dev = cur_dev->next) {
print_device(cur_dev);
cur_dev = cur_dev->next;
}
}
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);
}
}
@@ -103,7 +141,7 @@ int main(int argc, char* argv[])
#endif
devs = hid_enumerate(0x0, 0x0);
print_devices(devs);
print_devices_with_descriptor(devs);
hid_free_enumeration(devs);
// Set up the command buffer.
@@ -141,8 +179,9 @@ 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) {
+6
View File
@@ -1631,6 +1631,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;
+41
View File
@@ -481,6 +481,28 @@ static int parse_hid_vid_pid_from_sysfs(const char *sysfs_path, unsigned *bus_ty
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.
@@ -1236,6 +1258,25 @@ 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)
{
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)
{
+27
View File
@@ -1431,6 +1431,33 @@ 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)
{
if (dev) {
+3
View File
@@ -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()
+10
View File
@@ -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
@@ -51,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()
+21 -1
View File
@@ -30,7 +30,7 @@
extern "C" {
#endif
#include "hidapi.h"
#include "hidapi_winapi.h"
#include <windows.h>
@@ -1307,6 +1307,22 @@ end:
}
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) {
@@ -1320,6 +1336,10 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
return last_global_error_str;
}
#ifndef hidapi_winapi_EXPORTS
#include "hidapi_descriptor_reconstruct.c"
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
+988
View File
@@ -0,0 +1,988 @@
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
libusb/hidapi Team
Copyright 2022, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
https://github.com/libusb/hidapi .
********************************************************/
#include "hidapi_descriptor_reconstruct.h"
/**
* @brief References to report descriptor buffer.
*
*/
struct rd_buffer {
unsigned char* buf; /* Pointer to the array which stores the reconstructed descriptor */
size_t buf_size; /* Size of the buffer in bytes */
size_t byte_idx; /* Index of the next report byte to write to buf array */
};
/**
* @brief Function that appends a byte to encoded report descriptor buffer.
*
* @param[in] byte Single byte to append.
* @param rpt_desc Pointer to report descriptor buffer struct.
*/
static void rd_append_byte(unsigned char byte, struct rd_buffer* rpt_desc) {
if (rpt_desc->byte_idx < rpt_desc->buf_size) {
rpt_desc->buf[rpt_desc->byte_idx] = byte;
rpt_desc->byte_idx++;
}
}
/**
* @brief Writes a short report descriptor item according USB HID spec 1.11 chapter 6.2.2.2.
*
* @param[in] rd_item Enumeration identifying type (Main, Global, Local) and function (e.g Usage or Report Count) of the item.
* @param[in] data Data (Size depends on rd_item 0,1,2 or 4bytes).
* @param list Chained list of report descriptor bytes.
*
* @return Returns 0 if successful, -1 for error.
*/
static int rd_write_short_item(rd_items rd_item, LONG64 data, struct rd_buffer* rpt_desc) {
if (rd_item & 0x03) {
// Invalid input data, last to bits are reserved for data size
return -1;
}
if (rd_item == rd_main_collection_end) {
// Item without data (1Byte prefix only)
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x00;
rd_append_byte(oneBytePrefix, rpt_desc);
}
else if ((rd_item == rd_global_logical_minimum) ||
(rd_item == rd_global_logical_maximum) ||
(rd_item == rd_global_physical_minimum) ||
(rd_item == rd_global_physical_maximum)) {
// Item with signed integer data
if ((data >= -128) && (data <= 127)) {
// 1Byte prefix + 1Byte data
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
char localData = (char)data;
rd_append_byte(oneBytePrefix, rpt_desc);
rd_append_byte(localData & 0xFF, rpt_desc);
}
else if ((data >= -32768) && (data <= 32767)) {
// 1Byte prefix + 2Byte data
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
INT16 localData = (INT16)data;
rd_append_byte(oneBytePrefix, rpt_desc);
rd_append_byte(localData & 0xFF, rpt_desc);
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
}
else if ((data >= -2147483648LL) && (data <= 2147483647)) {
// 1Byte prefix + 4Byte data
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
INT32 localData = (INT32)data;
rd_append_byte(oneBytePrefix, rpt_desc);
rd_append_byte(localData & 0xFF, rpt_desc);
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
}
else {
// Data out of 32 bit signed integer range
return -1;
}
}
else {
// Item with unsigned integer data
if ((data >= 0) && (data <= 0xFF)) {
// 1Byte prefix + 1Byte data
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x01;
unsigned char localData = (unsigned char)data;
rd_append_byte(oneBytePrefix, rpt_desc);
rd_append_byte(localData & 0xFF, rpt_desc);
}
else if ((data >= 0) && (data <= 0xFFFF)) {
// 1Byte prefix + 2Byte data
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x02;
UINT16 localData = (UINT16)data;
rd_append_byte(oneBytePrefix, rpt_desc);
rd_append_byte(localData & 0xFF, rpt_desc);
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
}
else if ((data >= 0) && (data <= 0xFFFFFFFF)) {
// 1Byte prefix + 4Byte data
unsigned char oneBytePrefix = (unsigned char) rd_item + 0x03;
UINT32 localData = (UINT32)data;
rd_append_byte(oneBytePrefix, rpt_desc);
rd_append_byte(localData & 0xFF, rpt_desc);
rd_append_byte(localData >> 8 & 0xFF, rpt_desc);
rd_append_byte(localData >> 16 & 0xFF, rpt_desc);
rd_append_byte(localData >> 24 & 0xFF, rpt_desc);
}
else {
// Data out of 32 bit unsigned integer range
return -1;
}
}
return 0;
}
static struct rd_main_item_node * rd_append_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
struct rd_main_item_node *new_list_node;
// Determine last node in the list
while (*list != NULL)
{
list = &(*list)->next;
}
new_list_node = malloc(sizeof(*new_list_node)); // Create new list entry
new_list_node->FirstBit = first_bit;
new_list_node->LastBit = last_bit;
new_list_node->TypeOfNode = type_of_node;
new_list_node->CapsIndex = caps_index;
new_list_node->CollectionIndex = collection_index;
new_list_node->MainItemType = main_item_type;
new_list_node->ReportID = report_id;
new_list_node->next = NULL; // NULL marks last node in the list
*list = new_list_node;
return new_list_node;
}
static struct rd_main_item_node * rd_insert_main_item_node(int first_bit, int last_bit, rd_node_type type_of_node, int caps_index, int collection_index, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
// Insert item after the main item node referenced by list
struct rd_main_item_node *next_item = (*list)->next;
(*list)->next = NULL;
rd_append_main_item_node(first_bit, last_bit, type_of_node, caps_index, collection_index, main_item_type, report_id, list);
(*list)->next->next = next_item;
return (*list)->next;
}
static struct rd_main_item_node * rd_search_main_item_list_for_bit_position(int search_bit, rd_main_items main_item_type, unsigned char report_id, struct rd_main_item_node **list) {
// Determine first INPUT/OUTPUT/FEATURE main item, where the last bit position is equal or greater than the search bit position
while (((*list)->next->MainItemType != rd_collection) &&
((*list)->next->MainItemType != rd_collection_end) &&
!(((*list)->next->LastBit >= search_bit) &&
((*list)->next->ReportID == report_id) &&
((*list)->next->MainItemType == main_item_type))
)
{
list = &(*list)->next;
}
return *list;
}
int hid_winapi_descriptor_reconstruct_pp_data(void *preparsed_data, unsigned char *buf, size_t buf_size)
{
hidp_preparsed_data *pp_data = (hidp_preparsed_data *) preparsed_data;
// Check if MagicKey is correct, to ensure that pp_data points to an valid preparse data structure
if (memcmp(pp_data->MagicKey, "HidP KDR", 8) != 0) {
return -1;
}
struct rd_buffer rpt_desc = {
.buf = buf,
.buf_size = buf_size,
.byte_idx = 0
};
// Set pointer to the first node of link_collection_nodes
phid_pp_link_collection_node link_collection_nodes = (phid_pp_link_collection_node)(((unsigned char*)&pp_data->caps[0]) + pp_data->FirstByteOfLinkCollectionArray);
// ****************************************************************************************************************************
// Create lookup tables for the bit range of each report per collection (position of first bit and last bit in each collection)
// coll_bit_range[COLLECTION_INDEX][REPORT_ID][INPUT/OUTPUT/FEATURE]
// ****************************************************************************************************************************
// Allocate memory and initialize lookup table
rd_bit_range ****coll_bit_range;
coll_bit_range = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_bit_range));
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
coll_bit_range[collection_node_idx] = malloc(256 * sizeof(coll_bit_range[0])); // 256 possible report IDs (incl. 0x00)
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
coll_bit_range[collection_node_idx][reportid_idx] = malloc(NUM_OF_HIDP_REPORT_TYPES * sizeof(coll_bit_range[0][0]));
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
coll_bit_range[collection_node_idx][reportid_idx][rt_idx] = malloc(sizeof(rd_bit_range));
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = -1;
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = -1;
}
}
}
// Fill the lookup table where caps exist
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
for (USHORT caps_idx = pp_data->caps_info[rt_idx].FirstCap; caps_idx < pp_data->caps_info[rt_idx].LastCap; caps_idx++) {
int first_bit, last_bit;
first_bit = (pp_data->caps[caps_idx].BytePosition - 1) * 8
+ pp_data->caps[caps_idx].BitPosition;
last_bit = first_bit + pp_data->caps[caps_idx].ReportSize
* pp_data->caps[caps_idx].ReportCount - 1;
if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit == -1 ||
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit > first_bit) {
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->FirstBit = first_bit;
}
if (coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit < last_bit) {
coll_bit_range[pp_data->caps[caps_idx].LinkCollection][pp_data->caps[caps_idx].ReportID][rt_idx]->LastBit = last_bit;
}
}
}
// *************************************************************************
// -Determine hierachy levels of each collections and store it in:
// coll_levels[COLLECTION_INDEX]
// -Determine number of direct childs of each collections and store it in:
// coll_number_of_direct_childs[COLLECTION_INDEX]
// *************************************************************************
int max_coll_level = 0;
int *coll_levels = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_levels[0]));
int *coll_number_of_direct_childs = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_number_of_direct_childs[0]));
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
coll_levels[collection_node_idx] = -1;
coll_number_of_direct_childs[collection_node_idx] = 0;
}
{
int actual_coll_level = 0;
USHORT collection_node_idx = 0;
while (actual_coll_level >= 0) {
coll_levels[collection_node_idx] = actual_coll_level;
if ((link_collection_nodes[collection_node_idx].NumberOfChildren > 0) &&
(coll_levels[link_collection_nodes[collection_node_idx].FirstChild] == -1)) {
actual_coll_level++;
coll_levels[collection_node_idx] = actual_coll_level;
if (max_coll_level < actual_coll_level) {
max_coll_level = actual_coll_level;
}
coll_number_of_direct_childs[collection_node_idx]++;
collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
}
else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
coll_number_of_direct_childs[link_collection_nodes[collection_node_idx].Parent]++;
collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
}
else {
actual_coll_level--;
if (actual_coll_level >= 0) {
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
}
}
}
}
// *********************************************************************************
// Propagate the bit range of each report from the child collections to their parent
// and store the merged result for the parent
// *********************************************************************************
for (int actual_coll_level = max_coll_level - 1; actual_coll_level >= 0; actual_coll_level--) {
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
if (coll_levels[collection_node_idx] == actual_coll_level) {
USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
while (child_idx) {
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
// Merge bit range from childs
if ((coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
(coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit)) {
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->FirstBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->FirstBit;
}
if (coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit < coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit) {
coll_bit_range[collection_node_idx][reportid_idx][rt_idx]->LastBit = coll_bit_range[child_idx][reportid_idx][rt_idx]->LastBit;
}
child_idx = link_collection_nodes[child_idx].NextSibling;
}
}
}
}
}
}
// *************************************************************************************************
// Determine child collection order of the whole hierachy, based on previously determined bit ranges
// and store it this index coll_child_order[COLLECTION_INDEX][DIRECT_CHILD_INDEX]
// *************************************************************************************************
USHORT **coll_child_order;
coll_child_order = malloc(pp_data->NumberLinkCollectionNodes * sizeof(*coll_child_order));
{
BOOLEAN *coll_parsed_flag;
coll_parsed_flag = malloc(pp_data->NumberLinkCollectionNodes * sizeof(coll_parsed_flag[0]));
for (USHORT collection_node_idx = 0; collection_node_idx < pp_data->NumberLinkCollectionNodes; collection_node_idx++) {
coll_parsed_flag[collection_node_idx] = FALSE;
}
int actual_coll_level = 0;
USHORT collection_node_idx = 0;
while (actual_coll_level >= 0) {
if ((coll_number_of_direct_childs[collection_node_idx] != 0) &&
(coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] == FALSE)) {
coll_parsed_flag[link_collection_nodes[collection_node_idx].FirstChild] = TRUE;
coll_child_order[collection_node_idx] = malloc((coll_number_of_direct_childs[collection_node_idx]) * sizeof(coll_child_order[0]));
{
// Create list of child collection indices
// sorted reverse to the order returned to HidP_GetLinkCollectionNodeschild
// which seems to match teh original order, as long as no bit position needs to be considered
USHORT child_idx = link_collection_nodes[collection_node_idx].FirstChild;
int child_count = coll_number_of_direct_childs[collection_node_idx] - 1;
coll_child_order[collection_node_idx][child_count] = child_idx;
while (link_collection_nodes[child_idx].NextSibling) {
child_count--;
child_idx = link_collection_nodes[child_idx].NextSibling;
coll_child_order[collection_node_idx][child_count] = child_idx;
}
}
if (coll_number_of_direct_childs[collection_node_idx] > 1) {
// Sort child collections indices by bit positions
for (HIDP_REPORT_TYPE rt_idx = 0; rt_idx < NUM_OF_HIDP_REPORT_TYPES; rt_idx++) {
for (int reportid_idx = 0; reportid_idx < 256; reportid_idx++) {
for (int child_idx = 1; child_idx < coll_number_of_direct_childs[collection_node_idx]; child_idx++) {
// since the coll_bit_range array is not sorted, we need to reference the collection index in
// our sorted coll_child_order array, and look up the corresponding bit ranges for comparing values to sort
int prev_coll_idx = coll_child_order[collection_node_idx][child_idx - 1];
int cur_coll_idx = coll_child_order[collection_node_idx][child_idx];
if ((coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
(coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit != -1) &&
(coll_bit_range[prev_coll_idx][reportid_idx][rt_idx]->FirstBit > coll_bit_range[cur_coll_idx][reportid_idx][rt_idx]->FirstBit)) {
// Swap position indices of the two compared child collections
USHORT idx_latch = coll_child_order[collection_node_idx][child_idx - 1];
coll_child_order[collection_node_idx][child_idx - 1] = coll_child_order[collection_node_idx][child_idx];
coll_child_order[collection_node_idx][child_idx] = idx_latch;
}
}
}
}
}
actual_coll_level++;
collection_node_idx = link_collection_nodes[collection_node_idx].FirstChild;
}
else if (link_collection_nodes[collection_node_idx].NextSibling != 0) {
collection_node_idx = link_collection_nodes[collection_node_idx].NextSibling;
}
else {
actual_coll_level--;
if (actual_coll_level >= 0) {
collection_node_idx = link_collection_nodes[collection_node_idx].Parent;
}
}
}
free(coll_parsed_flag);
}
// ***************************************************************************************
// Create sorted main_item_list containing all the Collection and CollectionEnd main items
// ***************************************************************************************
struct rd_main_item_node *main_item_list = (struct rd_main_item_node*)malloc(sizeof(main_item_list));
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;
}
+238
View File
@@ -0,0 +1,238 @@
/*******************************************************
HIDAPI - Multi-Platform library for
communication with HID devices.
libusb/hidapi Team
Copyright 2022, All Rights Reserved.
At the discretion of the user of this library,
this software may be licensed under the terms of the
GNU General Public License v3, a BSD-Style license, or the
original HIDAPI license as outlined in the LICENSE.txt,
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
files located at the root of the source distribution.
These files may also be found in the public source
code repository located at:
https://github.com/libusb/hidapi .
********************************************************/
#ifndef HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
#define HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
/* Do not warn about wcsncpy usage.
https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "hidapi_winapi.h"
#if _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4200)
#pragma warning(disable: 4201)
#endif
#include <windows.h>
#include "hidapi_hidsdi.h"
#define NUM_OF_HIDP_REPORT_TYPES 3
typedef enum rd_items_ {
rd_main_input = 0x80, /* 1000 00 nn */
rd_main_output = 0x90, /* 1001 00 nn */
rd_main_feature = 0xB0, /* 1011 00 nn */
rd_main_collection = 0xA0, /* 1010 00 nn */
rd_main_collection_end = 0xC0, /* 1100 00 nn */
rd_global_usage_page = 0x04, /* 0000 01 nn */
rd_global_logical_minimum = 0x14, /* 0001 01 nn */
rd_global_logical_maximum = 0x24, /* 0010 01 nn */
rd_global_physical_minimum = 0x34, /* 0011 01 nn */
rd_global_physical_maximum = 0x44, /* 0100 01 nn */
rd_global_unit_exponent = 0x54, /* 0101 01 nn */
rd_global_unit = 0x64, /* 0110 01 nn */
rd_global_report_size = 0x74, /* 0111 01 nn */
rd_global_report_id = 0x84, /* 1000 01 nn */
rd_global_report_count = 0x94, /* 1001 01 nn */
rd_global_push = 0xA4, /* 1010 01 nn */
rd_global_pop = 0xB4, /* 1011 01 nn */
rd_local_usage = 0x08, /* 0000 10 nn */
rd_local_usage_minimum = 0x18, /* 0001 10 nn */
rd_local_usage_maximum = 0x28, /* 0010 10 nn */
rd_local_designator_index = 0x38, /* 0011 10 nn */
rd_local_designator_minimum = 0x48, /* 0100 10 nn */
rd_local_designator_maximum = 0x58, /* 0101 10 nn */
rd_local_string = 0x78, /* 0111 10 nn */
rd_local_string_minimum = 0x88, /* 1000 10 nn */
rd_local_string_maximum = 0x98, /* 1001 10 nn */
rd_local_delimiter = 0xA8 /* 1010 10 nn */
} rd_items;
typedef enum rd_main_items_ {
rd_input = HidP_Input,
rd_output = HidP_Output,
rd_feature = HidP_Feature,
rd_collection,
rd_collection_end,
rd_delimiter_open,
rd_delimiter_usage,
rd_delimiter_close,
} rd_main_items;
typedef struct rd_bit_range_ {
int FirstBit;
int LastBit;
} rd_bit_range;
typedef enum rd_item_node_type_ {
rd_item_node_cap,
rd_item_node_padding,
rd_item_node_collection,
} rd_node_type;
struct rd_main_item_node {
int FirstBit; /* Position of first bit in report (counting from 0) */
int LastBit; /* Position of last bit in report (counting from 0) */
rd_node_type TypeOfNode; /* Information if caps index refers to the array of button caps, value caps,
or if the node is just a padding element to fill unused bit positions.
The node can also be a collection node without any bits in the report. */
int CapsIndex; /* Index in the array of caps */
int CollectionIndex; /* Index in the array of link collections */
rd_main_items MainItemType; /* Input, Output, Feature, Collection or Collection End */
unsigned char ReportID;
struct rd_main_item_node* next;
};
typedef struct hid_pp_caps_info_ {
USHORT FirstCap;
USHORT NumberOfCaps; // Includes empty caps after LastCap
USHORT LastCap;
USHORT ReportByteLength;
} hid_pp_caps_info, *phid_pp_caps_info;
typedef struct hid_pp_link_collection_node_ {
USAGE LinkUsage;
USAGE LinkUsagePage;
USHORT Parent;
USHORT NumberOfChildren;
USHORT NextSibling;
USHORT FirstChild;
ULONG CollectionType : 8;
ULONG IsAlias : 1;
ULONG Reserved : 23;
// Same as the public API structure HIDP_LINK_COLLECTION_NODE, but without PVOID UserContext at the end
} hid_pp_link_collection_node, *phid_pp_link_collection_node;
typedef struct hidp_unknown_token_ {
UCHAR Token; /* Specifies the one-byte prefix of a global item. */
UCHAR Reserved[3];
ULONG BitField; /* Specifies the data part of the global item. */
} hidp_unknown_token, * phidp_unknown_token;
typedef struct hid_pp_cap_ {
USAGE UsagePage;
UCHAR ReportID;
UCHAR BitPosition;
USHORT ReportSize; // WIN32 term for this is BitSize
USHORT ReportCount;
USHORT BytePosition;
USHORT BitCount;
ULONG BitField;
USHORT NextBytePosition;
USHORT LinkCollection;
USAGE LinkUsagePage;
USAGE LinkUsage;
// Start of 8 Flags in one byte
BOOLEAN IsMultipleItemsForArray:1;
BOOLEAN IsPadding:1;
BOOLEAN IsButtonCap:1;
BOOLEAN IsAbsolute:1;
BOOLEAN IsRange:1;
BOOLEAN IsAlias:1; // IsAlias is set to TRUE in the first n-1 capability structures added to the capability array. IsAlias set to FALSE in the nth capability structure.
BOOLEAN IsStringRange:1;
BOOLEAN IsDesignatorRange:1;
// End of 8 Flags in one byte
BOOLEAN Reserved1[3];
hidp_unknown_token UnknownTokens[4]; // 4 x 8 Byte
union {
struct {
USAGE UsageMin;
USAGE UsageMax;
USHORT StringMin;
USHORT StringMax;
USHORT DesignatorMin;
USHORT DesignatorMax;
USHORT DataIndexMin;
USHORT DataIndexMax;
} Range;
struct {
USAGE Usage;
USAGE Reserved1;
USHORT StringIndex;
USHORT Reserved2;
USHORT DesignatorIndex;
USHORT Reserved3;
USHORT DataIndex;
USHORT Reserved4;
} NotRange;
};
union {
struct {
LONG LogicalMin;
LONG LogicalMax;
} Button;
struct {
BOOLEAN HasNull;
UCHAR Reserved4[3];
LONG LogicalMin;
LONG LogicalMax;
LONG PhysicalMin;
LONG PhysicalMax;
} NotButton;
};
ULONG Units;
ULONG UnitsExp;
} hid_pp_cap, *phid_pp_cap;
typedef struct hidp_preparsed_data_ {
UCHAR MagicKey[8];
USAGE Usage;
USAGE UsagePage;
USHORT Reserved[2];
// CAPS structure for Input, Output and Feature
hid_pp_caps_info caps_info[3];
USHORT FirstByteOfLinkCollectionArray;
USHORT NumberLinkCollectionNodes;
#if defined(__MINGW32__) || defined(__CYGWIN__)
// MINGW fails with: Flexible array member in union not supported
// Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
union {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
hid_pp_cap caps[0];
hid_pp_link_collection_node LinkCollectionArray[0];
#pragma GCC diagnostic pop
};
#else
union {
hid_pp_cap caps[];
hid_pp_link_collection_node LinkCollectionArray[];
};
#endif
} hidp_preparsed_data;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif
+7
View File
@@ -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
+16
View File
@@ -26,6 +26,8 @@
#ifndef HIDAPI_WINAPI_H__
#define HIDAPI_WINAPI_H__
#include <stdint.h>
#include <guiddef.h>
#include "hidapi.h"
@@ -51,6 +53,20 @@ extern "C" {
*/
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
+15
View File
@@ -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}"
)
+122
View File
@@ -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
```
<vendor_id>_<product_id>_<usage>_<usage_table>.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
```
+238
View File
@@ -0,0 +1,238 @@
#include <hid.c>
#include <../windows/hidapi_descriptor_reconstruct.h>
#include <hidapi.h>
#if defined(__MINGW32__)
#pragma GCC diagnostic ignored "-Wformat"
#pragma GCC diagnostic ignored "-Wformat-extra-args"
#endif
void dump_hid_pp_cap(FILE* file, phid_pp_cap pp_cap, unsigned int cap_idx) {
fprintf(file, "pp_data->cap[%d]->UsagePage = 0x%04hX\n", cap_idx, pp_cap->UsagePage);
fprintf(file, "pp_data->cap[%d]->ReportID = 0x%02hhX\n", cap_idx, pp_cap->ReportID);
fprintf(file, "pp_data->cap[%d]->BitPosition = %hhu\n", cap_idx, pp_cap->BitPosition);
fprintf(file, "pp_data->cap[%d]->BitSize = %hu\n", cap_idx, pp_cap->ReportSize);
fprintf(file, "pp_data->cap[%d]->ReportCount = %hu\n", cap_idx, pp_cap->ReportCount);
fprintf(file, "pp_data->cap[%d]->BytePosition = 0x%04hX\n", cap_idx, pp_cap->BytePosition);
fprintf(file, "pp_data->cap[%d]->BitCount = %hu\n", cap_idx, pp_cap->BitCount);
fprintf(file, "pp_data->cap[%d]->BitField = 0x%02lX\n", cap_idx, pp_cap->BitField);
fprintf(file, "pp_data->cap[%d]->NextBytePosition = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition);
fprintf(file, "pp_data->cap[%d]->LinkCollection = 0x%04hX\n", cap_idx, pp_cap->LinkCollection);
fprintf(file, "pp_data->cap[%d]->LinkUsagePage = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage);
fprintf(file, "pp_data->cap[%d]->LinkUsage = 0x%04hX\n", cap_idx, pp_cap->LinkUsage);
// 8 Flags in one byte
fprintf(file, "pp_data->cap[%d]->IsMultipleItemsForArray = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray);
fprintf(file, "pp_data->cap[%d]->IsButtonCap = %hhu\n", cap_idx, pp_cap->IsButtonCap);
fprintf(file, "pp_data->cap[%d]->IsPadding = %hhu\n", cap_idx, pp_cap->IsPadding);
fprintf(file, "pp_data->cap[%d]->IsAbsolute = %hhu\n", cap_idx, pp_cap->IsAbsolute);
fprintf(file, "pp_data->cap[%d]->IsRange = %hhu\n", cap_idx, pp_cap->IsRange);
fprintf(file, "pp_data->cap[%d]->IsAlias = %hhu\n", cap_idx, pp_cap->IsAlias);
fprintf(file, "pp_data->cap[%d]->IsStringRange = %hhu\n", cap_idx, pp_cap->IsStringRange);
fprintf(file, "pp_data->cap[%d]->IsDesignatorRange = %hhu\n", cap_idx, pp_cap->IsDesignatorRange);
fprintf(file, "pp_data->cap[%d]->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[%d]->pp_cap->UnknownTokens[%d].Token = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token);
fprintf(file, "pp_data->cap[%d]->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[%d]->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[%d]->Range.UsageMin = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin);
fprintf(file, "pp_data->cap[%d]->Range.UsageMax = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax);
fprintf(file, "pp_data->cap[%d]->Range.StringMin = %hu\n", cap_idx, pp_cap->Range.StringMin);
fprintf(file, "pp_data->cap[%d]->Range.StringMax = %hu\n", cap_idx, pp_cap->Range.StringMax);
fprintf(file, "pp_data->cap[%d]->Range.DesignatorMin = %hu\n", cap_idx, pp_cap->Range.DesignatorMin);
fprintf(file, "pp_data->cap[%d]->Range.DesignatorMax = %hu\n", cap_idx, pp_cap->Range.DesignatorMax);
fprintf(file, "pp_data->cap[%d]->Range.DataIndexMin = %hu\n", cap_idx, pp_cap->Range.DataIndexMin);
fprintf(file, "pp_data->cap[%d]->Range.DataIndexMax = %hu\n", cap_idx, pp_cap->Range.DataIndexMax);
}
else {
fprintf(file, "pp_data->cap[%d]->NotRange.Usage = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage);
fprintf(file, "pp_data->cap[%d]->NotRange.Reserved1 = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1);
fprintf(file, "pp_data->cap[%d]->NotRange.StringIndex = %hu\n", cap_idx, pp_cap->NotRange.StringIndex);
fprintf(file, "pp_data->cap[%d]->NotRange.Reserved2 = %hu\n", cap_idx, pp_cap->NotRange.Reserved2);
fprintf(file, "pp_data->cap[%d]->NotRange.DesignatorIndex = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex);
fprintf(file, "pp_data->cap[%d]->NotRange.Reserved3 = %hu\n", cap_idx, pp_cap->NotRange.Reserved3);
fprintf(file, "pp_data->cap[%d]->NotRange.DataIndex = %hu\n", cap_idx, pp_cap->NotRange.DataIndex);
fprintf(file, "pp_data->cap[%d]->NotRange.Reserved4 = %hu\n", cap_idx, pp_cap->NotRange.Reserved4);
}
if (pp_cap->IsButtonCap) {
fprintf(file, "pp_data->cap[%d]->Button.LogicalMin = %ld\n", cap_idx, pp_cap->Button.LogicalMin);
fprintf(file, "pp_data->cap[%d]->Button.LogicalMax = %ld\n", cap_idx, pp_cap->Button.LogicalMax);
}
else
{
fprintf(file, "pp_data->cap[%d]->NotButton.HasNull = %hhu\n", cap_idx, pp_cap->NotButton.HasNull);
fprintf(file, "pp_data->cap[%d]->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[%d]->NotButton.LogicalMin = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin);
fprintf(file, "pp_data->cap[%d]->NotButton.LogicalMax = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax);
fprintf(file, "pp_data->cap[%d]->NotButton.PhysicalMin = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin);
fprintf(file, "pp_data->cap[%d]->NotButton.PhysicalMax = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax);
};
fprintf(file, "pp_data->cap[%d]->Units = %lu\n", cap_idx, pp_cap->Units);
fprintf(file, "pp_data->cap[%d]->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[%d]->LinkUsage = 0x%04hX\n", coll_idx, pcoll->LinkUsage);
fprintf(file, "pp_data->LinkCollectionArray[%d]->LinkUsagePage = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage);
fprintf(file, "pp_data->LinkCollectionArray[%d]->Parent = %hu\n", coll_idx, pcoll->Parent);
fprintf(file, "pp_data->LinkCollectionArray[%d]->NumberOfChildren = %hu\n", coll_idx, pcoll->NumberOfChildren);
fprintf(file, "pp_data->LinkCollectionArray[%d]->NextSibling = %hu\n", coll_idx, pcoll->NextSibling);
fprintf(file, "pp_data->LinkCollectionArray[%d]->FirstChild = %hu\n", coll_idx, pcoll->FirstChild);
fprintf(file, "pp_data->LinkCollectionArray[%d]->CollectionType = %d\n", coll_idx, pcoll->CollectionType);
fprintf(file, "pp_data->LinkCollectionArray[%d]->IsAlias = %d\n", coll_idx, pcoll->IsAlias);
fprintf(file, "pp_data->LinkCollectionArray[%d]->Reserved = 0x%08X\n", coll_idx, 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;
}
+76
View File
@@ -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:
# <name>.pp_data - textual representation of HIDP_PREPARSED_DATA;
# <name>_expected.rpt_desc - reconstructed HID Report Descriptor out of .pp_data file;
#
# (Non-required by test):
# <name>_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 "$<TARGET_FILE_DIR:hidapi_winapi>"
)
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()
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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,
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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,
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
File diff suppressed because it is too large Load Diff
@@ -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,
@@ -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
@@ -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
@@ -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,
@@ -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
File diff suppressed because it is too large Load Diff
@@ -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,
@@ -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
@@ -0,0 +1,560 @@
#include "../hidapi_descriptor_reconstruct.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#if defined(__MINGW32__)
#pragma GCC diagnostic ignored "-Wformat"
#endif
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");
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[%d]", &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[<idx>] can have at most %zu elements, accessing %ud, (%s)", caps_info_count, rt_idx, line);
continue;
}
if (sscanf(line, "pp_data->caps_info[%d]->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[%d]->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[%d]->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[%d]->ReportByteLength = %hu\n", &rt_idx, &temp_ushort) == 2) {
pp_data->caps_info[rt_idx].ReportByteLength = temp_ushort;
continue;
}
fprintf(stderr, "Ignorring 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[%d]", &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[%d]->UsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
pp_data->caps[caps_idx].UsagePage = temp_usage;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->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[%d]->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[%d]->BitSize = %hu\n", &caps_idx, &temp_ushort) == 2) {
pp_data->caps[caps_idx].ReportSize = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->ReportCount = %hu\n", &caps_idx, &temp_ushort) == 2) {
pp_data->caps[caps_idx].ReportCount = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->BytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
pp_data->caps[caps_idx].BytePosition = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->BitCount = %hu\n", &caps_idx, &temp_ushort) == 2) {
pp_data->caps[caps_idx].BitCount = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->BitField = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) {
pp_data->caps[caps_idx].BitField = temp_ulong;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->NextBytePosition = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
pp_data->caps[caps_idx].NextBytePosition = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->LinkCollection = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
pp_data->caps[caps_idx].LinkCollection = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->LinkUsagePage = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
pp_data->caps[caps_idx].LinkUsagePage = temp_usage;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->pp_cap->UnknownTokens[%d]", &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[<idx>].UnknownTokens[<idx>] can have at most %zu elements, accessing %ud, (%s)", unknown_tokens_count, token_idx, line);
continue;
}
if (sscanf(line, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].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[%d]->pp_cap->UnknownTokens[%d].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[%d]->pp_cap->UnknownTokens[%d].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, "Ignorring unimplemented pp_data->cap[]->pp_cap->UnknownTokens field: %s", line);
continue;
}
// Range
if (sscanf(line, "pp_data->cap[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->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[%d]->Units = %lu\n", &caps_idx, &temp_ulong) == 2) {
pp_data->caps[caps_idx].Units = temp_ulong;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->UnitsExp = %lu\n", &caps_idx, &temp_ulong) == 2) {
pp_data->caps[caps_idx].UnitsExp = temp_ulong;
continue;
}
if (sscanf(line, "pp_data->cap[%d]->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, "Ignorring unimplemented cap field: %s", line);
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]", &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[%d]->LinkUsage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) {
pcoll[coll_idx].LinkUsage = temp_usage;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->LinkUsagePage = 0x%04hX\n", &coll_idx, &temp_usage) == 2) {
pcoll[coll_idx].LinkUsagePage = temp_usage;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->Parent = %hu\n", &coll_idx, &temp_ushort) == 2) {
pcoll[coll_idx].Parent = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->NumberOfChildren = %hu\n", &coll_idx, &temp_ushort) == 2) {
pcoll[coll_idx].NumberOfChildren = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->NextSibling = %hu\n", &coll_idx, &temp_ushort) == 2) {
pcoll[coll_idx].NextSibling = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->FirstChild = %hu\n", &coll_idx, &temp_ushort) == 2) {
pcoll[coll_idx].FirstChild = temp_ushort;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->CollectionType = %ld\n", &coll_idx, &temp_ulong) == 2) {
pcoll[coll_idx].CollectionType = temp_ulong;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->IsAlias = %ld\n", &coll_idx, &temp_ulong) == 2) {
pcoll[coll_idx].IsAlias = temp_ulong;
continue;
}
if (sscanf(line, "pp_data->LinkCollectionArray[%d]->Reserved = %ld\n", &coll_idx, &temp_ulong) == 2) {
pcoll[coll_idx].Reserved = temp_ulong;
continue;
}
fprintf(stderr, "Ignorring 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;
}