248 lines
7.4 KiB
C
248 lines
7.4 KiB
C
|
/*******************************************************
|
||
|
HIDAPI - Multi-Platform library for
|
||
|
communication with HID devices.
|
||
|
|
||
|
libusb/hidapi Team
|
||
|
|
||
|
Copyright 2022, All Rights Reserved.
|
||
|
|
||
|
At the discretion of the user of this library,
|
||
|
this software may be licensed under the terms of the
|
||
|
GNU General Public License v3, a BSD-Style license, or the
|
||
|
original HIDAPI license as outlined in the LICENSE.txt,
|
||
|
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||
|
files located at the root of the source distribution.
|
||
|
These files may also be found in the public source
|
||
|
code repository located at:
|
||
|
https://github.com/libusb/hidapi .
|
||
|
********************************************************/
|
||
|
#ifndef HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
|
||
|
#define HIDAPI_DESCRIPTOR_RECONSTRUCT_H__
|
||
|
|
||
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||
|
/* Do not warn about wcsncpy usage.
|
||
|
https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */
|
||
|
#define _CRT_SECURE_NO_WARNINGS
|
||
|
#endif
|
||
|
|
||
|
#include "hidapi_winapi.h"
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable: 4200)
|
||
|
#pragma warning(disable: 4201)
|
||
|
#pragma warning(disable: 4214)
|
||
|
#endif
|
||
|
|
||
|
#include <windows.h>
|
||
|
|
||
|
#include "hidapi_hidsdi.h"
|
||
|
#include <assert.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;
|
||
|
|
||
|
// Note: This is risk-reduction-measure for this specific struct, as it has ULONG bit-field.
|
||
|
// Although very unlikely, it might still be possible that the compiler creates a memory layout that is
|
||
|
// not binary compatile.
|
||
|
// Other structs are not checked at the time of writing.
|
||
|
static_assert(sizeof(struct hid_pp_link_collection_node_) == 16,
|
||
|
"Size of struct hid_pp_link_collection_node_ not as expected. This might break binary compatibility");
|
||
|
|
||
|
typedef struct hidp_unknown_token_ {
|
||
|
UCHAR Token; /* Specifies the one-byte prefix of a global item. */
|
||
|
UCHAR Reserved[3];
|
||
|
ULONG BitField; /* Specifies the data part of the global item. */
|
||
|
} hidp_unknown_token, * phidp_unknown_token;
|
||
|
|
||
|
typedef struct hid_pp_cap_ {
|
||
|
USAGE UsagePage;
|
||
|
UCHAR ReportID;
|
||
|
UCHAR BitPosition;
|
||
|
USHORT ReportSize; // WIN32 term for this is BitSize
|
||
|
USHORT ReportCount;
|
||
|
USHORT BytePosition;
|
||
|
USHORT BitCount;
|
||
|
ULONG BitField;
|
||
|
USHORT NextBytePosition;
|
||
|
USHORT LinkCollection;
|
||
|
USAGE LinkUsagePage;
|
||
|
USAGE LinkUsage;
|
||
|
|
||
|
// Start of 8 Flags in one byte
|
||
|
BOOLEAN IsMultipleItemsForArray:1;
|
||
|
|
||
|
BOOLEAN IsPadding:1;
|
||
|
BOOLEAN IsButtonCap:1;
|
||
|
BOOLEAN IsAbsolute:1;
|
||
|
BOOLEAN IsRange:1;
|
||
|
BOOLEAN IsAlias:1; // IsAlias is set to TRUE in the first n-1 capability structures added to the capability array. IsAlias set to FALSE in the nth capability structure.
|
||
|
BOOLEAN IsStringRange:1;
|
||
|
BOOLEAN IsDesignatorRange:1;
|
||
|
// End of 8 Flags in one byte
|
||
|
BOOLEAN Reserved1[3];
|
||
|
|
||
|
hidp_unknown_token UnknownTokens[4]; // 4 x 8 Byte
|
||
|
|
||
|
union {
|
||
|
struct {
|
||
|
USAGE UsageMin;
|
||
|
USAGE UsageMax;
|
||
|
USHORT StringMin;
|
||
|
USHORT StringMax;
|
||
|
USHORT DesignatorMin;
|
||
|
USHORT DesignatorMax;
|
||
|
USHORT DataIndexMin;
|
||
|
USHORT DataIndexMax;
|
||
|
} Range;
|
||
|
struct {
|
||
|
USAGE Usage;
|
||
|
USAGE Reserved1;
|
||
|
USHORT StringIndex;
|
||
|
USHORT Reserved2;
|
||
|
USHORT DesignatorIndex;
|
||
|
USHORT Reserved3;
|
||
|
USHORT DataIndex;
|
||
|
USHORT Reserved4;
|
||
|
} NotRange;
|
||
|
};
|
||
|
union {
|
||
|
struct {
|
||
|
LONG LogicalMin;
|
||
|
LONG LogicalMax;
|
||
|
} Button;
|
||
|
struct {
|
||
|
BOOLEAN HasNull;
|
||
|
UCHAR Reserved4[3];
|
||
|
LONG LogicalMin;
|
||
|
LONG LogicalMax;
|
||
|
LONG PhysicalMin;
|
||
|
LONG PhysicalMax;
|
||
|
} NotButton;
|
||
|
};
|
||
|
ULONG Units;
|
||
|
ULONG UnitsExp;
|
||
|
|
||
|
} hid_pp_cap, *phid_pp_cap;
|
||
|
|
||
|
typedef struct hidp_preparsed_data_ {
|
||
|
UCHAR MagicKey[8];
|
||
|
USAGE Usage;
|
||
|
USAGE UsagePage;
|
||
|
USHORT Reserved[2];
|
||
|
|
||
|
// CAPS structure for Input, Output and Feature
|
||
|
hid_pp_caps_info caps_info[3];
|
||
|
|
||
|
USHORT FirstByteOfLinkCollectionArray;
|
||
|
USHORT NumberLinkCollectionNodes;
|
||
|
|
||
|
#ifndef _MSC_VER
|
||
|
// MINGW fails with: Flexible array member in union not supported
|
||
|
// Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
|
||
|
union {
|
||
|
#pragma GCC diagnostic push
|
||
|
#pragma GCC diagnostic ignored "-Wpedantic"
|
||
|
hid_pp_cap caps[0];
|
||
|
hid_pp_link_collection_node LinkCollectionArray[0];
|
||
|
#pragma GCC diagnostic pop
|
||
|
};
|
||
|
#else
|
||
|
union {
|
||
|
hid_pp_cap caps[];
|
||
|
hid_pp_link_collection_node LinkCollectionArray[];
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
} hidp_preparsed_data;
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning(pop)
|
||
|
#endif
|
||
|
|
||
|
#endif
|