From 739c6e405dc8bb21a94a68b9482e0c321f06fa95 Mon Sep 17 00:00:00 2001 From: bagong Date: Sun, 22 May 2016 09:14:25 +0200 Subject: [PATCH 01/29] Fix policy-warning in cmake output for different cmake versions --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 719d48bb..27f42420 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,8 @@ cmake_minimum_required(VERSION 2.8) +if(${CMAKE_MAJOR_VERSION} GREATER 2) + cmake_policy(SET CMP0048 OLD) +endif(${CMAKE_MAJOR_VERSION} GREATER 2) + cmake_policy(SET CMP0048 OLD) project(hidapi) From c940d263e297a9f8273572bb1b0a540e4f730792 Mon Sep 17 00:00:00 2001 From: Marije Baalman Date: Wed, 5 Nov 2014 17:01:28 +0100 Subject: [PATCH 02/29] win: towards a windows version --- CMakeLists.txt | 3 + hidapi_parser/hidapi_parser.c | 69 +++++++ hidtest/hidtest.cpp | 14 +- hidtestwindows/CMakeLists.txt | 18 ++ hidtestwindows/hidtestwindows.cpp | 311 ++++++++++++++++++++++++++++++ windows/hid.c | 117 +++++++++++ 6 files changed, 527 insertions(+), 5 deletions(-) create mode 100644 hidtestwindows/CMakeLists.txt create mode 100644 hidtestwindows/hidtestwindows.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 27f42420..5cd6768e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,9 @@ if( HID_EXAMPLE_TEST ) if(APPLE) add_subdirectory(hidtestosx) endif() + if(WIN32) + add_subdirectory(hidtestwindows) + endif() endif() if( HID_EXAMPLE_OSC ) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 3f94cb50..d6043efd 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -1240,6 +1240,75 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d } void hid_parse_element_info( struct hid_dev_desc * devdesc ){ + hid_device * dev = devdesc->device; + + struct hid_device_collection * device_collection = hid_new_collection(); + devdesc->device_collection = device_collection; + + struct hid_device_collection * parent_collection = devdesc->device_collection; + struct hid_device_collection * prev_collection; + struct hid_device_element * prev_element; + + device_collection->num_collections = 0; + device_collection->num_elements = 0; + + int numreports = 1; + int report_lengths[256]; + int report_ids[256]; + report_ids[0] = 0; + report_lengths[0] = 0; + + + int numColls = 0; + + int nt_res, nt_res2; + /* Get the Usage Page and Usage for this device. */ + res = HidD_GetPreparsedData(write_handle, &pp_data); + if (res) { + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res == HIDP_STATUS_SUCCESS) { + numColls = caps.NumberLinkCollectionNodes; + + device_collection->num_collections = numColls; + device_collection->usage_page = caps.UsagePage; + device_collection->usage = caps.Usage; + + device_collection->index = 0; + // type + // num_elements + // usage_min , usage_max + // parent_collection + // next_collection + // first_collection + // first_element + + // num_elements: + // NumberInputButtonCaps + NumberInputValueCaps + + // NumberOutputButtonCaps + NumberOutputValueCaps + + // NumberFeatureButtonCaps + NumberFeatureValueCaps + device_collection->num_elements = + caps.NumberInputButtonCaps + caps.NumberInputValueCaps + + caps.NumberOutputButtonCaps + caps.NumberOutputValueCaps + + caps.NumberFeatureButtonCaps + caps.NumberFeatureValueCaps; + + + PHIDP_LINK_COLLECTION_NODE linkCollectionNodes[ numColls ]; + nt_res2 = HidP_GetLinkCollectionNodes( linkCollectionNodes, numColls, pp_data ); + if (nt_res2 == HIDP_STATUS_SUCCESS) { + // then I have the linkCollectionNodes + } + // input + int numValueCaps = caps.NumberInputValueCaps; + PHIDP_VALUE_CAPS pInputValueCaps[ numValueCaps ]; + nt_res2 = HidP_GetValueCaps( HidP_Input, pInputValueCaps, numValueCaps, pp_data ); + // output + // feature + } + + HidD_FreePreparsedData(pp_data); + } + + } #endif diff --git a/hidtest/hidtest.cpp b/hidtest/hidtest.cpp index 7682afa5..8ff3ea80 100644 --- a/hidtest/hidtest.cpp +++ b/hidtest/hidtest.cpp @@ -224,7 +224,8 @@ int main(int argc, char* argv[]) return -1; devs = hid_enumerate(0x0, 0x0); - cur_dev = devs; + cur_dev = devs; + printf( "curdev %ls\n", cur_dev ); 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"); @@ -250,7 +251,9 @@ int main(int argc, char* argv[]) // mouse: // handle = hid_open(0x1241, 0x1166, NULL); // run'n'drive - handle = hid_open(0x044f, 0xd003, NULL); +// handle = hid_open(0x044f, 0xd003, NULL); + // impakt + handle = hid_open(0x07b5, 0x0312, NULL); if (!handle) { printf("unable to open device\n"); return 1; @@ -285,7 +288,7 @@ int main(int argc, char* argv[]) printf("Unable to read indexed string 1\n"); printf("Indexed String 1: %ls\n", wstr); - +/* //// PARSING THE DESCRIPTOR res = hid_get_report_descriptor( handle, descr_buf, MAX_DESCRIPTOR ); if (res < 0) @@ -560,7 +563,7 @@ int main(int argc, char* argv[]) } printf("\n"); printf("number of elements, %i\n", descriptor->num_elements ); - +*/ // Set the hid_read() function to be non-blocking. hid_set_nonblocking(handle, 1); // @@ -620,6 +623,7 @@ int main(int argc, char* argv[]) // printf("bitmask test, %i, %i, %02hhx\n", i, BITMASK1(i), BITMASK1(i) ); // } +/* // Read requested state. hid_read() has been set to be // non-blocking by the call to hid_set_nonblocking() above. // This loop demonstrates the non-blocking nature of hid_read(). @@ -661,7 +665,7 @@ int main(int argc, char* argv[]) usleep(500*100); #endif } - +*/ hid_close(handle); diff --git a/hidtestwindows/CMakeLists.txt b/hidtestwindows/CMakeLists.txt new file mode 100644 index 00000000..19a0fb38 --- /dev/null +++ b/hidtestwindows/CMakeLists.txt @@ -0,0 +1,18 @@ +message( "===hidtestwindows cmakelists===" ) + +include_directories( + ${CMAKE_BINARY_DIR} + ${hidapi_SOURCE_DIR}/hidapi/ + ${hidapi_SOURCE_DIR}/hidapi_parser/ +) + + +set(hidtest_SRCS + hidtestwindows.cpp +) + +add_executable( hidtestwindows ${hidtest_SRCS} ) + +target_link_libraries(hidtestwindows hidapi hidapi_parser ${EXTRA_LIBS}) + +install(TARGETS hidtestwindows DESTINATION bin) diff --git a/hidtestwindows/hidtestwindows.cpp b/hidtestwindows/hidtestwindows.cpp new file mode 100644 index 00000000..7ee18203 --- /dev/null +++ b/hidtestwindows/hidtestwindows.cpp @@ -0,0 +1,311 @@ +/* hidapi_parser $ + * + * Copyright (C) 2013, Marije Baalman + * This work was funded by a crowd-funding initiative for SuperCollider's [1] HID implementation + * including a substantial donation from BEK, Bergen Center for Electronic Arts, Norway + * + * [1] http://supercollider.sourceforge.net + * [2] http://www.bek.no + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/******************************************************* + Windows HID simplification + + Alan Ott + Signal 11 Software + + 8/22/2009 + + Copyright 2009 + + This contents of this file may be used by anyone + for any reason without any conditions and may be + used as a starting point for your own applications + which use HIDAPI. +********************************************************/ + +//TODO: add copyright notice + +#include +#include +#include +#include +#include "hidapi.h" + +// Headers needed for sleeping. +#ifdef _WIN32 + #include +#else + #include +#endif + + +//// ---------- HID descriptor parser + +#define MAX_DESCRIPTOR 4096 + + +// main items +#define HID_INPUT 0x80 +#define HID_OUTPUT 0x90 +#define HID_COLLECTION 0xA0 +#define HID_FEATURE 0xB0 +// #define HID_COLLECTION 0xa1 +#define HID_END_COLLECTION 0xC0 + +// HID Report Items from HID 1.11 Section 6.2.2 +#define HID_USAGE_PAGE 0x04 +// #define HID_USAGE_PAGE 0x05 +// #define HID_USAGE_PAGE_EXT 0x06 + +#define HID_USAGE 0x08 +// #define HID_USAGE 0x09 +// #define HID_USAGE_EXT 0x0a + +#define HID_USAGE_MIN 0x18 +// #define HID_USAGE_MIN 0x19 +#define HID_USAGE_MAX 0x28 +// #define HID_USAGE_MAX 0x29 + +#define HID_DESIGNATOR_INDEX 0x38 +#define HID_DESIGNATOR_MIN 0x48 +#define HID_DESIGNATOR_MAX 0x58 + +#define HID_STRING_INDEX 0x78 +#define HID_STRING_MIN 0x88 +#define HID_STRING_MAX 0x98 + +#define HID_DELIMITER 0xA8 + +#define HID_LOGICAL_MIN 0x14 +// #define HID_LOGICAL_MIN 0x15 +// #define HID_LOGICAL_MIN_2 0x16 +#define HID_LOGICAL_MAX 0x24 +// #define HID_LOGICAL_MAX 0x25 +// #define HID_LOGICAL_MAX_2 0x26 + +#define HID_PHYSICAL_MIN 0x34 +// #define HID_PHYSICAL_MIN 0x35 +// #define HID_PHYSICAL_MIN_2 0x36 +// #define HID_PHYSICAL_MIN_3 0x37 +#define HID_PHYSICAL_MAX 0x44 +// #define HID_PHYSICAL_MAX 0x45 +// #define HID_PHYSICAL_MAX_2 0x46 + +#define HID_UNIT_EXPONENT 0x54 +// #define HID_UNIT 0x55 +#define HID_UNIT 0x64 +// #define HID_UNIT 0x65 + +#define HID_REPORT_SIZE 0x74 +// #define HID_REPORT_SIZE 0x75 +#define HID_REPORT_ID 0x84 + +#define HID_REPORT_COUNT 0x94 +// #define HID_REPORT_COUNT 0x95 + +#define HID_PUSH 0xA4 +#define HID_POP 0xB4 + +#define HID_RESERVED 0xC4 // above this it is all reserved + + +// HID Report Usage Pages from HID Usage Tables 1.12 Section 3, Table 1 +#define HID_USAGE_PAGE_GENERICDESKTOP 0x01 +#define HID_USAGE_PAGE_KEY_CODES 0x07 +#define HID_USAGE_PAGE_LEDS 0x08 +#define HID_USAGE_PAGE_BUTTONS 0x09 + +// HID Report Usages from HID Usage Tables 1.12 Section 4, Table 6 +#define HID_USAGE_POINTER 0x01 +#define HID_USAGE_MOUSE 0x02 +#define HID_USAGE_JOYSTICK 0x04 +#define HID_USAGE_KEYBOARD 0x06 +#define HID_USAGE_X 0x30 +#define HID_USAGE_Y 0x31 +#define HID_USAGE_Z 0x32 +#define HID_USAGE_RX 0x33 +#define HID_USAGE_RY 0x34 +#define HID_USAGE_RZ 0x35 +#define HID_USAGE_SLIDER 0x36 +#define HID_USAGE_DIAL 0x37 +#define HID_USAGE_WHEEL 0x38 + + +// HID Report Collection Types from HID 1.12 6.2.2.6 +#define HID_COLLECTION_PHYSICAL 0 +#define HID_COLLECTION_APPLICATION 1 + +// HID Input/Output/Feature Item Data (attributes) from HID 1.11 6.2.2.5 +/// more like flags +#define HID_ITEM_CONSTANT 0x1 +#define HID_ITEM_VARIABLE 0x2 +#define HID_ITEM_RELATIVE 0x4 +#define HID_ITEM_WRAP 0x8 +#define HID_ITEM_LINEAR 0x10 +#define HID_ITEM_PREFERRED 0x20 +#define HID_ITEM_NULL 0x40 +#define HID_ITEM_BITFIELD 0x80 + +// Report Types from HID 1.11 Section 7.2.1 +#define HID_REPORT_TYPE_INPUT 1 +#define HID_REPORT_TYPE_OUTPUT 2 +#define HID_REPORT_TYPE_FEATURE 3 + +struct hid_device_descriptor { + int num_elements; +// int usage_page; +// int usage; + /** Pointer to the first element */ + struct hid_device_element *first; +}; + +struct hid_device_element { + int index; + + int type; // button/axis + int vartype; // abs/relative + int usage_page; // usage page + int usage; // some kind of index (as from descriptor) + + int logical_min; + int logical_max; + + int phys_min; + int phys_max; + + int resolution; // in bits + + int value; + + /** Pointer to the next element */ + struct hid_device_element *next; +}; + +struct hid_device_descriptor *descriptor; + +#define BITMASK1(n) ((1ULL << (n)) - 1ULL) + +int main(int argc, char* argv[]) +{ + int res; + unsigned char buf[256]; + unsigned char descr_buf[MAX_DESCRIPTOR]; + #define MAX_STR 255 + wchar_t wstr[MAX_STR]; + hid_device *handle; + int i; + + descriptor = (struct hid_device_descriptor *) malloc( sizeof( struct hid_device_descriptor) ); + descriptor->num_elements = 0; + +#ifdef WIN32 + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); +#endif + + struct hid_device_info *devs, *cur_dev; + + if (hid_init()) + return -1; + + devs = hid_enumerate(0x0, 0x0); + cur_dev = devs; + printf( "curdev %ls\n", cur_dev ); + while (cur_dev) { + printf("Device Found\n (vendor,product): %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number); + printf("\n"); + printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string); + printf(" Product: %ls\n", cur_dev->product_string); + printf(" Release: %hx\n", cur_dev->release_number); + printf(" Interface: %d\n", cur_dev->interface_number); + printf("\n"); + cur_dev = cur_dev->next; + } + hid_free_enumeration(devs); + + // Set up the command buffer. + memset(buf,0x00,sizeof(buf)); + buf[0] = 0x01; + buf[1] = 0x81; + + + // Open the device using the VID, PID, + // and optionally the Serial number. + ////handle = hid_open(0x4d8, 0x3f, L"12345"); +// handle = hid_open(0x4d8, 0x3f, NULL); + // mouse: +// handle = hid_open(0x1241, 0x1166, NULL); + // run'n'drive +// handle = hid_open(0x044f, 0xd003, NULL); + // impakt + handle = hid_open(0x07b5, 0x0312, NULL); + if (!handle) { + printf("unable to open device\n"); + return 1; + } + + // Read the Manufacturer String + wstr[0] = 0x0000; + res = hid_get_manufacturer_string(handle, wstr, MAX_STR); + if (res < 0) + printf("Unable to read manufacturer string\n"); + printf("Manufacturer String: %ls\n", wstr); + + // Read the Product String + wstr[0] = 0x0000; + res = hid_get_product_string(handle, wstr, MAX_STR); + if (res < 0) + printf("Unable to read product string\n"); + printf("Product String: %ls\n", wstr); + + // Read the Serial Number String + wstr[0] = 0x0000; + res = hid_get_serial_number_string(handle, wstr, MAX_STR); + if (res < 0) + printf("Unable to read serial number string\n"); + printf("Serial Number String: (%d) %ls", wstr[0], wstr); + printf("\n"); + + // Read Indexed String 1 + wstr[0] = 0x0000; + res = hid_get_indexed_string(handle, 1, wstr, MAX_STR); + if (res < 0) + printf("Unable to read indexed string 1\n"); + printf("Indexed String 1: %ls\n", wstr); + + + // Set the hid_read() function to be non-blocking. + hid_set_nonblocking(handle, 1); + +// // Try to read from the device. There shoud be no +// // data here, but execution should not block. + res = hid_read(handle, buf, 17); + + printf( "res of read %i\n", res ); + + hid_close(handle); + + /* Free static HIDAPI objects. */ + hid_exit(); + +#ifdef WIN32 + system("pause"); +#endif + + return 0; +} diff --git a/windows/hid.c b/windows/hid.c index 0671f128..b9de43cc 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -94,6 +94,111 @@ extern "C" { USHORT fields_not_used_by_hidapi[10]; } HIDP_CAPS, *PHIDP_CAPS; typedef void* PHIDP_PREPARSED_DATA; + + typedef enum _HIDP_REPORT_TYPE { + HidP_Input, + HidP_Output, + HidP_Feature + } HIDP_REPORT_TYPE; + +typedef struct _HIDP_BUTTON_CAPS { + USAGE UsagePage; + UCHAR ReportID; + BOOLEAN IsAlias; + USHORT BitField; + USHORT LinkCollection; + USAGE LinkUsage; + USAGE LinkUsagePage; + BOOLEAN IsRange; + BOOLEAN IsStringRange; + BOOLEAN IsDesignatorRange; + BOOLEAN IsAbsolute; + ULONG Reserved[10]; + 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; + }; +} HIDP_BUTTON_CAPS, *PHIDP_BUTTON_CAPS; + + +typedef struct _HIDP_VALUE_CAPS { + USAGE UsagePage; + UCHAR ReportID; + BOOLEAN IsAlias; + USHORT BitField; + USHORT LinkCollection; + USAGE LinkUsage; + USAGE LinkUsagePage; + BOOLEAN IsRange; + BOOLEAN IsStringRange; + BOOLEAN IsDesignatorRange; + BOOLEAN IsAbsolute; + BOOLEAN HasNull; + UCHAR Reserved; + USHORT BitSize; + USHORT ReportCount; + USHORT Reserved2[5]; + ULONG UnitsExp; + ULONG Units; + LONG LogicalMin; + LONG LogicalMax; + LONG PhysicalMin; + LONG PhysicalMax; + 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; + }; +} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; + +typedef struct _HIDP_LINK_COLLECTION_NODE { + USAGE LinkUsage; + USAGE LinkUsagePage; + USHORT Parent; + USHORT NumberOfChildren; + USHORT NextSibling; + USHORT FirstChild; + ULONG CollectionType :8; + ULONG IsAlias :1; + ULONG Reserved :23; + PVOID UserContext; +} HIDP_LINK_COLLECTION_NODE, *PHIDP_LINK_COLLECTION_NODE; + #define HIDP_STATUS_SUCCESS 0x110000 typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); @@ -108,6 +213,10 @@ extern "C" { typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); + typedef NTSTATUS (__stdcall *HidP_GetLinkCollectionNodes_)( PHIDP_LINK_COLLECTION_NODE link_collection_nodes, PULONG link_collection_nodes_length, PHIDP_PREPARSED_DATA preparsed_data); + typedef NTSTATUS (__stdcall *HidP_GetButtonCaps_)( HIDP_REPORT_TYPE report_type, PHIDP_BUTTON_CAPS button_caps, PUSHORT button_caps_length, PHIDP_PREPARSED_DATA preparsed_data ); + typedef NTSTATUS (__stdcall *HidP_GetValueCaps_)( HIDP_REPORT_TYPE report_type, PHIDP_VALUE_CAPS value_caps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA preparsed_data ); + static HidD_GetAttributes_ HidD_GetAttributes; static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; static HidD_GetManufacturerString_ HidD_GetManufacturerString; @@ -120,6 +229,10 @@ extern "C" { static HidP_GetCaps_ HidP_GetCaps; static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; + static HidP_GetLinkCollectionNodes_ HidP_GetLinkCollectionNodes; + static HidP_GetButtonCaps_ HidP_GetButtonCaps; + static HidP_GetValueCaps_ HidP_GetValueCaps; + static HMODULE lib_handle = NULL; static BOOLEAN initialized = FALSE; #endif /* HIDAPI_USE_DDK */ @@ -209,6 +322,10 @@ static int lookup_functions() RESOLVE(HidD_FreePreparsedData); RESOLVE(HidP_GetCaps); RESOLVE(HidD_SetNumInputBuffers); + + RESOLVE(HidP_GetLinkCollectionNodes); + RESOLVE(HidP_GetButtonCaps); + RESOLVE(HidP_GetValueCaps); #undef RESOLVE } else From 0fffed10033312bf3eca4c4e62500a92b2b76926 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Mon, 9 May 2016 14:34:35 +0100 Subject: [PATCH 03/29] win: initial state that compiles No new features --- hidapi_parser/hidapi_parser.c | 36 ++++++++++++++++++++++++++++------- hidapi_parser/hidapi_parser.h | 2 +- windows/hid.c | 13 ++++++++----- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index d6043efd..e9ff4236 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -27,7 +27,10 @@ #include #include +#include #include "hidapi_parser.h" +#include + // SET IN CMAKE // #define DEBUG_PARSER @@ -1241,6 +1244,7 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d void hid_parse_element_info( struct hid_dev_desc * devdesc ){ hid_device * dev = devdesc->device; + struct hid_device_info *dev_info = devdesc->info; struct hid_device_collection * device_collection = hid_new_collection(); devdesc->device_collection = device_collection; @@ -1262,8 +1266,22 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ int numColls = 0; int nt_res, nt_res2; + PHIDP_PREPARSED_DATA pp_data = NULL; + HIDP_CAPS caps; + + /* Open a handle to the device */ + HANDLE dev_handle = CreateFileA(dev_info->path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + + /* Check validity of write_handle. */ + if (dev_handle == INVALID_HANDLE_VALUE) { + /* Unable to open the device. */ + //register_error(dev, "CreateFile"); + // TODO: not sure what to do here + return; + } + /* Get the Usage Page and Usage for this device. */ - res = HidD_GetPreparsedData(write_handle, &pp_data); + BOOLEAN res = HidD_GetPreparsedData(dev_handle, &pp_data); if (res) { nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { @@ -1271,7 +1289,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ device_collection->num_collections = numColls; device_collection->usage_page = caps.UsagePage; - device_collection->usage = caps.Usage; + device_collection->usage_index = caps.Usage; device_collection->index = 0; // type @@ -1292,23 +1310,27 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ caps.NumberFeatureButtonCaps + caps.NumberFeatureValueCaps; - PHIDP_LINK_COLLECTION_NODE linkCollectionNodes[ numColls ]; + PHIDP_LINK_COLLECTION_NODE *linkCollectionNodes; + linkCollectionNodes = malloc(numColls * sizeof(HIDP_LINK_COLLECTION_NODE)); nt_res2 = HidP_GetLinkCollectionNodes( linkCollectionNodes, numColls, pp_data ); if (nt_res2 == HIDP_STATUS_SUCCESS) { // then I have the linkCollectionNodes } // input int numValueCaps = caps.NumberInputValueCaps; - PHIDP_VALUE_CAPS pInputValueCaps[ numValueCaps ]; + PHIDP_VALUE_CAPS *pInputValueCaps; + pInputValueCaps = malloc(numValueCaps * sizeof(HIDP_VALUE_CAPS)); nt_res2 = HidP_GetValueCaps( HidP_Input, pInputValueCaps, numValueCaps, pp_data ); // output // feature - } + free(linkCollectionNodes); + free(pInputValueCaps); + } HidD_FreePreparsedData(pp_data); + CloseHandle(dev_handle); + } - - } #endif diff --git a/hidapi_parser/hidapi_parser.h b/hidapi_parser/hidapi_parser.h index 4756ea3e..73103d81 100644 --- a/hidapi_parser/hidapi_parser.h +++ b/hidapi_parser/hidapi_parser.h @@ -32,7 +32,7 @@ extern "C" { #endif -#include +#include "hidapi.h" struct hid_device_element; struct hid_device_collection; diff --git a/windows/hid.c b/windows/hid.c index b9de43cc..fc2a7d9e 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -21,6 +21,8 @@ ********************************************************/ #include +#include + #ifndef _NTDEF_ typedef LONG NTSTATUS; @@ -71,7 +73,7 @@ extern "C" { extern "C" { #endif -#ifndef HIDAPI_USE_DDK +#if 0 /* Since we're not building with the DDK, and the HID header files aren't part of the SDK, we have to define all this stuff here. In lookup_functions(), the function pointers @@ -305,7 +307,7 @@ static void register_error(hid_device *device, const char *op) device->last_error_str = msg; } -#ifndef HIDAPI_USE_DDK +#if 0 HIDAPI_USE_DDK static int lookup_functions() { lib_handle = LoadLibraryA("hid.dll"); @@ -356,7 +358,7 @@ static HANDLE open_device(const char *path, BOOL enumerate) int HID_API_EXPORT hid_init(void) { -#ifndef HIDAPI_USE_DDK +#if 0 HIDAPI_USE_DDK if (!initialized) { if (lookup_functions() < 0) { hid_exit(); @@ -370,7 +372,7 @@ int HID_API_EXPORT hid_init(void) int HID_API_EXPORT hid_exit(void) { -#ifndef HIDAPI_USE_DDK +#if 0 HIDAPI_USE_DDK if (lib_handle) FreeLibrary(lib_handle); lib_handle = NULL; @@ -386,7 +388,8 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor struct hid_device_info *cur_dev = NULL; /* Windows objects for interacting with the driver. */ - GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; + GUID InterfaceClassGuid; + HidD_GetHidGuid(&InterfaceClassGuid); SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; From 3b30c96d4bb106f13fbdb694820e4028c8c90747 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Wed, 11 May 2016 23:29:10 +0100 Subject: [PATCH 04/29] win: collection parsing started --- hidapi/hidapi.h | 3 + hidapi_parser/hidapi_parser.c | 325 ++++++++++++++++++++++++++++------ windows/hid.c | 5 + 3 files changed, 281 insertions(+), 52 deletions(-) diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index 950cc64f..f6d6663d 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -429,6 +429,9 @@ extern "C" { int HID_API_EXPORT HID_API_CALL hid_dump_element_info(hid_device *dev); IOHIDDeviceRef HID_API_EXPORT HID_API_CALL get_device_handle( hid_device *dev ); #endif +#ifdef WIN32 + HANDLE HID_API_EXPORT HID_API_CALL get_device_handle(hid_device *dev); +#endif #ifdef __cplusplus } diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index e9ff4236..6d85fda2 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -28,8 +28,9 @@ #include #include -#include "hidapi_parser.h" #include +#include "hidapi_parser.h" + // SET IN CMAKE @@ -1235,17 +1236,157 @@ void hid_element_set_output_value( struct hid_dev_desc * devdesc, struct hid_dev #ifdef WIN32 + +void debug_element(struct hid_device_element *element) +{ + printf("index: %d\n", element->index); + printf("parent_collection: %p\n", element->parent_collection); + printf("io_type: %d\n", element->io_type); + printf("usage_page: %d\n", element->usage_page); + printf("usage_min: %d\n", element->usage_min); + printf("usage_max: %d\n", element->usage_max); + printf("usage: %d\n", element->usage); + printf("type: %d\n", element->type); + printf("isarray: %d\n", element->isarray); + printf("isrelative: %d\n", element->isrelative); + printf("isvariable: %d\n", element->isvariable); + printf("logical_min: %d\n", element->logical_min); + printf("logical_max: %d\n", element->logical_max); + printf("phys_min: %d\n", element->phys_min); + printf("phys_max: %d\n", element->phys_max); + printf("unit: %d\n", element->unit); + printf("unit_exponent: %d\n", element->unit_exponent); + printf("report_id: %d\n", element->report_id); + printf("report_size: %d\n", element->report_size); + printf("report_index: %d\n", element->report_index); + fflush(stdout); +} + +void debug_collection(struct hid_device_collection *collection, int col_index) +{ + printf("COLLECTION[%d] @%p:\n", col_index, collection); + printf("index: %d\n", collection->index); + printf("type: %d\n", collection->type); + printf("usage_page: %d\n", collection->usage_page); + printf("usage_index: %d\n", collection->usage_index); + printf("parent: %p\n", collection->parent_collection); + printf("children: %d\n", collection->num_collections); + if (collection->num_collections > 0) + printf("first_collection: %p\n", collection->first_collection); + if (collection->next_collection) + printf("next_collection: %p\n", collection->next_collection); + fflush(stdout); +} + + + +static int hid_parse_caps(struct hid_device_element **elements, int *elements_array_index, struct hid_device_collection **collections, struct hid_device_collection *device_collection, + const PHIDP_PREPARSED_DATA pp_data, const PHIDP_CAPS caps, int report_type, BOOL is_button, int *index) +{ + USHORT numCaps; + enum _HIDP_REPORT_TYPE api_report_type; + + if (is_button){ + switch (report_type){ + case HID_REPORT_TYPE_INPUT: numCaps = caps->NumberInputButtonCaps; api_report_type = HidP_Input; break; + case HID_REPORT_TYPE_OUTPUT: numCaps = caps->NumberOutputButtonCaps; api_report_type = HidP_Output; break; + case HID_REPORT_TYPE_FEATURE: numCaps = caps->NumberFeatureButtonCaps; api_report_type = HidP_Feature; break; + } + PHIDP_BUTTON_CAPS pButtonCaps; + pButtonCaps = malloc(numCaps * sizeof(HIDP_BUTTON_CAPS)); + if (HidP_GetButtonCaps(api_report_type, pButtonCaps, &numCaps, pp_data) != HIDP_STATUS_SUCCESS){ + free(pButtonCaps); + return -1; + } + for (int i = 0; i < numCaps; i++, (*elements_array_index)++){ + PHIDP_BUTTON_CAPS pCaps = &pButtonCaps[i]; + elements[*elements_array_index]->parent_collection = collections[pCaps->LinkCollection]; + if (!collections[pCaps->LinkCollection]->first_element){ + collections[pCaps->LinkCollection]->first_element = elements[*elements_array_index]; + }elements[*elements_array_index]->io_type = report_type; + elements[*elements_array_index]->index = (*index)++; + elements[*elements_array_index]->usage_page = pCaps->UsagePage; + if (pCaps->IsRange){ + elements[*elements_array_index]->usage_min = pCaps->Range.UsageMin; + elements[*elements_array_index]->usage_max = pCaps->Range.UsageMax; + } + else{ + elements[*elements_array_index]->usage = pCaps->NotRange.Usage; + } + USHORT bitField = pCaps->BitField; + elements[*elements_array_index]->type = bitField & 0xf; + elements[*elements_array_index]->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); + elements[*elements_array_index]->isrelative = pCaps->IsAbsolute ? 0 : 1; + elements[*elements_array_index]->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); + elements[*elements_array_index]->report_id = pCaps->ReportID; + elements[*elements_array_index]->report_size = 0; // TODO: not sure about this one. The API does not seem to provide this + elements[*elements_array_index]->report_index = 0; // TODO: not sure about this one. The API does not seem to provide this + debug_element(elements[*elements_array_index]); + } + free(pButtonCaps); + + } + else { + switch (report_type){ + case HID_REPORT_TYPE_INPUT: numCaps = caps->NumberInputValueCaps; api_report_type = HidP_Input; break; + case HID_REPORT_TYPE_OUTPUT: numCaps = caps->NumberOutputValueCaps; api_report_type = HidP_Output; break; + case HID_REPORT_TYPE_FEATURE: numCaps = caps->NumberFeatureValueCaps; api_report_type = HidP_Feature; break; + } + PHIDP_VALUE_CAPS pValueCaps; + pValueCaps = malloc(numCaps * sizeof(HIDP_VALUE_CAPS)); + if (HidP_GetValueCaps(api_report_type, pValueCaps, &numCaps, pp_data) != HIDP_STATUS_SUCCESS){ + free(pValueCaps); + return -1; + } + for (int i = 0; i < numCaps; i++, *(elements_array_index)++){ + PHIDP_VALUE_CAPS pCaps = &pValueCaps[i]; + elements[*elements_array_index]->parent_collection = collections[pCaps->LinkCollection]; + if (!collections[pCaps->LinkCollection]->first_element){ + collections[pCaps->LinkCollection]->first_element = elements[*elements_array_index]; + } + elements[*elements_array_index]->io_type = HID_REPORT_TYPE_INPUT; + elements[*elements_array_index]->index = (*index)++; + elements[*elements_array_index]->usage_page = pCaps->UsagePage; + if (pCaps->IsRange){ + elements[*elements_array_index]->usage_min = pCaps->Range.UsageMin; + elements[*elements_array_index]->usage_max = pCaps->Range.UsageMax; + } + else{ + elements[*elements_array_index]->usage = pCaps->NotRange.Usage; + } + USHORT bitField = pCaps->BitField; + elements[*elements_array_index]->type = bitField & 0xf; + elements[*elements_array_index]->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); + elements[*elements_array_index]->isrelative = pCaps->IsAbsolute ? 0 : 1; + elements[*elements_array_index]->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); + elements[*elements_array_index]->logical_min = pCaps->LogicalMin; + elements[*elements_array_index]->logical_max = pCaps->LogicalMax; + elements[*elements_array_index]->phys_min = pCaps->PhysicalMin; + elements[*elements_array_index]->phys_max = pCaps->PhysicalMax; + elements[*elements_array_index]->unit = pCaps->Units; + elements[*elements_array_index]->unit_exponent = pCaps->UnitsExp; + elements[*elements_array_index]->report_id = pCaps->ReportID; + elements[*elements_array_index]->report_size = pCaps->BitSize; + elements[*elements_array_index]->report_index = pCaps->ReportCount; + debug_element(elements[*elements_array_index]); + } + free(pValueCaps); + } +} + + + int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_element * element ){ } int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * devdesc ){ - + // TO see how to handle HID Reports + //See https ://msdn.microsoft.com/en-us/library/windows/hardware/ff538783(v=vs.85).aspx } void hid_parse_element_info( struct hid_dev_desc * devdesc ){ hid_device * dev = devdesc->device; - struct hid_device_info *dev_info = devdesc->info; - + struct hid_device_collection * device_collection = hid_new_collection(); devdesc->device_collection = device_collection; @@ -1262,15 +1403,17 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ report_ids[0] = 0; report_lengths[0] = 0; + // To keep track of indices + int new_index = 0; int numColls = 0; - int nt_res, nt_res2; + NTSTATUS nt_res; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; /* Open a handle to the device */ - HANDLE dev_handle = CreateFileA(dev_info->path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + HANDLE dev_handle = get_device_handle(dev); /* Check validity of write_handle. */ if (dev_handle == INVALID_HANDLE_VALUE) { @@ -1282,55 +1425,133 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ /* Get the Usage Page and Usage for this device. */ BOOLEAN res = HidD_GetPreparsedData(dev_handle, &pp_data); - if (res) { - nt_res = HidP_GetCaps(pp_data, &caps); - if (nt_res == HIDP_STATUS_SUCCESS) { - numColls = caps.NumberLinkCollectionNodes; - - device_collection->num_collections = numColls; - device_collection->usage_page = caps.UsagePage; - device_collection->usage_index = caps.Usage; - - device_collection->index = 0; - // type - // num_elements - // usage_min , usage_max - // parent_collection - // next_collection - // first_collection - // first_element - - // num_elements: - // NumberInputButtonCaps + NumberInputValueCaps + - // NumberOutputButtonCaps + NumberOutputValueCaps + - // NumberFeatureButtonCaps + NumberFeatureValueCaps - device_collection->num_elements = - caps.NumberInputButtonCaps + caps.NumberInputValueCaps + - caps.NumberOutputButtonCaps + caps.NumberOutputValueCaps + - caps.NumberFeatureButtonCaps + caps.NumberFeatureValueCaps; - - - PHIDP_LINK_COLLECTION_NODE *linkCollectionNodes; - linkCollectionNodes = malloc(numColls * sizeof(HIDP_LINK_COLLECTION_NODE)); - nt_res2 = HidP_GetLinkCollectionNodes( linkCollectionNodes, numColls, pp_data ); - if (nt_res2 == HIDP_STATUS_SUCCESS) { - // then I have the linkCollectionNodes + if (!res){ + // TODO: what should we do here? + return; + } + + nt_res = HidP_GetCaps(pp_data, &caps); + if (nt_res != HIDP_STATUS_SUCCESS) { + // TODO: what should we do here + return; + } + numColls = caps.NumberLinkCollectionNodes; + + device_collection->num_collections = numColls; + device_collection->usage_page = caps.UsagePage; + device_collection->usage_index = caps.Usage; + + device_collection->index = new_index++; + device_collection->num_elements = + caps.NumberInputButtonCaps + caps.NumberInputValueCaps + + caps.NumberOutputButtonCaps + caps.NumberOutputValueCaps + + caps.NumberFeatureButtonCaps + caps.NumberFeatureValueCaps; + + PHIDP_LINK_COLLECTION_NODE linkCollectionNodes; + linkCollectionNodes = malloc(numColls * sizeof(HIDP_LINK_COLLECTION_NODE)); + struct hid_device_collection **collections = malloc(numColls * sizeof(struct hid_device_collection *)); + nt_res = HidP_GetLinkCollectionNodes( linkCollectionNodes, &numColls, pp_data ); + if (nt_res != HIDP_STATUS_SUCCESS){ + // TODO: what to do here? + return; + } + + // Create the N collections, and put them in an array, so that we can efficiently construct the pointers to each other using the Windows API + for (int i = 0; i < numColls; i++){ + collections[i] = hid_new_collection(); + } + + // And now fill the data and create the collection links + for (int i = 0; i < numColls; i++){ + PHIDP_LINK_COLLECTION_NODE p_collection = &linkCollectionNodes[i]; + // Documentation says that if parent is 0, then there is no parent, but then how do you indicate that the parent is at index 0??? + // I think that is wrong, and 0 indicates that the parent is the collection at index + // I will assume that the collection at index 0 is always the outermost one + if (i == 0){ + device_collection->first_collection = collections[i]; + collections[i]->parent_collection = device_collection; + } + else{ + collections[i]->parent_collection = collections[p_collection->Parent]; + } + if (p_collection->NextSibling) + collections[i]->next_collection = collections[p_collection->NextSibling]; + + if (p_collection->FirstChild) + collections[i]->first_collection = collections[p_collection->FirstChild]; + + collections[i]->num_collections = p_collection->NumberOfChildren; + // TODO set pointer to first element + collections[i]->type = p_collection->CollectionType; + collections[i]->usage_page = p_collection->LinkUsagePage; + collections[i]->usage_index = p_collection->LinkUsage; + collections[i]->index = new_index++; // TODO not sure about this one + debug_collection(collections[i], i); + } + debug_collection(device_collection, 100); + + /* And create all the element structures with pointers, so that we can create the links. We create the links at the beginning for convenience */ + struct hid_device_element **elements = malloc(device_collection->num_elements * sizeof(struct hid_device_element *)); + for (int i = 0; i < device_collection->num_elements; i++){ + elements[i] = hid_new_element(); + } + for (int i = 0; i < device_collection->num_elements - 1; i++){ + elements[i]->next = elements[i + 1]; + } + + device_collection->first_element = elements[0]; + + /* Now parse the (input, output, feature) x (button, values) capabilities */ + int index_element = 0; + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, FALSE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, FALSE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, TRUE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, TRUE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, TRUE, &new_index); + + /* Reports */ + // Pehaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports + for (int i = 0; i < index_element; i++){ + int report_id = elements[i]->report_id; + int report_size = elements[i]->report_size; + int report_count = elements[i]->report_index; + + int reportexists = 0; + for (int j = 0; j < numreports; j++){ + reportexists = (report_ids[j] == report_id); + } + if (!reportexists){ + report_ids[numreports] = report_id; + report_lengths[numreports] = 0; + numreports++; + } + int k = 0; + int index = 0; + for (k = 0; knumber_of_reports = numreports; + devdesc->report_lengths = (int*)malloc(sizeof(int) * numreports); + devdesc->report_ids = (int*)malloc(sizeof(int) * numreports); + for (int j = 0; jreport_lengths[j] = report_lengths[j]; + devdesc->report_ids[j] = report_ids[j]; } + + /* And clean up the temp structures */ + free(elements); + free(collections); + free(linkCollectionNodes); + HidD_FreePreparsedData(pp_data); + CloseHandle(dev_handle); + } #endif diff --git a/windows/hid.c b/windows/hid.c index fc2a7d9e..16b0fc11 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -999,6 +999,11 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) return (wchar_t*)dev->last_error_str; } +HANDLE HID_API_EXPORT get_device_handle(hid_device *dev){ + return dev->device_handle; +} + + /*#define PICPGM*/ /*#define S11*/ From b317698f9c39ec8daf2d8cd883b0df2faf36c41b Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Thu, 12 May 2016 22:29:34 +0100 Subject: [PATCH 05/29] win: element parsing --- hidapi_parser/hidapi_parser.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 6d85fda2..0f2d3832 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -1259,6 +1259,7 @@ void debug_element(struct hid_device_element *element) printf("report_id: %d\n", element->report_id); printf("report_size: %d\n", element->report_size); printf("report_index: %d\n", element->report_index); + printf("\n\n"); fflush(stdout); } @@ -1275,6 +1276,8 @@ void debug_collection(struct hid_device_collection *collection, int col_index) printf("first_collection: %p\n", collection->first_collection); if (collection->next_collection) printf("next_collection: %p\n", collection->next_collection); + + printf("\n\n"); fflush(stdout); } @@ -1319,8 +1322,8 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar elements[*elements_array_index]->isrelative = pCaps->IsAbsolute ? 0 : 1; elements[*elements_array_index]->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); elements[*elements_array_index]->report_id = pCaps->ReportID; - elements[*elements_array_index]->report_size = 0; // TODO: not sure about this one. The API does not seem to provide this - elements[*elements_array_index]->report_index = 0; // TODO: not sure about this one. The API does not seem to provide this + elements[*elements_array_index]->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to usage_max - usage_min + 1 (1 bit per usage)? + elements[*elements_array_index]->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1? debug_element(elements[*elements_array_index]); } free(pButtonCaps); @@ -1338,7 +1341,7 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar free(pValueCaps); return -1; } - for (int i = 0; i < numCaps; i++, *(elements_array_index)++){ + for (int i = 0; i < numCaps; i++, (*elements_array_index)++){ PHIDP_VALUE_CAPS pCaps = &pValueCaps[i]; elements[*elements_array_index]->parent_collection = collections[pCaps->LinkCollection]; if (!collections[pCaps->LinkCollection]->first_element){ @@ -1372,6 +1375,7 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar } free(pValueCaps); } + return 0; } @@ -1504,10 +1508,10 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ /* Now parse the (input, output, feature) x (button, values) capabilities */ int index_element = 0; hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, FALSE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, FALSE, &new_index); hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, TRUE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index); hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, TRUE, &new_index); + hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, FALSE, &new_index); hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, TRUE, &new_index); /* Reports */ @@ -1515,7 +1519,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ for (int i = 0; i < index_element; i++){ int report_id = elements[i]->report_id; int report_size = elements[i]->report_size; - int report_count = elements[i]->report_index; + int report_count = elements[i]->report_index; // TODO: report_count is not used???? int reportexists = 0; for (int j = 0; j < numreports; j++){ From b4578eb306848ef53416fcd2dd297a8360e336ca Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Fri, 13 May 2016 11:09:05 +0100 Subject: [PATCH 06/29] win: initial version of element value getting Not tested yet --- hidapi_parser/hidapi_parser.c | 82 +++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 0f2d3832..a11cf185 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -1381,11 +1381,87 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_element * element ){ - + return 0; } int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * devdesc ){ // TO see how to handle HID Reports //See https ://msdn.microsoft.com/en-us/library/windows/hardware/ff538783(v=vs.85).aspx + // If there is only one report, there will be no report ID in the report. Otherwise, it is the first byte + int report_id = 0; + int report_length = 0; + struct hid_device_collection * device_collection = devdesc->device_collection; + struct hid_device_element * cur_element = device_collection->first_element; + NTSTATUS res; + + if (devdesc->number_of_reports != 1){ + report_id = buf[0]; + } + + // Look for the size of the report (in bits), and convert to bytes (rounding up) + for (int i = 0; i < devdesc->number_of_reports; i++){ + if (devdesc->report_ids[i] == report_id){ + report_length = ((devdesc->report_lengths[i] - 1) / 8) + 1; + } + } + if (report_length == 0){ + // This should not happen, the report was not found + return -1; + } + + if (cur_element->io_type != HID_REPORT_TYPE_INPUT){ + cur_element = hid_get_next_input_element(cur_element); + } + printf("cur_element %p\n", cur_element ); + + // The Windows API has a function to get the data of all the buttons that are on, and another to get the value data by component page and usage + // We get all the buttons that are on + // TODO: perhaps we could put the preparsed data in the devdesc structure (only for Windows) + HANDLE dev_handle = get_device_handle(devdesc->device); + PHIDP_PREPARSED_DATA pp_data = NULL; + if (HidD_GetPreparsedData(dev_handle, &pp_data) != HIDP_STATUS_SUCCESS){ + return -1; + } + long max_usage_and_page_length = HidP_MaxUsageListLength(HidP_Input, 0, pp_data); + PUSAGE_AND_PAGE usage_and_page_list = malloc(max_usage_and_page_length * sizeof(USAGE_AND_PAGE));; + + if (HidP_GetButtonsEx(HidP_Input, 0, usage_and_page_list, &max_usage_and_page_length, pp_data, buf, report_length) != HIDP_STATUS_SUCCESS){ + free(usage_and_page_list); + return -1; + } + + while (cur_element != NULL){ + // Check that the element is part of this report + if (cur_element->report_id != report_id){ + cur_element = hid_get_next_input_element(cur_element); + continue; + } + + if (devdesc->_element_callback != NULL){ + // First see if it is a Value element (not a button), trying to get its value + // TODO may need to use HidP_GetUsageValueArray, if element->report_index > 1 + unsigned long new_value; + res = HidP_GetUsageValue(HidP_Input, cur_element->usage_page, 0, cur_element->usage, &new_value, pp_data, buf, report_length); + if (res == HIDP_STATUS_USAGE_NOT_FOUND){ + // Then see if we can find the element's page and usage in the buttons that are set to on, if not, it is implicitly 0 + new_value = 0; + for (int i = 0; i < max_usage_and_page_length; i++){ + if (usage_and_page_list[i].UsagePage = cur_element->usage_page && usage_and_page_list[i].Usage == cur_element->usage){ + new_value = 1; + } + } + } + // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef ); + if (new_value != cur_element->rawvalue || cur_element->repeat){ + printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); + hid_element_set_value_from_input(cur_element, new_value); + devdesc->_element_callback(cur_element, devdesc->_element_data); + } + } + cur_element = hid_get_next_input_element(cur_element); + } + free(usage_and_page_list); + + return 0; } void hid_parse_element_info( struct hid_dev_desc * devdesc ){ @@ -1395,8 +1471,6 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ devdesc->device_collection = device_collection; struct hid_device_collection * parent_collection = devdesc->device_collection; - struct hid_device_collection * prev_collection; - struct hid_device_element * prev_element; device_collection->num_collections = 0; device_collection->num_elements = 0; @@ -1518,7 +1592,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ // Pehaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports for (int i = 0; i < index_element; i++){ int report_id = elements[i]->report_id; - int report_size = elements[i]->report_size; + int report_size = elements[i]->report_size; int report_count = elements[i]->report_index; // TODO: report_count is not used???? int reportexists = 0; From 069aded5363b49d64dfa084ebc3012ddd7b065b5 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Mon, 16 May 2016 00:05:44 +0100 Subject: [PATCH 07/29] win: get values seems ok But buttons are not working yet --- hidapi_parser/hidapi_parser.c | 26 +++++++++++---------- windows/hid.c | 44 +++++++++++++++++------------------ 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index a11cf185..7e4cb8a3 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -884,7 +884,7 @@ int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * return hid_parse_input_elements_values( buf, devdesc ); #endif #ifdef WIN32 - return hid_parse_input_elements_values( buf, devdesc ); + return hid_parse_input_elements_values( buf, size, devdesc ); #endif #ifdef LINUX_FREEBSD struct hid_parsing_byte pbyte; @@ -1347,7 +1347,7 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar if (!collections[pCaps->LinkCollection]->first_element){ collections[pCaps->LinkCollection]->first_element = elements[*elements_array_index]; } - elements[*elements_array_index]->io_type = HID_REPORT_TYPE_INPUT; + elements[*elements_array_index]->io_type = report_type; elements[*elements_array_index]->index = (*index)++; elements[*elements_array_index]->usage_page = pCaps->UsagePage; if (pCaps->IsRange){ @@ -1383,7 +1383,7 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_element * element ){ return 0; } -int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * devdesc ){ +int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){ // TO see how to handle HID Reports //See https ://msdn.microsoft.com/en-us/library/windows/hardware/ff538783(v=vs.85).aspx // If there is only one report, there will be no report ID in the report. Otherwise, it is the first byte @@ -1397,10 +1397,11 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d report_id = buf[0]; } + // TODO: perhaps on Windows we do not need to calculate the report size here, and we can just get it from the size parameter that we got from above // Look for the size of the report (in bits), and convert to bytes (rounding up) for (int i = 0; i < devdesc->number_of_reports; i++){ if (devdesc->report_ids[i] == report_id){ - report_length = ((devdesc->report_lengths[i] - 1) / 8) + 1; + report_length = size; } } if (report_length == 0){ @@ -1411,20 +1412,22 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d if (cur_element->io_type != HID_REPORT_TYPE_INPUT){ cur_element = hid_get_next_input_element(cur_element); } - printf("cur_element %p\n", cur_element ); + //printf("cur_element %p\n", cur_element ); // The Windows API has a function to get the data of all the buttons that are on, and another to get the value data by component page and usage // We get all the buttons that are on // TODO: perhaps we could put the preparsed data in the devdesc structure (only for Windows) HANDLE dev_handle = get_device_handle(devdesc->device); - PHIDP_PREPARSED_DATA pp_data = NULL; - if (HidD_GetPreparsedData(dev_handle, &pp_data) != HIDP_STATUS_SUCCESS){ + PHIDP_PREPARSED_DATA pp_data; + if (!HidD_GetPreparsedData(dev_handle, &pp_data)){ return -1; } long max_usage_and_page_length = HidP_MaxUsageListLength(HidP_Input, 0, pp_data); - PUSAGE_AND_PAGE usage_and_page_list = malloc(max_usage_and_page_length * sizeof(USAGE_AND_PAGE));; + PUSAGE_AND_PAGE usage_and_page_list = malloc(max_usage_and_page_length * sizeof(USAGE_AND_PAGE)); + memset(usage_and_page_list, 0, max_usage_and_page_length * sizeof(USAGE_AND_PAGE)); - if (HidP_GetButtonsEx(HidP_Input, 0, usage_and_page_list, &max_usage_and_page_length, pp_data, buf, report_length) != HIDP_STATUS_SUCCESS){ + NTSTATUS ntres = HidP_GetButtonsEx(HidP_Input, 0, usage_and_page_list, &max_usage_and_page_length, pp_data, buf, report_length); + if ( ntres != HIDP_STATUS_SUCCESS){ free(usage_and_page_list); return -1; } @@ -1437,7 +1440,6 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d } if (devdesc->_element_callback != NULL){ - // First see if it is a Value element (not a button), trying to get its value // TODO may need to use HidP_GetUsageValueArray, if element->report_index > 1 unsigned long new_value; res = HidP_GetUsageValue(HidP_Input, cur_element->usage_page, 0, cur_element->usage, &new_value, pp_data, buf, report_length); @@ -1453,6 +1455,7 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef ); if (new_value != cur_element->rawvalue || cur_element->repeat){ printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); + fflush(stdout); hid_element_set_value_from_input(cur_element, new_value); devdesc->_element_callback(cur_element, devdesc->_element_data); } @@ -1581,6 +1584,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ /* Now parse the (input, output, feature) x (button, values) capabilities */ int index_element = 0; + new_index = 0; hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, FALSE, &new_index); hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, TRUE, &new_index); hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index); @@ -1628,8 +1632,6 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ free(collections); free(linkCollectionNodes); HidD_FreePreparsedData(pp_data); - CloseHandle(dev_handle); - } #endif diff --git a/windows/hid.c b/windows/hid.c index 16b0fc11..5efbb0a8 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -249,6 +249,7 @@ struct hid_device_ { BOOL read_pending; char *read_buf; OVERLAPPED ol; + PHIDP_PREPARSED_DATA preparsed_data; }; static hid_device *new_hid_device() @@ -703,6 +704,8 @@ HID_API_EXPORT hid_device* HID_API_CALL hid_open_path(const char *path) register_error(dev, "HidD_GetPreparsedData"); goto err; } + dev->preparsed_data = pp_data; + nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res != HIDP_STATUS_SUCCESS) { register_error(dev, "HidP_GetCaps"); @@ -801,15 +804,16 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char ResetEvent(ev); res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); - if (!res) { - if (GetLastError() != ERROR_IO_PENDING) { - /* ReadFile() has failed. - Clean up and return error. */ - CancelIo(dev->device_handle); - dev->read_pending = FALSE; - goto end_of_function; - } - } + if (!res) { + DWORD er = GetLastError(); + if (GetLastError() != ERROR_IO_PENDING) { + /* ReadFile() has failed. + Clean up and return error. */ + CancelIoEx(dev->device_handle); + dev->read_pending = FALSE; + goto end_of_function; + } + } } if (milliseconds >= 0) { @@ -831,20 +835,9 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char dev->read_pending = FALSE; if (res && bytes_read > 0) { - if (dev->read_buf[0] == 0x0) { - /* If report numbers aren't being used, but Windows sticks a report - number (0x0) on the beginning of the report anyway. To make this - work like the other platforms, and to make it work more like the - HID spec, we'll skip over this byte. */ - bytes_read--; - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf+1, copy_len); - } - else { - /* Copy the whole buffer, report number and all. */ - copy_len = length > bytes_read ? bytes_read : length; - memcpy(data, dev->read_buf, copy_len); - } + /* Copy the whole buffer, report number and all. */ + copy_len = length > bytes_read ? bytes_read : length; + memcpy(data, dev->read_buf, copy_len); } end_of_function: @@ -1003,6 +996,11 @@ HANDLE HID_API_EXPORT get_device_handle(hid_device *dev){ return dev->device_handle; } +PHIDP_PREPARSED_DATA get_preparsed_data(hid_device *dev) +{ + return dev->preparsed_data; +} + /*#define PICPGM*/ From 2c5cf28126a08cdd80b76d86b22d1b3982b23e55 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Mon, 16 May 2016 00:07:22 +0100 Subject: [PATCH 08/29] win: remove preparsed_data experiment --- windows/hid.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/windows/hid.c b/windows/hid.c index 5efbb0a8..43a8491f 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -249,7 +249,6 @@ struct hid_device_ { BOOL read_pending; char *read_buf; OVERLAPPED ol; - PHIDP_PREPARSED_DATA preparsed_data; }; static hid_device *new_hid_device() @@ -704,7 +703,6 @@ HID_API_EXPORT hid_device* HID_API_CALL hid_open_path(const char *path) register_error(dev, "HidD_GetPreparsedData"); goto err; } - dev->preparsed_data = pp_data; nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res != HIDP_STATUS_SUCCESS) { @@ -996,12 +994,6 @@ HANDLE HID_API_EXPORT get_device_handle(hid_device *dev){ return dev->device_handle; } -PHIDP_PREPARSED_DATA get_preparsed_data(hid_device *dev) -{ - return dev->preparsed_data; -} - - /*#define PICPGM*/ /*#define S11*/ From 044981d852364e54e77db8678937fa1a22706f5d Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Thu, 19 May 2016 08:54:59 +0100 Subject: [PATCH 09/29] win: starting to parse buttons correctly but need to change the way the elements are allocated. Instead of allocating everything at the beginning, allocate on the go. --- hidapi_parser/hidapi_parser.c | 62 +++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 7e4cb8a3..4e670ec4 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -1301,21 +1301,15 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar free(pButtonCaps); return -1; } - for (int i = 0; i < numCaps; i++, (*elements_array_index)++){ + for (int i = 0; i < numCaps; i++){ PHIDP_BUTTON_CAPS pCaps = &pButtonCaps[i]; elements[*elements_array_index]->parent_collection = collections[pCaps->LinkCollection]; if (!collections[pCaps->LinkCollection]->first_element){ collections[pCaps->LinkCollection]->first_element = elements[*elements_array_index]; - }elements[*elements_array_index]->io_type = report_type; + } + elements[*elements_array_index]->io_type = report_type; elements[*elements_array_index]->index = (*index)++; elements[*elements_array_index]->usage_page = pCaps->UsagePage; - if (pCaps->IsRange){ - elements[*elements_array_index]->usage_min = pCaps->Range.UsageMin; - elements[*elements_array_index]->usage_max = pCaps->Range.UsageMax; - } - else{ - elements[*elements_array_index]->usage = pCaps->NotRange.Usage; - } USHORT bitField = pCaps->BitField; elements[*elements_array_index]->type = bitField & 0xf; elements[*elements_array_index]->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); @@ -1324,7 +1318,20 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar elements[*elements_array_index]->report_id = pCaps->ReportID; elements[*elements_array_index]->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to usage_max - usage_min + 1 (1 bit per usage)? elements[*elements_array_index]->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1? - debug_element(elements[*elements_array_index]); + if (pCaps->IsRange){ + elements[*elements_array_index]->usage = pCaps->Range.UsageMin; + for (int j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ + (*elements_array_index)++; + elements[*elements_array_index] = elements[(*elements_array_index) - 1]; + elements[*elements_array_index]->usage = j; + } + } + else{ + elements[*elements_array_index]->usage = pCaps->NotRange.Usage; + debug_element(elements[*elements_array_index]); + + } + (*elements_array_index)++; } free(pButtonCaps); @@ -1350,6 +1357,7 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar elements[*elements_array_index]->io_type = report_type; elements[*elements_array_index]->index = (*index)++; elements[*elements_array_index]->usage_page = pCaps->UsagePage; + // TODO convert to one element per usage, as above if (pCaps->IsRange){ elements[*elements_array_index]->usage_min = pCaps->Range.UsageMin; elements[*elements_array_index]->usage_max = pCaps->Range.UsageMax; @@ -1422,11 +1430,11 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de if (!HidD_GetPreparsedData(dev_handle, &pp_data)){ return -1; } - long max_usage_and_page_length = HidP_MaxUsageListLength(HidP_Input, 0, pp_data); - PUSAGE_AND_PAGE usage_and_page_list = malloc(max_usage_and_page_length * sizeof(USAGE_AND_PAGE)); - memset(usage_and_page_list, 0, max_usage_and_page_length * sizeof(USAGE_AND_PAGE)); + long usage_and_page_length = HidP_MaxUsageListLength(HidP_Input, 0, pp_data); + PUSAGE_AND_PAGE usage_and_page_list = malloc(usage_and_page_length * sizeof(USAGE_AND_PAGE)); + memset(usage_and_page_list, 0, usage_and_page_length * sizeof(USAGE_AND_PAGE)); - NTSTATUS ntres = HidP_GetButtonsEx(HidP_Input, 0, usage_and_page_list, &max_usage_and_page_length, pp_data, buf, report_length); + NTSTATUS ntres = HidP_GetButtonsEx(HidP_Input, 0, usage_and_page_list, &usage_and_page_length, pp_data, buf, report_length); if ( ntres != HIDP_STATUS_SUCCESS){ free(usage_and_page_list); return -1; @@ -1443,22 +1451,28 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de // TODO may need to use HidP_GetUsageValueArray, if element->report_index > 1 unsigned long new_value; res = HidP_GetUsageValue(HidP_Input, cur_element->usage_page, 0, cur_element->usage, &new_value, pp_data, buf, report_length); - if (res == HIDP_STATUS_USAGE_NOT_FOUND){ + if (res == HIDP_STATUS_SUCCESS){ + // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef ); + if (new_value != cur_element->rawvalue || cur_element->repeat){ + printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); + fflush(stdout); + hid_element_set_value_from_input(cur_element, new_value); + devdesc->_element_callback(cur_element, devdesc->_element_data); + } + } + else if (res == HIDP_STATUS_USAGE_NOT_FOUND){ // Then see if we can find the element's page and usage in the buttons that are set to on, if not, it is implicitly 0 new_value = 0; - for (int i = 0; i < max_usage_and_page_length; i++){ - if (usage_and_page_list[i].UsagePage = cur_element->usage_page && usage_and_page_list[i].Usage == cur_element->usage){ + for (int i = 0; i < usage_and_page_length; i++){ + USAGE usage = usage_and_page_list[i].Usage; + if (usage_and_page_list[i].UsagePage = cur_element->usage_page && usage == cur_element->usage){ new_value = 1; + hid_element_set_value_from_input(cur_element, new_value); + devdesc->_element_callback(cur_element, devdesc->_element_data); + break; } } } - // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef ); - if (new_value != cur_element->rawvalue || cur_element->repeat){ - printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); - fflush(stdout); - hid_element_set_value_from_input(cur_element, new_value); - devdesc->_element_callback(cur_element, devdesc->_element_data); - } } cur_element = hid_get_next_input_element(cur_element); } From 4e27e89c9139cbaf3bec4589b2c039765db54e26 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Thu, 19 May 2016 12:53:17 +0100 Subject: [PATCH 10/29] win: properly create elements and refactor Taking into account when there is arrange of usages or a HID element, each should have its own SC element (at least if it is not an array) --- hidapi_parser/hidapi_parser.c | 215 +++++++++++++++++++++------------- 1 file changed, 131 insertions(+), 84 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 4e670ec4..ebebaeae 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -150,6 +150,8 @@ struct hid_device_element * hid_new_element(){ struct hid_device_element * element = (struct hid_device_element *) malloc( sizeof( struct hid_device_element ) ); element->next = NULL; + element->parent_collection = NULL; + element->index = -1; element->repeat = 0; element->usage_min = 0; @@ -1271,23 +1273,81 @@ void debug_collection(struct hid_device_collection *collection, int col_index) printf("usage_page: %d\n", collection->usage_page); printf("usage_index: %d\n", collection->usage_index); printf("parent: %p\n", collection->parent_collection); - printf("children: %d\n", collection->num_collections); - if (collection->num_collections > 0) + printf("children collections: %d\n", collection->num_collections); + if (collection->first_collection) printf("first_collection: %p\n", collection->first_collection); if (collection->next_collection) printf("next_collection: %p\n", collection->next_collection); - + printf("children elements: %d\n", collection->num_elements); + if (collection->first_element) + printf("first_element: %p\n", collection->first_element); printf("\n\n"); fflush(stdout); } +static void add_element_to_collection(struct hid_device_collection *collection, struct hid_device_element *element) +{ + if (!collection->first_element){ + collection->first_element = element; + } + collection->num_elements++; + element->parent_collection = collection; +} + + +static struct hid_device_element *duplicate_element_with_new_usage(struct hid_device_element *source_element, int new_usage, struct hid_device_collection *device_collection, int *index) +{ + struct hid_device_element *new_element = hid_new_element(); + memcpy(new_element, source_element, sizeof(struct hid_device_element)); + new_element->index = (*index)++; + device_collection->num_elements++; + // Update the collection + add_element_to_collection(source_element->parent_collection, new_element); + new_element->usage = new_usage; + return new_element; +} + +static void fill_element_from_button_caps(PHIDP_BUTTON_CAPS pCaps, struct hid_device_element *element) +{ + USHORT bitField = pCaps->BitField; + element->usage_page = pCaps->UsagePage; + element->type = bitField & 0xf; + element->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); + element->isrelative = pCaps->IsAbsolute ? 0 : 1; + element->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); + element->report_id = pCaps->ReportID; + element->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to usage_max - usage_min + 1 (1 bit per usage)? + element->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1? + +} + + +static void fill_element_from_value_caps(PHIDP_VALUE_CAPS pCaps, struct hid_device_element *element) +{ + USHORT bitField = pCaps->BitField; + element->usage_page = pCaps->UsagePage; + element->type = bitField & 0xf; + element->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); + element->isrelative = pCaps->IsAbsolute ? 0 : 1; + element->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); + element->logical_min = pCaps->LogicalMin; + element->logical_max = pCaps->LogicalMax; + element->phys_min = pCaps->PhysicalMin; + element->phys_max = pCaps->PhysicalMax; + element->unit = pCaps->Units; + element->unit_exponent = pCaps->UnitsExp; + element->report_id = pCaps->ReportID; + element->report_size = pCaps->BitSize; + element->report_index = pCaps->ReportCount; +} -static int hid_parse_caps(struct hid_device_element **elements, int *elements_array_index, struct hid_device_collection **collections, struct hid_device_collection *device_collection, +static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid_device_collection **ppcollections, struct hid_device_collection *pdevice_collection, const PHIDP_PREPARSED_DATA pp_data, const PHIDP_CAPS caps, int report_type, BOOL is_button, int *index) { USHORT numCaps; enum _HIDP_REPORT_TYPE api_report_type; + struct hid_device_element *plast_element = *pplast_element; if (is_button){ switch (report_type){ @@ -1302,39 +1362,37 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar return -1; } for (int i = 0; i < numCaps; i++){ - PHIDP_BUTTON_CAPS pCaps = &pButtonCaps[i]; - elements[*elements_array_index]->parent_collection = collections[pCaps->LinkCollection]; - if (!collections[pCaps->LinkCollection]->first_element){ - collections[pCaps->LinkCollection]->first_element = elements[*elements_array_index]; + // Create a new element + struct hid_device_element *new_element = hid_new_element(); + if (plast_element){ + plast_element->next = new_element; } - elements[*elements_array_index]->io_type = report_type; - elements[*elements_array_index]->index = (*index)++; - elements[*elements_array_index]->usage_page = pCaps->UsagePage; - USHORT bitField = pCaps->BitField; - elements[*elements_array_index]->type = bitField & 0xf; - elements[*elements_array_index]->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); - elements[*elements_array_index]->isrelative = pCaps->IsAbsolute ? 0 : 1; - elements[*elements_array_index]->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); - elements[*elements_array_index]->report_id = pCaps->ReportID; - elements[*elements_array_index]->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to usage_max - usage_min + 1 (1 bit per usage)? - elements[*elements_array_index]->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1? + // Connect to previous element + plast_element = new_element; + // Add element to collections, and fill element values + PHIDP_BUTTON_CAPS pCaps = &pButtonCaps[i]; + add_element_to_collection(pdevice_collection, new_element); + add_element_to_collection(ppcollections[pCaps->LinkCollection], new_element); + new_element->io_type = report_type; + new_element->index = (*index)++; + fill_element_from_button_caps(pCaps, new_element); if (pCaps->IsRange){ - elements[*elements_array_index]->usage = pCaps->Range.UsageMin; + // If it is a range, we copy the element, and update the usage. We want to have an element per usage. + new_element->usage = pCaps->Range.UsageMin; + debug_element(new_element); for (int j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ - (*elements_array_index)++; - elements[*elements_array_index] = elements[(*elements_array_index) - 1]; - elements[*elements_array_index]->usage = j; + new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index); + plast_element->next = new_element; + plast_element = new_element; + debug_element(new_element); } } else{ - elements[*elements_array_index]->usage = pCaps->NotRange.Usage; - debug_element(elements[*elements_array_index]); - + new_element->usage = pCaps->NotRange.Usage; + debug_element(new_element); } - (*elements_array_index)++; } free(pButtonCaps); - } else { switch (report_type){ @@ -1348,41 +1406,43 @@ static int hid_parse_caps(struct hid_device_element **elements, int *elements_ar free(pValueCaps); return -1; } - for (int i = 0; i < numCaps; i++, (*elements_array_index)++){ - PHIDP_VALUE_CAPS pCaps = &pValueCaps[i]; - elements[*elements_array_index]->parent_collection = collections[pCaps->LinkCollection]; - if (!collections[pCaps->LinkCollection]->first_element){ - collections[pCaps->LinkCollection]->first_element = elements[*elements_array_index]; + for (int i = 0; i < numCaps; i++){ + // Create a new element + struct hid_device_element *new_element = hid_new_element(); + if (plast_element){ + plast_element->next = new_element; } - elements[*elements_array_index]->io_type = report_type; - elements[*elements_array_index]->index = (*index)++; - elements[*elements_array_index]->usage_page = pCaps->UsagePage; - // TODO convert to one element per usage, as above + // Connect to previous element + plast_element = new_element; + // Add element to collections, and fill element values + PHIDP_VALUE_CAPS pCaps = &pValueCaps[i]; + add_element_to_collection(pdevice_collection, new_element); + add_element_to_collection(ppcollections[pCaps->LinkCollection], new_element); + new_element->io_type = report_type; + new_element->index = (*index)++; + fill_element_from_value_caps(pCaps, new_element); + if (pCaps->IsRange){ - elements[*elements_array_index]->usage_min = pCaps->Range.UsageMin; - elements[*elements_array_index]->usage_max = pCaps->Range.UsageMax; + // If it is a range, we copy the element, and update the usage. We want to have an element per usage. + new_element->usage = pCaps->Range.UsageMin; + debug_element(new_element); + for (int j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ + new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index); + plast_element->next = new_element; + plast_element = new_element; + debug_element(new_element); + } } else{ - elements[*elements_array_index]->usage = pCaps->NotRange.Usage; + new_element->usage = pCaps->NotRange.Usage; + debug_element(new_element); } - USHORT bitField = pCaps->BitField; - elements[*elements_array_index]->type = bitField & 0xf; - elements[*elements_array_index]->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); - elements[*elements_array_index]->isrelative = pCaps->IsAbsolute ? 0 : 1; - elements[*elements_array_index]->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); - elements[*elements_array_index]->logical_min = pCaps->LogicalMin; - elements[*elements_array_index]->logical_max = pCaps->LogicalMax; - elements[*elements_array_index]->phys_min = pCaps->PhysicalMin; - elements[*elements_array_index]->phys_max = pCaps->PhysicalMax; - elements[*elements_array_index]->unit = pCaps->Units; - elements[*elements_array_index]->unit_exponent = pCaps->UnitsExp; - elements[*elements_array_index]->report_id = pCaps->ReportID; - elements[*elements_array_index]->report_size = pCaps->BitSize; - elements[*elements_array_index]->report_index = pCaps->ReportCount; - debug_element(elements[*elements_array_index]); } free(pValueCaps); } + + // make sure the last element index is visible outside + *pplast_element = plast_element; return 0; } @@ -1537,10 +1597,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ device_collection->usage_index = caps.Usage; device_collection->index = new_index++; - device_collection->num_elements = - caps.NumberInputButtonCaps + caps.NumberInputValueCaps + - caps.NumberOutputButtonCaps + caps.NumberOutputValueCaps + - caps.NumberFeatureButtonCaps + caps.NumberFeatureValueCaps; + device_collection->num_elements = 0; PHIDP_LINK_COLLECTION_NODE linkCollectionNodes; linkCollectionNodes = malloc(numColls * sizeof(HIDP_LINK_COLLECTION_NODE)); @@ -1576,7 +1633,6 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ collections[i]->first_collection = collections[p_collection->FirstChild]; collections[i]->num_collections = p_collection->NumberOfChildren; - // TODO set pointer to first element collections[i]->type = p_collection->CollectionType; collections[i]->usage_page = p_collection->LinkUsagePage; collections[i]->usage_index = p_collection->LinkUsage; @@ -1585,33 +1641,24 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ } debug_collection(device_collection, 100); - /* And create all the element structures with pointers, so that we can create the links. We create the links at the beginning for convenience */ - struct hid_device_element **elements = malloc(device_collection->num_elements * sizeof(struct hid_device_element *)); - for (int i = 0; i < device_collection->num_elements; i++){ - elements[i] = hid_new_element(); - } - for (int i = 0; i < device_collection->num_elements - 1; i++){ - elements[i]->next = elements[i + 1]; - } - - device_collection->first_element = elements[0]; - - /* Now parse the (input, output, feature) x (button, values) capabilities */ + /* Now, create the elements, parsing the (input, output, feature) x (button, values) capabilities */ int index_element = 0; new_index = 0; - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, FALSE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, TRUE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, TRUE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, FALSE, &new_index); - hid_parse_caps(elements, &index_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, TRUE, &new_index); + struct hid_device_element *last_element = NULL; + hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, FALSE, &new_index); + hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_INPUT, TRUE, &new_index); + hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, FALSE, &new_index); + hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_OUTPUT, TRUE, &new_index); + hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, FALSE, &new_index); + hid_parse_caps(&last_element, collections, device_collection, pp_data, &caps, HID_REPORT_TYPE_FEATURE, TRUE, &new_index); /* Reports */ - // Pehaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports - for (int i = 0; i < index_element; i++){ - int report_id = elements[i]->report_id; - int report_size = elements[i]->report_size; - int report_count = elements[i]->report_index; // TODO: report_count is not used???? + // Perhaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports + struct hid_device_element *element = device_collection->first_element; + while (element != NULL){ + int report_id = element->report_id; + int report_size = element->report_size; + int report_count = element->report_index; // TODO: report_count is not used???? int reportexists = 0; for (int j = 0; j < numreports; j++){ @@ -1631,6 +1678,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ } } report_lengths[index] += report_size; + element = element->next; } devdesc->number_of_reports = numreports; @@ -1642,7 +1690,6 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ } /* And clean up the temp structures */ - free(elements); free(collections); free(linkCollectionNodes); HidD_FreePreparsedData(pp_data); From 6a9a5c8777d7beba1a909ce8385823d9254fa954 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Fri, 20 May 2016 09:49:55 +0100 Subject: [PATCH 11/29] win: some reformatting --- hidapi_parser/hidapi_parser.c | 74 +++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index ebebaeae..5da6fe88 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -694,38 +694,42 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ } void hid_element_set_value_from_input( struct hid_device_element * element, int value ){ - element->rawvalue = value; - if ( element->logical_min < 0 ){ - // value should be interpreted as signed value - // so: check report size, test the highest bit, if one, invert and add one, otherwise keep value - int bitSignIndex = element->report_size - 1; - int signBit = 0x1 << bitSignIndex; - if ( signBit & value ){ - unsigned int bitMask = BITMASK1( element->report_size ); - unsigned int uvalue = (unsigned int) value; - unsigned int negvalue = ~(uvalue); - negvalue = ~(uvalue) & bitMask; - negvalue = negvalue + 1; - element->value = -1 * negvalue; - } else { - element->value = value; - } - } else { - // value should be interpreted as unsigned value - // so: keep value as is - if ( element->isarray ){ // array elements should be parsed differently - if ( value == 0 ){ // previous key was pressed, so keep previous usage - element->value = 0; - element->array_value = 0; - } else { // new key, so value + usage min is the current usage - element->usage = element->usage_min + value; - element->value = 1; - element->array_value = value; - } - } else { - element->value = value; + element->rawvalue = value; + if (element->logical_min < 0){ + // value should be interpreted as signed value + // so: check report size, test the highest bit, if one, invert and add one, otherwise keep value + int bitSignIndex = element->report_size - 1; + int signBit = 0x1 << bitSignIndex; + if (signBit & value){ + unsigned int bitMask = BITMASK1(element->report_size); + unsigned int uvalue = (unsigned int)value; + unsigned int negvalue = ~(uvalue); + negvalue = ~(uvalue)& bitMask; + negvalue = negvalue + 1; + element->value = -1 * negvalue; + } + else { + element->value = value; + } + } + else { + // value should be interpreted as unsigned value + // so: keep value as is + if (element->isarray){ // array elements should be parsed differently + if (value == 0){ // previous key was pressed, so keep previous usage + element->value = 0; + element->array_value = 0; + } + else { // new key, so value + usage min is the current usage + element->usage = element->usage_min + value; + element->value = 1; + element->array_value = value; + } + } + else { + element->value = value; + } } - } } float hid_element_map_logical( struct hid_device_element * element ){ @@ -1514,7 +1518,7 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de if (res == HIDP_STATUS_SUCCESS){ // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef ); if (new_value != cur_element->rawvalue || cur_element->repeat){ - printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); + //printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); fflush(stdout); hid_element_set_value_from_input(cur_element, new_value); devdesc->_element_callback(cur_element, devdesc->_element_data); @@ -1527,11 +1531,13 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de USAGE usage = usage_and_page_list[i].Usage; if (usage_and_page_list[i].UsagePage = cur_element->usage_page && usage == cur_element->usage){ new_value = 1; - hid_element_set_value_from_input(cur_element, new_value); - devdesc->_element_callback(cur_element, devdesc->_element_data); break; } } + if (new_value != cur_element->rawvalue || cur_element->repeat){ + hid_element_set_value_from_input(cur_element, new_value); + devdesc->_element_callback(cur_element, devdesc->_element_data); + } } } cur_element = hid_get_next_input_element(cur_element); From bbe86b14f4319642564c5ca406ac6fcf2546a3cd Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Fri, 20 May 2016 09:50:13 +0100 Subject: [PATCH 12/29] win: some tidying up, and update header file --- hidapi_parser/hidapi_parser.h | 2 +- windows/hid.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hidapi_parser/hidapi_parser.h b/hidapi_parser/hidapi_parser.h index 73103d81..e6056447 100644 --- a/hidapi_parser/hidapi_parser.h +++ b/hidapi_parser/hidapi_parser.h @@ -184,7 +184,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ); #ifdef WIN32 int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_element * element ); -int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * devdesc ); +int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_dev_desc * devdesc ); void hid_parse_element_info( struct hid_dev_desc * devdesc ); #endif diff --git a/windows/hid.c b/windows/hid.c index 43a8491f..ca08451e 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -807,7 +807,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char if (GetLastError() != ERROR_IO_PENDING) { /* ReadFile() has failed. Clean up and return error. */ - CancelIoEx(dev->device_handle); + CancelIo(dev->device_handle); dev->read_pending = FALSE; goto end_of_function; } From a8d77d70021fdbd6db21eae4b2af8c646818b294 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Sun, 22 May 2016 22:47:04 +0100 Subject: [PATCH 13/29] do not the DDK to compile now The Hid components are part of the standard SDK with MSVC --- windows/hid.c | 216 -------------------------------------------------- 1 file changed, 216 deletions(-) diff --git a/windows/hid.c b/windows/hid.c index ca08451e..7f4fbf84 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -38,16 +38,11 @@ typedef LONG NTSTATUS; #define _wcsdup wcsdup #endif -/*#define HIDAPI_USE_DDK*/ - #ifdef __cplusplus extern "C" { #endif #include #include - #ifdef HIDAPI_USE_DDK - #include - #endif /* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */ #define HID_OUT_CTL_CODE(id) \ @@ -73,172 +68,6 @@ extern "C" { extern "C" { #endif -#if 0 - /* Since we're not building with the DDK, and the HID header - files aren't part of the SDK, we have to define all this - stuff here. In lookup_functions(), the function pointers - defined below are set. */ - typedef struct _HIDD_ATTRIBUTES{ - ULONG Size; - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; - } HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; - - typedef USHORT USAGE; - typedef struct _HIDP_CAPS { - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - USHORT fields_not_used_by_hidapi[10]; - } HIDP_CAPS, *PHIDP_CAPS; - typedef void* PHIDP_PREPARSED_DATA; - - typedef enum _HIDP_REPORT_TYPE { - HidP_Input, - HidP_Output, - HidP_Feature - } HIDP_REPORT_TYPE; - -typedef struct _HIDP_BUTTON_CAPS { - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - USHORT BitField; - USHORT LinkCollection; - USAGE LinkUsage; - USAGE LinkUsagePage; - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - ULONG Reserved[10]; - 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; - }; -} HIDP_BUTTON_CAPS, *PHIDP_BUTTON_CAPS; - - -typedef struct _HIDP_VALUE_CAPS { - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - USHORT BitField; - USHORT LinkCollection; - USAGE LinkUsage; - USAGE LinkUsagePage; - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - BOOLEAN HasNull; - UCHAR Reserved; - USHORT BitSize; - USHORT ReportCount; - USHORT Reserved2[5]; - ULONG UnitsExp; - ULONG Units; - LONG LogicalMin; - LONG LogicalMax; - LONG PhysicalMin; - LONG PhysicalMax; - 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; - }; -} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; - -typedef struct _HIDP_LINK_COLLECTION_NODE { - USAGE LinkUsage; - USAGE LinkUsagePage; - USHORT Parent; - USHORT NumberOfChildren; - USHORT NextSibling; - USHORT FirstChild; - ULONG CollectionType :8; - ULONG IsAlias :1; - ULONG Reserved :23; - PVOID UserContext; -} HIDP_LINK_COLLECTION_NODE, *PHIDP_LINK_COLLECTION_NODE; - - #define HIDP_STATUS_SUCCESS 0x110000 - - typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib); - typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length); - typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len); - typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data); - typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data); - typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps); - typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers); - - typedef NTSTATUS (__stdcall *HidP_GetLinkCollectionNodes_)( PHIDP_LINK_COLLECTION_NODE link_collection_nodes, PULONG link_collection_nodes_length, PHIDP_PREPARSED_DATA preparsed_data); - typedef NTSTATUS (__stdcall *HidP_GetButtonCaps_)( HIDP_REPORT_TYPE report_type, PHIDP_BUTTON_CAPS button_caps, PUSHORT button_caps_length, PHIDP_PREPARSED_DATA preparsed_data ); - typedef NTSTATUS (__stdcall *HidP_GetValueCaps_)( HIDP_REPORT_TYPE report_type, PHIDP_VALUE_CAPS value_caps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA preparsed_data ); - - static HidD_GetAttributes_ HidD_GetAttributes; - static HidD_GetSerialNumberString_ HidD_GetSerialNumberString; - static HidD_GetManufacturerString_ HidD_GetManufacturerString; - static HidD_GetProductString_ HidD_GetProductString; - static HidD_SetFeature_ HidD_SetFeature; - static HidD_GetFeature_ HidD_GetFeature; - static HidD_GetIndexedString_ HidD_GetIndexedString; - static HidD_GetPreparsedData_ HidD_GetPreparsedData; - static HidD_FreePreparsedData_ HidD_FreePreparsedData; - static HidP_GetCaps_ HidP_GetCaps; - static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers; - - static HidP_GetLinkCollectionNodes_ HidP_GetLinkCollectionNodes; - static HidP_GetButtonCaps_ HidP_GetButtonCaps; - static HidP_GetValueCaps_ HidP_GetValueCaps; - - static HMODULE lib_handle = NULL; - static BOOLEAN initialized = FALSE; -#endif /* HIDAPI_USE_DDK */ - struct hid_device_ { HANDLE device_handle; BOOL blocking; @@ -307,36 +136,6 @@ static void register_error(hid_device *device, const char *op) device->last_error_str = msg; } -#if 0 HIDAPI_USE_DDK -static int lookup_functions() -{ - lib_handle = LoadLibraryA("hid.dll"); - if (lib_handle) { -#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1; - RESOLVE(HidD_GetAttributes); - RESOLVE(HidD_GetSerialNumberString); - RESOLVE(HidD_GetManufacturerString); - RESOLVE(HidD_GetProductString); - RESOLVE(HidD_SetFeature); - RESOLVE(HidD_GetFeature); - RESOLVE(HidD_GetIndexedString); - RESOLVE(HidD_GetPreparsedData); - RESOLVE(HidD_FreePreparsedData); - RESOLVE(HidP_GetCaps); - RESOLVE(HidD_SetNumInputBuffers); - - RESOLVE(HidP_GetLinkCollectionNodes); - RESOLVE(HidP_GetButtonCaps); - RESOLVE(HidP_GetValueCaps); -#undef RESOLVE - } - else - return -1; - - return 0; -} -#endif - static HANDLE open_device(const char *path, BOOL enumerate) { HANDLE handle; @@ -358,26 +157,11 @@ static HANDLE open_device(const char *path, BOOL enumerate) int HID_API_EXPORT hid_init(void) { -#if 0 HIDAPI_USE_DDK - if (!initialized) { - if (lookup_functions() < 0) { - hid_exit(); - return -1; - } - initialized = TRUE; - } -#endif return 0; } int HID_API_EXPORT hid_exit(void) { -#if 0 HIDAPI_USE_DDK - if (lib_handle) - FreeLibrary(lib_handle); - lib_handle = NULL; - initialized = FALSE; -#endif return 0; } From 2ba471cfa3ddc2b2fbc7896022f8850f03e389b1 Mon Sep 17 00:00:00 2001 From: Luis Lloret Date: Sun, 22 May 2016 22:48:26 +0100 Subject: [PATCH 14/29] fix logical values for buttons, DEBUG_PARSER, C99 loop variable and some tidying up --- hidapi_parser/hidapi_parser.c | 65 ++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 5da6fe88..def812e5 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -1317,11 +1317,13 @@ static void fill_element_from_button_caps(PHIDP_BUTTON_CAPS pCaps, struct hid_de USHORT bitField = pCaps->BitField; element->usage_page = pCaps->UsagePage; element->type = bitField & 0xf; + element->logical_min = 0; + element->logical_max = 1; element->isarray = ((bitField & HID_ITEM_VARIABLE) == 0); element->isrelative = pCaps->IsAbsolute ? 0 : 1; element->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); element->report_id = pCaps->ReportID; - element->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to usage_max - usage_min + 1 (1 bit per usage)? + element->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; element->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1? } @@ -1349,6 +1351,7 @@ static void fill_element_from_value_caps(PHIDP_VALUE_CAPS pCaps, struct hid_devi static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid_device_collection **ppcollections, struct hid_device_collection *pdevice_collection, const PHIDP_PREPARSED_DATA pp_data, const PHIDP_CAPS caps, int report_type, BOOL is_button, int *index) { + int i, j; USHORT numCaps; enum _HIDP_REPORT_TYPE api_report_type; struct hid_device_element *plast_element = *pplast_element; @@ -1365,7 +1368,7 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid free(pButtonCaps); return -1; } - for (int i = 0; i < numCaps; i++){ + for (i = 0; i < numCaps; i++){ // Create a new element struct hid_device_element *new_element = hid_new_element(); if (plast_element){ @@ -1382,18 +1385,24 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid fill_element_from_button_caps(pCaps, new_element); if (pCaps->IsRange){ // If it is a range, we copy the element, and update the usage. We want to have an element per usage. - new_element->usage = pCaps->Range.UsageMin; + new_element->usage = pCaps->Range.UsageMin; +#ifdef DEBUG_PARSER debug_element(new_element); - for (int j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ +#endif + for (j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index); plast_element->next = new_element; plast_element = new_element; +#ifdef DEBUG_PARSER debug_element(new_element); +#endif } } else{ new_element->usage = pCaps->NotRange.Usage; +#ifdef DEBUG_PARSER debug_element(new_element); +#endif } } free(pButtonCaps); @@ -1410,7 +1419,7 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid free(pValueCaps); return -1; } - for (int i = 0; i < numCaps; i++){ + for (i = 0; i < numCaps; i++){ // Create a new element struct hid_device_element *new_element = hid_new_element(); if (plast_element){ @@ -1430,16 +1439,20 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid // If it is a range, we copy the element, and update the usage. We want to have an element per usage. new_element->usage = pCaps->Range.UsageMin; debug_element(new_element); - for (int j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ + for (j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index); plast_element->next = new_element; plast_element = new_element; +#ifdef DEBUG_PARSER debug_element(new_element); +#endif } } else{ new_element->usage = pCaps->NotRange.Usage; - debug_element(new_element); +#ifdef DEBUG_PARSER + debug_element(new_element); +#endif } } free(pValueCaps); @@ -1456,9 +1469,8 @@ int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_el return 0; } int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){ - // TO see how to handle HID Reports - //See https ://msdn.microsoft.com/en-us/library/windows/hardware/ff538783(v=vs.85).aspx // If there is only one report, there will be no report ID in the report. Otherwise, it is the first byte + int i; int report_id = 0; int report_length = 0; struct hid_device_collection * device_collection = devdesc->device_collection; @@ -1469,9 +1481,8 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de report_id = buf[0]; } - // TODO: perhaps on Windows we do not need to calculate the report size here, and we can just get it from the size parameter that we got from above - // Look for the size of the report (in bits), and convert to bytes (rounding up) - for (int i = 0; i < devdesc->number_of_reports; i++){ + // I thtink on Windows we do not need to calculate the report size here, and we can just get it from the size parameter that we got from above + for (i = 0; i < devdesc->number_of_reports; i++){ if (devdesc->report_ids[i] == report_id){ report_length = size; } @@ -1484,11 +1495,9 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de if (cur_element->io_type != HID_REPORT_TYPE_INPUT){ cur_element = hid_get_next_input_element(cur_element); } - //printf("cur_element %p\n", cur_element ); // The Windows API has a function to get the data of all the buttons that are on, and another to get the value data by component page and usage // We get all the buttons that are on - // TODO: perhaps we could put the preparsed data in the devdesc structure (only for Windows) HANDLE dev_handle = get_device_handle(devdesc->device); PHIDP_PREPARSED_DATA pp_data; if (!HidD_GetPreparsedData(dev_handle, &pp_data)){ @@ -1516,10 +1525,10 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de unsigned long new_value; res = HidP_GetUsageValue(HidP_Input, cur_element->usage_page, 0, cur_element->usage, &new_value, pp_data, buf, report_length); if (res == HIDP_STATUS_SUCCESS){ - // printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalueref %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, newValueRef ); if (new_value != cur_element->rawvalue || cur_element->repeat){ - //printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); - fflush(stdout); +#ifdef DEBUG_PARSER + printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); +#endif hid_element_set_value_from_input(cur_element, new_value); devdesc->_element_callback(cur_element, devdesc->_element_data); } @@ -1527,7 +1536,7 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de else if (res == HIDP_STATUS_USAGE_NOT_FOUND){ // Then see if we can find the element's page and usage in the buttons that are set to on, if not, it is implicitly 0 new_value = 0; - for (int i = 0; i < usage_and_page_length; i++){ + for (i = 0; i < usage_and_page_length; i++){ USAGE usage = usage_and_page_list[i].Usage; if (usage_and_page_list[i].UsagePage = cur_element->usage_page && usage == cur_element->usage){ new_value = 1; @@ -1536,6 +1545,9 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de } if (new_value != cur_element->rawvalue || cur_element->repeat){ hid_element_set_value_from_input(cur_element, new_value); +#ifdef DEBUG_PARSER + printf("element page %i, usage %i, index %i, value %i, rawvalue %i, newvalue %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->rawvalue, new_value); +#endif devdesc->_element_callback(cur_element, devdesc->_element_data); } } @@ -1548,6 +1560,7 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de } void hid_parse_element_info( struct hid_dev_desc * devdesc ){ + int i, j; hid_device * dev = devdesc->device; struct hid_device_collection * device_collection = hid_new_collection(); @@ -1615,12 +1628,12 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ } // Create the N collections, and put them in an array, so that we can efficiently construct the pointers to each other using the Windows API - for (int i = 0; i < numColls; i++){ + for (i = 0; i < numColls; i++){ collections[i] = hid_new_collection(); } // And now fill the data and create the collection links - for (int i = 0; i < numColls; i++){ + for (i = 0; i < numColls; i++){ PHIDP_LINK_COLLECTION_NODE p_collection = &linkCollectionNodes[i]; // Documentation says that if parent is 0, then there is no parent, but then how do you indicate that the parent is at index 0??? // I think that is wrong, and 0 indicates that the parent is the collection at index @@ -1643,9 +1656,13 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ collections[i]->usage_page = p_collection->LinkUsagePage; collections[i]->usage_index = p_collection->LinkUsage; collections[i]->index = new_index++; // TODO not sure about this one +#ifdef DEBUG_PARSER debug_collection(collections[i], i); - } +#endif + } +#ifdef DEBUG_PARSER debug_collection(device_collection, 100); +#endif /* Now, create the elements, parsing the (input, output, feature) x (button, values) capabilities */ int index_element = 0; @@ -1660,6 +1677,8 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ /* Reports */ // Perhaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports + // On Windows it is not clear that knowing the report size is important at this point, since we get it implicitly on the read size. It's quite likely that the calculation done here + // is not right, but it does not affect (should revisit later) struct hid_device_element *element = device_collection->first_element; while (element != NULL){ int report_id = element->report_id; @@ -1667,7 +1686,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ int report_count = element->report_index; // TODO: report_count is not used???? int reportexists = 0; - for (int j = 0; j < numreports; j++){ + for (j = 0; j < numreports; j++){ reportexists = (report_ids[j] == report_id); } if (!reportexists){ @@ -1690,7 +1709,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ devdesc->number_of_reports = numreports; devdesc->report_lengths = (int*)malloc(sizeof(int) * numreports); devdesc->report_ids = (int*)malloc(sizeof(int) * numreports); - for (int j = 0; jreport_lengths[j] = report_lengths[j]; devdesc->report_ids[j] = report_ids[j]; } From 9746deafda435c5ff3e3413d31a208f73541200d Mon Sep 17 00:00:00 2001 From: bagong Date: Wed, 25 May 2016 21:04:01 +0200 Subject: [PATCH 15/29] Win: Add extended hidsdi.h for MinGW build --- windows/hidsdi.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 windows/hidsdi.h diff --git a/windows/hidsdi.h b/windows/hidsdi.h new file mode 100644 index 00000000..1ccf5492 --- /dev/null +++ b/windows/hidsdi.h @@ -0,0 +1,88 @@ +/* + * hidsdi.h + * + * [extended MinGW header with definitions for hidapi in SuperCollider 3.8 MinGW build + * source: https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/87mxjs7l5a.fsf@latte.josefsson.org/ + * tested with MinGW 4.8.2 as provided with Qt 5.5: + * version : MinGW-W64-builds-4.2.0 + * user : niXman] + * + * Public interface for USB HID user space functions. + * + * Contributors: + * Created by Simon Josefsson + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __HIDSDI_H +#define __HIDSDI_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* http://msdn.microsoft.com/en-us/library/ff538876%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_FlushQueue(HANDLE HidDeviceObject); + +/* http://msdn.microsoft.com/en-us/library/ff538900%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetAttributes(HANDLE HidDeviceObject, PHIDD_ATTRIBUTES Attributes); + +/* http://msdn.microsoft.com/en-us/library/ff538945%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetInputReport(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength); + +/* http://msdn.microsoft.com/en-us/library/ff539677%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetPhysicalDescriptor(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); + +/* http://msdn.microsoft.com/en-us/library/ff538959%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetManufacturerString(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); + +/* http://msdn.microsoft.com/en-us/library/windows/hardware/ff539681(v=vs.85).aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetProductString (HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); + +/* http://msdn.microsoft.com/en-us/library/ff539683%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetSerialNumberString(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); + +/* http://msdn.microsoft.com/en-us/library/ff538910%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetFeature(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength); + + /* http://msdn.microsoft.com/en-us/library/ff539684%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_SetFeature(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength); + +/* http://msdn.microsoft.com/en-us/library/ff538924(v=vs.85).aspx */ +HIDAPI VOID NTAPI HidD_GetHidGuid(LPGUID HidGuid); + +/* http://msdn.microsoft.com/en-us/library/windows/hardware/ff539675(v=vs.85).aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetNumInputBuffers (HANDLE HidDeviceObject, PULONG NumberBuffers); + +/* http://msdn.microsoft.com/en-us/library/windows/hardware/ff539686(v=vs.85).aspx */ +HIDAPI BOOLEAN NTAPI HidD_SetNumInputBuffers (HANDLE HidDeviceObject, ULONG NumberBuffers); + +/* http://msdn.microsoft.com/en-us/library/ff538893%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_FreePreparsedData(PHIDP_PREPARSED_DATA PreparsedData); + +/*http://msdn.microsoft.com/en-us/library/ff539679%28v=VS.85%29.aspx*/ +HIDAPI BOOLEAN NTAPI HidD_GetPreparsedData(HANDLE HidDeviceObject, PHIDP_PREPARSED_DATA *PreparsedData); + +/* http://msdn.microsoft.com/en-us/library/ff538927%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_GetIndexedString(HANDLE HidDeviceObject, ULONG StringIndex, PVOID Buffer, ULONG BufferLength); + +/* http://msdn.microsoft.com/en-us/library/ff539690%28v=VS.85%29.aspx */ +HIDAPI BOOLEAN NTAPI HidD_SetOutputReport(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength); + +#ifdef __cplusplus +} +#endif + +#endif /* __HIDSDI_H */ From 543ff1295787e052b663d03a8e69299c8104cd8e Mon Sep 17 00:00:00 2001 From: bagong Date: Wed, 25 May 2016 21:04:50 +0200 Subject: [PATCH 16/29] Win: use added header in MinGW build --- hidapi_parser/hidapi_parser.c | 187 ++++++++++++++++++---------------- windows/hid.c | 43 ++++---- 2 files changed, 121 insertions(+), 109 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index def812e5..38ff3bbe 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -1,12 +1,12 @@ -/* hidapi_parser $ +/* hidapi_parser $ * * Copyright (C) 2013, Marije Baalman * This work was funded by a crowd-funding initiative for SuperCollider's [1] HID implementation * including a substantial donation from BEK, Bergen Center for Electronic Arts, Norway - * + * * [1] http://supercollider.sourceforge.net * [2] http://www.bek.no - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or @@ -27,8 +27,15 @@ #include #include +#ifdef _WIN32 #include +#ifdef __MINGW32__ +#include "../windows/hidsdi.h" +#else #include +#endif +#endif + #include "hidapi_parser.h" @@ -140,7 +147,7 @@ // struct hid_device_descriptor * descriptor; // descriptor = (struct hid_device_descriptor *) malloc( sizeof( struct hid_device_descriptor) ); // // hid_descriptor_init( descriptor ); -// +// // descriptor->first = NULL; // hid_set_descriptor_callback(descriptor, NULL, NULL); // hid_set_element_callback(descriptor, NULL, NULL); @@ -153,7 +160,7 @@ struct hid_device_element * hid_new_element(){ element->parent_collection = NULL; element->index = -1; element->repeat = 0; - + element->usage_min = 0; element->usage_max = 0; element->logical_min = 0; @@ -163,7 +170,7 @@ struct hid_device_element * hid_new_element(){ element->report_id = 0; element->unit = 0; element->unit_exponent = 0; - + element->rawvalue = 0; return element; @@ -221,7 +228,7 @@ void hid_set_element_callback( struct hid_dev_desc * devd, hid_element_callback } void hid_set_from_making_element( struct hid_device_element * making, struct hid_device_element * new_element ){ - + new_element->type = making->type; new_element->isrelative = (making->type & HID_ITEM_RELATIVE ) > 0; new_element->isarray = ( (making->type & HID_ITEM_VARIABLE ) == 0 ); @@ -235,14 +242,14 @@ void hid_set_from_making_element( struct hid_device_element * making, struct hid if ( (making->phys_min == 0) && (making->phys_max == 0) ){ new_element->phys_min = making->logical_min; new_element->phys_max = making->logical_max; - + } else { new_element->phys_min = making->phys_min; new_element->phys_max = making->phys_max; } new_element->unit = making->unit; new_element->unit_exponent = making->unit_exponent; - + new_element->report_size = making->report_size; new_element->report_id = making->report_id; } @@ -250,7 +257,7 @@ void hid_set_from_making_element( struct hid_device_element * making, struct hid int hid_element_get_signed_value( int inputvalue, int bytesize ){ int outputvalue; int bitSignIndex = bytesize*8 - 1; - int signBit = 0x1 << bitSignIndex; + int signBit = 0x1 << bitSignIndex; if ( signBit & inputvalue ){ unsigned int bitMask = BITMASK1( bytesize*8 ); unsigned int uvalue = (unsigned int) inputvalue; @@ -268,36 +275,36 @@ int hid_element_get_signed_value( int inputvalue, int bytesize ){ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_dev_desc * device_desc ){ struct hid_device_collection * device_collection = hid_new_collection(); device_desc->device_collection = device_collection; - + struct hid_device_collection * parent_collection = device_desc->device_collection; struct hid_device_collection * prev_collection = 0; struct hid_device_element * prev_element = 0; - + struct hid_device_element * making_element = hid_new_element(); - + int current_usages[256]; int current_usage_index = 0; int current_report_size; int current_usage_min = -1; int current_usage_max = -1; - + int current_report_count = 0; // unsigned char current_input; // unsigned char current_output; int collection_nesting = 0; - + int next_byte_tag = -1; int next_byte_size = 0; int next_byte_type = 0; int next_val = 0; - + unsigned char toadd = 0; int byte_count = 0; - + int i,j; - + int numreports = 1; int report_lengths[256]; int report_ids[256]; @@ -306,7 +313,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ int k; int index; - + device_collection->num_collections = 0; device_collection->num_elements = 0; #ifdef DEBUG_PARSER @@ -494,7 +501,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ new_element->usage = current_usage_min + j; } new_element->report_index = j; - + new_element->value = 0; new_element->array_value = 0; if ( parent_collection->num_elements == 0 ){ @@ -529,7 +536,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ #endif making_element->type = next_val; // add the elements for this report - for ( j=0; jio_type = 2; @@ -542,7 +549,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ new_element->usage = current_usage_min + j; } new_element->report_index = j; - + index = 0; for ( k=0; kreport_id == report_ids[k] ){ @@ -551,7 +558,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ } } report_lengths[index] += making_element->report_size; - + new_element->value = 0; new_element->array_value = 0; if ( parent_collection->num_elements == 0 ){ @@ -587,7 +594,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ making_element->type = next_val; // add the elements for this report for ( j=0; jio_type = 3; new_element->index = device_collection->num_elements; new_element->parent_collection = parent_collection; @@ -598,7 +605,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ new_element->usage = current_usage_min + j; } new_element->report_index = j; - + new_element->value = 0; new_element->array_value = 0; if ( parent_collection->num_elements == 0 ){ @@ -621,7 +628,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ } current_usage_index = 0; current_usage_min = -1; - current_usage_max = -1; + current_usage_max = -1; making_element->usage_min = -1; making_element->usage_max = -1; making_element->usage = 0; @@ -653,7 +660,7 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ making_element->usage_max = -1; current_usage_index = 0; current_usage_min = -1; - current_usage_max = -1; + current_usage_max = -1; collection_nesting--; #ifdef DEBUG_PARSER printf("\n\tend collection: %i, %i\n", collection_nesting, descr_buf[i] ); @@ -685,11 +692,11 @@ int hid_parse_report_descriptor( unsigned char* descr_buf, int size, struct hid_ device_desc->report_lengths[j] = report_lengths[j]; device_desc->report_ids[j] = report_ids[j]; } - + #ifdef DEBUG_PARSER printf("----------- end setting report ids --------------\n " ); #endif - + return 0; } @@ -732,7 +739,7 @@ void hid_element_set_value_from_input( struct hid_device_element * element, int } } -float hid_element_map_logical( struct hid_device_element * element ){ +float hid_element_map_logical( struct hid_device_element * element ){ float result; if ( element->isarray ){ result = (float) element->value; @@ -862,7 +869,7 @@ int hid_parse_single_byte( unsigned char current_byte, struct hid_parsing_byte * nextVal = ( current_byte << pbyte->bitIndex ); pbyte->bitIndex += pbyte->remainingBits; pbyte->remainingBits = 0; - } else { + } else { // use a partial byte: bitMask = BITMASK1( currentBitsize ); nextVal = bitMask & current_byte; @@ -884,16 +891,16 @@ int hid_parse_single_byte( unsigned char current_byte, struct hid_parsing_byte * return -1; } -int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){ +int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){ -#ifdef APPLE +#ifdef APPLE return hid_parse_input_elements_values( buf, devdesc ); #endif #ifdef WIN32 return hid_parse_input_elements_values( buf, size, devdesc ); #endif #ifdef LINUX_FREEBSD - struct hid_parsing_byte pbyte; + struct hid_parsing_byte pbyte; pbyte.nextVal = 0; pbyte.currentSize = 10; pbyte.bitIndex = 0; @@ -906,7 +913,7 @@ int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * int i; int starti = 0; int reportid = 0; - + if ( devdesc->number_of_reports > 1 ){ reportid = (int) buf[i]; starti = 1; @@ -954,11 +961,11 @@ int hid_send_output_report( struct hid_dev_desc * devd, int reportid ){ break; } } - + size_t buflength = devd->report_lengths[ index ] / 8; #ifdef DEBUG_PARSER printf("report id %i, buflength %i\t", reportid, buflength ); -#endif +#endif // if ( reportid != 0 ){ buflength++; // one more byte if report id is not 0 @@ -966,17 +973,17 @@ int hid_send_output_report( struct hid_dev_desc * devd, int reportid ){ buf = (char *) malloc( sizeof( char ) * buflength ); memset(buf, 0x0, sizeof(char) * buflength); - + // iterate over elements, find which ones are output elements with the right report id, // and set their output values to the buffer - + struct hid_device_collection * device_collection = devd->device_collection; struct hid_device_element * cur_element = device_collection->first_element; if ( cur_element->io_type != 2 || ( cur_element->report_id != reportid ) ){ cur_element = hid_get_next_output_element_with_reportid(cur_element, reportid); } - + #ifdef DEBUG_PARSER printf("-----------------------\n"); #endif @@ -985,7 +992,7 @@ int hid_send_output_report( struct hid_dev_desc * devd, int reportid ){ int byte_index = 1; int bit_offset = 0; int next_val = 0; - + while ( cur_element != NULL && (byte_index < buflength) ){ int current_output = 0; @@ -1020,7 +1027,7 @@ int hid_send_output_report( struct hid_dev_desc * devd, int reportid ){ #ifdef DEBUG_PARSER printf("-----------------------\n"); #endif - + int res = hid_write(devd->device, (const unsigned char*)buf, buflength); @@ -1039,11 +1046,11 @@ int hid_send_output_report_old( struct hid_dev_desc * devd, int reportid ){ break; } } - + size_t buflength = devd->report_lengths[ index ] / 8; #ifdef DEBUG_PARSER printf("report id %i, buflength %i\t", reportid, buflength ); -#endif +#endif if ( reportid != 0 ){ buflength++; // one more byte if report id is not 0 @@ -1053,7 +1060,7 @@ int hid_send_output_report_old( struct hid_dev_desc * devd, int reportid ){ // iterate over elements, find which ones are output elements with the right report id, // and set their output values to the buffer - + int next_byte_size; int next_mod_bit_size; int byte_count = 0; @@ -1068,8 +1075,8 @@ int hid_send_output_report_old( struct hid_dev_desc * devd, int reportid ){ #ifdef DEBUG_PARSER printf("report_size %i, bytesize %i, bitsize %i \t", cur_element->report_size, next_byte_size, next_mod_bit_size ); -#endif - +#endif + #ifdef DEBUG_PARSER printf("-----------------------\n"); #endif @@ -1080,16 +1087,16 @@ int hid_send_output_report_old( struct hid_dev_desc * devd, int reportid ){ curbyte = (unsigned char) cur_element->value; #ifdef DEBUG_PARSER printf("element page %i, usage %i, index %i, value %i, report_size %i, curbyte %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->report_size, curbyte ); -#endif +#endif cur_element = hid_get_next_output_element_with_reportid( cur_element, reportid ); - next_byte_size = cur_element->report_size/8; + next_byte_size = cur_element->report_size/8; } else if ( cur_element->report_size == 16 ){ int shift = byte_count*8; curbyte = (unsigned char) (cur_element->value >> shift); byte_count++; #ifdef DEBUG_PARSER printf("element page %i, usage %i, index %i, value %i, report_size %i, curbyte %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->report_size, curbyte ); -#endif +#endif if ( byte_count == next_byte_size ){ cur_element = hid_get_next_output_element_with_reportid( cur_element, reportid ); next_byte_size = cur_element->report_size/8; @@ -1105,17 +1112,17 @@ int hid_send_output_report_old( struct hid_dev_desc * devd, int reportid ){ bitindex += cur_element->report_size; #ifdef DEBUG_PARSER printf("element page %i, usage %i, index %i, value %i, report_size %i, curbyte %i\n", cur_element->usage_page, cur_element->usage, cur_element->index, cur_element->value, cur_element->report_size, curbyte ); -#endif +#endif cur_element = hid_get_next_output_element_with_reportid( cur_element, reportid ); next_byte_size = cur_element->report_size/8; - } + } } buf[ i ] = curbyte; } #ifdef DEBUG_PARSER printf("-----------------------\n"); #endif - + int res = hid_write(devd->device, (const unsigned char*)buf, buflength); @@ -1159,14 +1166,14 @@ struct hid_dev_desc * hid_open_device_path( const char *path, unsigned short ven hid_device * handle = hid_open_path( path ); if (!handle){ return NULL; - } + } struct hid_dev_desc * newdesc = hid_read_descriptor( handle ); if ( newdesc == NULL ){ hid_close( handle ); return NULL; } struct hid_device_info * newinfo = hid_enumerate(vendor,product); - //newdesc->device = handle; + //newdesc->device = handle; int havenotfound = strcmp(path, newinfo->path) != 0; while (havenotfound && (newinfo != NULL) ){ newinfo = newinfo->next; @@ -1174,7 +1181,7 @@ struct hid_dev_desc * hid_open_device_path( const char *path, unsigned short ven } if ( newinfo == NULL ){ hid_close( handle ); - return NULL; + return NULL; } newdesc->info = newinfo; @@ -1190,7 +1197,7 @@ struct hid_dev_desc * hid_open_device( unsigned short vendor, unsigned short pr hid_device * handle = hid_open( vendor, product, serial_number ); if (!handle){ return NULL; - } + } struct hid_dev_desc * newdesc = hid_read_descriptor( handle ); if ( newdesc == NULL ){ hid_close( handle ); @@ -1202,11 +1209,11 @@ struct hid_dev_desc * hid_open_device( unsigned short vendor, unsigned short pr // int havenotfound = wcscmp(serial_number, newinfo->serial_number) == 0; // while (havenotfound && (newinfo != NULL) ){ // newinfo = newinfo->next; -// havenotfound = wcscmp(serial_number, newinfo->serial_number) == 0; +// havenotfound = wcscmp(serial_number, newinfo->serial_number) == 0; // } if ( newinfo == NULL ){ hid_close( handle ); - return NULL; + return NULL; } newdesc->info = newinfo; @@ -1222,14 +1229,14 @@ void hid_close_device( struct hid_dev_desc * devdesc ){ hid_free_enumeration( devdesc->info ); hid_free_collection( devdesc->device_collection ); free( devdesc->report_ids ); - free( devdesc->report_lengths ); + free( devdesc->report_lengths ); // hid_free_descriptor( devdesc->descriptor ); - //TODO: more memory freeing? + //TODO: more memory freeing? } void hid_element_set_output_value( struct hid_dev_desc * devdesc, struct hid_device_element * element, int value ){ element->value = value; -#ifdef APPLE +#ifdef APPLE hid_send_element_output( devdesc, element ); #endif #ifdef WIN32 @@ -1313,7 +1320,7 @@ static struct hid_device_element *duplicate_element_with_new_usage(struct hid_de static void fill_element_from_button_caps(PHIDP_BUTTON_CAPS pCaps, struct hid_device_element *element) -{ +{ USHORT bitField = pCaps->BitField; element->usage_page = pCaps->UsagePage; element->type = bitField & 0xf; @@ -1323,14 +1330,14 @@ static void fill_element_from_button_caps(PHIDP_BUTTON_CAPS pCaps, struct hid_de element->isrelative = pCaps->IsAbsolute ? 0 : 1; element->isvariable = ((bitField & HID_ITEM_CONSTANT) == 0); element->report_id = pCaps->ReportID; - element->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; + element->report_size = pCaps->Range.UsageMax - pCaps->Range.UsageMin + 1; element->report_index = 1; // TODO: not sure about this one. The API does not seem to provide this. Perhaps set to 1? } static void fill_element_from_value_caps(PHIDP_VALUE_CAPS pCaps, struct hid_device_element *element) -{ +{ USHORT bitField = pCaps->BitField; element->usage_page = pCaps->UsagePage; element->type = bitField & 0xf; @@ -1348,7 +1355,7 @@ static void fill_element_from_value_caps(PHIDP_VALUE_CAPS pCaps, struct hid_devi element->report_index = pCaps->ReportCount; } -static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid_device_collection **ppcollections, struct hid_device_collection *pdevice_collection, +static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid_device_collection **ppcollections, struct hid_device_collection *pdevice_collection, const PHIDP_PREPARSED_DATA pp_data, const PHIDP_CAPS caps, int report_type, BOOL is_button, int *index) { int i, j; @@ -1401,7 +1408,7 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid else{ new_element->usage = pCaps->NotRange.Usage; #ifdef DEBUG_PARSER - debug_element(new_element); + debug_element(new_element); #endif } } @@ -1428,7 +1435,7 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid // Connect to previous element plast_element = new_element; // Add element to collections, and fill element values - PHIDP_VALUE_CAPS pCaps = &pValueCaps[i]; + PHIDP_VALUE_CAPS pCaps = &pValueCaps[i]; add_element_to_collection(pdevice_collection, new_element); add_element_to_collection(ppcollections[pCaps->LinkCollection], new_element); new_element->io_type = report_type; @@ -1437,7 +1444,7 @@ static int hid_parse_caps(struct hid_device_element **pplast_element, struct hid if (pCaps->IsRange){ // If it is a range, we copy the element, and update the usage. We want to have an element per usage. - new_element->usage = pCaps->Range.UsageMin; + new_element->usage = pCaps->Range.UsageMin; debug_element(new_element); for (j = pCaps->Range.UsageMin + 1; j <= pCaps->Range.UsageMax; j++){ new_element = duplicate_element_with_new_usage(plast_element, j, pdevice_collection, index); @@ -1533,7 +1540,7 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de devdesc->_element_callback(cur_element, devdesc->_element_data); } } - else if (res == HIDP_STATUS_USAGE_NOT_FOUND){ + else if (res == HIDP_STATUS_USAGE_NOT_FOUND){ // Then see if we can find the element's page and usage in the buttons that are set to on, if not, it is implicitly 0 new_value = 0; for (i = 0; i < usage_and_page_length; i++){ @@ -1550,7 +1557,7 @@ int hid_parse_input_elements_values( unsigned char* buf, int size, struct hid_de #endif devdesc->_element_callback(cur_element, devdesc->_element_data); } - } + } } cur_element = hid_get_next_input_element(cur_element); } @@ -1562,7 +1569,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ int i, j; hid_device * dev = devdesc->device; - + struct hid_device_collection * device_collection = hid_new_collection(); devdesc->device_collection = device_collection; @@ -1578,7 +1585,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ report_lengths[0] = 0; // To keep track of indices - int new_index = 0; + int new_index = 0; int numColls = 0; @@ -1595,7 +1602,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ //register_error(dev, "CreateFile"); // TODO: not sure what to do here return; - } + } /* Get the Usage Page and Usage for this device. */ BOOLEAN res = HidD_GetPreparsedData(dev_handle, &pp_data); @@ -1625,9 +1632,9 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ if (nt_res != HIDP_STATUS_SUCCESS){ // TODO: what to do here? return; - } - - // Create the N collections, and put them in an array, so that we can efficiently construct the pointers to each other using the Windows API + } + + // Create the N collections, and put them in an array, so that we can efficiently construct the pointers to each other using the Windows API for (i = 0; i < numColls; i++){ collections[i] = hid_new_collection(); } @@ -1636,7 +1643,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ for (i = 0; i < numColls; i++){ PHIDP_LINK_COLLECTION_NODE p_collection = &linkCollectionNodes[i]; // Documentation says that if parent is 0, then there is no parent, but then how do you indicate that the parent is at index 0??? - // I think that is wrong, and 0 indicates that the parent is the collection at index + // I think that is wrong, and 0 indicates that the parent is the collection at index // I will assume that the collection at index 0 is always the outermost one if (i == 0){ device_collection->first_collection = collections[i]; @@ -1677,12 +1684,12 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ){ /* Reports */ // Perhaps look at this (from MSDN): The XxxReportByteLength members of a HID collection's HIDP_CAPS structure specify the required size of input, output, and feature reports - // On Windows it is not clear that knowing the report size is important at this point, since we get it implicitly on the read size. It's quite likely that the calculation done here + // On Windows it is not clear that knowing the report size is important at this point, since we get it implicitly on the read size. It's quite likely that the calculation done here // is not right, but it does not affect (should revisit later) struct hid_device_element *element = device_collection->first_element; while (element != NULL){ int report_id = element->report_id; - int report_size = element->report_size; + int report_size = element->report_size; int report_count = element->report_index; // TODO: report_count is not used???? int reportexists = 0; @@ -1737,16 +1744,16 @@ int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_el // get the logical mix/max for this LED element CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef ); - CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef ); + CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef ); // calculate the range CFIndex modCFIndex = maxCFIndex - minCFIndex + 1; // compute the value for this LED element CFIndex tCFIndex = minCFIndex + ( element->value % modCFIndex ); uint64_t timestamp = 0; // create the IO HID Value to be sent - + IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex ); - + if ( tIOHIDValueRef ) { tIOReturn = IOHIDDeviceSetValue( device_handle, tIOHIDElementRef, tIOHIDValueRef ); CFRelease( tIOHIDValueRef ); @@ -1757,23 +1764,23 @@ int hid_send_element_output( struct hid_dev_desc * devdesc, struct hid_device_el return -1; } -// int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){ +// int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * devdesc ){ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * devdesc ){ struct hid_device_collection * device_collection = devdesc->device_collection; struct hid_device_element * cur_element = device_collection->first_element; int i=0; int newvalue; int reportid = 0; - + IOHIDDeviceRef device_handle = get_device_handle( devdesc->device ); IOHIDValueRef newValueRef; IOReturn tIOReturn; - + /* if ( devdesc->number_of_reports > 1 ){ reportid = (int) buf[i]; } - + if ( cur_element->io_type != 1 || ( cur_element->report_id != reportid ) ){ cur_element = hid_get_next_input_element_with_reportid(cur_element, reportid ); } @@ -1804,7 +1811,7 @@ int hid_parse_input_elements_values( unsigned char* buf, struct hid_dev_desc * d // printf( "cur_element %i\n", cur_element ); } // printf( "======== end of report\n"); - return 0; + return 0; } /* @@ -1847,7 +1854,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ) IOHIDElementType tIOHIDElementType = IOHIDElementGetType(tIOHIDElementRef); uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef); uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef); - + if ( tIOHIDElementType == kIOHIDElementTypeCollection ){ //TODO: COULD ALSO READ WHICH KIND OF COLLECTION struct hid_device_collection * new_collection = hid_new_collection(); @@ -1892,7 +1899,7 @@ void hid_parse_element_info( struct hid_dev_desc * devdesc ) Boolean hasPreferredState = IOHIDElementHasPreferredState(tIOHIDElementRef); // ["NoNullPosition", "NullState"], Boolean hasNullState = IOHIDElementHasNullState(tIOHIDElementRef); - int type = 0; + int type = 0; new_element->type = 0; type = (int) isVirtual; new_element->isvariable = (int) !isVirtual; diff --git a/windows/hid.c b/windows/hid.c index 7f4fbf84..9290f58d 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -8,7 +8,7 @@ 8/22/2009 Copyright 2009, 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 @@ -21,8 +21,12 @@ ********************************************************/ #include -#include +#ifdef __MINGW32__ +#include "./hidsdi.h" +#else +#include +#endif #ifndef _NTDEF_ typedef LONG NTSTATUS; @@ -59,6 +63,7 @@ extern "C" { #include "hidapi.h" + #ifdef _MSC_VER /* Thanks Microsoft, but I know how to use strncpy(). */ #pragma warning(disable:4996) @@ -118,7 +123,7 @@ static void register_error(hid_device *device, const char *op) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPVOID)&msg, 0/*sz*/, NULL); - + /* Get rid of the CR and LF that FormatMessage() sticks at the end of the message. Thanks Microsoft! */ ptr = msg; @@ -191,9 +196,9 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - + /* Iterate over each device in the HID class, looking for the right one. */ - + for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; @@ -204,7 +209,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor &InterfaceClassGuid, device_index, &device_interface_data); - + if (!res) { /* A return of FALSE from this function means that there are no more devices. */ @@ -276,7 +281,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; - } + } /* Get the Vendor ID and Product ID for this device. */ @@ -320,7 +325,7 @@ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned shor HidD_FreePreparsedData(pp_data); } - + /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; @@ -420,7 +425,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; - + devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { @@ -446,7 +451,7 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi } hid_free_enumeration(devs); - + return handle; } @@ -490,7 +495,7 @@ HID_API_EXPORT hid_device* HID_API_CALL hid_open_path(const char *path) nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res != HIDP_STATUS_SUCCESS) { - register_error(dev, "HidP_GetCaps"); + register_error(dev, "HidP_GetCaps"); goto err_pp_data; } dev->output_report_length = caps.OutputReportByteLength; @@ -503,7 +508,7 @@ HID_API_EXPORT hid_device* HID_API_CALL hid_open_path(const char *path) err_pp_data: HidD_FreePreparsedData(pp_data); -err: +err: free_hid_device(dev); return NULL; } @@ -542,7 +547,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char * } res = WriteFile(dev->device_handle, buf, length, NULL, &ol); - + if (!res) { if (GetLastError() != ERROR_IO_PENDING) { /* WriteFile() failed. Return error. */ @@ -585,7 +590,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char memset(dev->read_buf, 0, dev->input_report_length); ResetEvent(ev); res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol); - + if (!res) { DWORD er = GetLastError(); if (GetLastError() != ERROR_IO_PENDING) { @@ -612,7 +617,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char we are in non-blocking mode. Get the number of bytes read. The actual data has been copied to the data[] array which was passed to ReadFile(). */ res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); - + /* Set pending back to false, even if GetOverlappedResult() returned error. */ dev->read_pending = FALSE; @@ -621,13 +626,13 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char copy_len = length > bytes_read ? bytes_read : length; memcpy(data, dev->read_buf, copy_len); } - + end_of_function: if (!res) { register_error(dev, "GetOverlappedResult"); return -1; } - + return copy_len; } @@ -782,7 +787,7 @@ HANDLE HID_API_EXPORT get_device_handle(hid_device *dev){ /*#define PICPGM*/ /*#define S11*/ #define P32 -#ifdef S11 +#ifdef S11 unsigned short VendorID = 0xa0a0; unsigned short ProductID = 0x0001; #endif @@ -812,7 +817,7 @@ int __cdecl main(int argc, char* argv[]) memset(buf,0x00,sizeof(buf)); buf[0] = 0; buf[1] = 0x81; - + /* Open the device. */ int handle = open(VendorID, ProductID, L"12345"); From 71627a698681a876e8f47a7e73f3c0c14faf8356 Mon Sep 17 00:00:00 2001 From: bagong Date: Wed, 25 May 2016 21:05:55 +0200 Subject: [PATCH 17/29] Win: generalize linked setupapi --- windows/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 9d551598..5129ea97 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -2,4 +2,4 @@ message(STATUS " Windows" ) include_directories( ${hidapi_SOURCE_DIR}/hidapi/ ) add_library( hidapi STATIC hid.c ) -target_link_libraries( hidapi setupapi.lib ) +target_link_libraries( hidapi setupapi ) From fea827f565a18e6619b65b3d11379c630ae08433 Mon Sep 17 00:00:00 2001 From: bagong Date: Wed, 25 May 2016 21:06:48 +0200 Subject: [PATCH 18/29] Cross: install hut folder --- CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cd6768e..564b16c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ option(HID_DEBUG_PARSER "verbose parser debugging output" OFF) option(HID_EXAMPLE_TEST "build test example" OFF) option(HID_EXAMPLE_OSC "build osc example" OFF) -option(HID_INSTALL_HUT "install hid usage tables" OFF) +option(HID_INSTALL_HUT "install hid usage tables" ON) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(HIDAPI "default" CACHE STRING "HID API to use (one of {default,hidraw,libusb})") @@ -109,11 +109,10 @@ if( HID_EXAMPLE_OSC ) add_subdirectory(hidapi2osc) endif() -if( HID_DEBUG_PARSER ) - set(HID_HUT_PATH ${CMAKE_INSTALL_PREFIX}/share/hidapi CACHE STRING "Installation path for the HID usage tables") - +if( HID_DEBUG_PARSER OR HID_INSTALL_HUT ) + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/hidapi" CACHE STRING "Installation path for the HID usage tables") install(DIRECTORY hut - DESTINATION ${HID_HUT_PATH} - FILES_MATCHING PATTERN "*.yaml" + DESTINATION ${HID_HUT_PATH} + FILES_MATCHING PATTERN "*.yaml" ) endif() From 3d963f9ebbe6d840d99f7494d3ef553e590ff227 Mon Sep 17 00:00:00 2001 From: bagong Date: Wed, 25 May 2016 21:34:00 +0200 Subject: [PATCH 19/29] Cross: change hidapi folder to HID_Support --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 564b16c3..08f61859 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ if( HID_EXAMPLE_OSC ) endif() if( HID_DEBUG_PARSER OR HID_INSTALL_HUT ) - set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/hidapi" CACHE STRING "Installation path for the HID usage tables") + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/HID_Support" CACHE STRING "Installation path for the HID usage tables") install(DIRECTORY hut DESTINATION ${HID_HUT_PATH} FILES_MATCHING PATTERN "*.yaml" From 2f599f29153471be5b2b328fec598140743a0f32 Mon Sep 17 00:00:00 2001 From: bagong Date: Wed, 25 May 2016 23:21:03 +0200 Subject: [PATCH 20/29] Mac: install hut tables into app-bundle --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08f61859..94ae1db1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,11 @@ if( HID_EXAMPLE_OSC ) endif() if( HID_DEBUG_PARSER OR HID_INSTALL_HUT ) - set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/HID_Support" CACHE STRING "Installation path for the HID usage tables") + if(APPLE) + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${scappauxresourcesdir}/HID_Support" CACHE STRING "Installation path for the HID usage tables") + else(APPLE) + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/HID_Support" CACHE STRING "Installation path for the HID usage tables") + endif(APPLE) install(DIRECTORY hut DESTINATION ${HID_HUT_PATH} FILES_MATCHING PATTERN "*.yaml" From b11c66a6cc6ef4d67af8566adc66cb573f6ad03b Mon Sep 17 00:00:00 2001 From: bagong Date: Thu, 2 Jun 2016 19:54:31 +0200 Subject: [PATCH 21/29] Provisional fix for install of HUT folder The install should be defined within SC, and not within the submodule, to allow variables like auxresourcesdir to be used without reassigning them --- CMakeLists.txt | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94ae1db1..cceff089 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,10 +110,25 @@ if( HID_EXAMPLE_OSC ) endif() if( HID_DEBUG_PARSER OR HID_INSTALL_HUT ) + # provisional to avoid having to commit to sc master while the HID submodule + # is not final/added to master + # the sc-settings for cmake_install_prefix and scappauxresourcesdir are not + # visible in this scope if(APPLE) - set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${scappauxresourcesdir}/HID_Support" CACHE STRING "Installation path for the HID usage tables") - else(APPLE) - set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/HID_Support" CACHE STRING "Installation path for the HID usage tables") + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + SET(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/Install") + endif() + # this will break if scappbundlename is reassigned in SC + # similar problem in editors/sc-ide/CMakeLists.txt 284 + set(scappbundlename "SuperCollider") + set(scappauxresourcesdir "${scappbundlename}/${scappbundlename}.app/Contents/Resources") + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${scappauxresourcesdir}/HID_Support") + elseif(WIN32) + set(auxresourcesdir "SuperCollider" CACHE STRING "Resources directory") + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/HID_Support") + else() + set(auxresourcesdir "share/SuperCollider" CACHE STRING "Resources directory") + set(HID_HUT_PATH "${CMAKE_INSTALL_PREFIX}/${auxresourcesdir}/HID_Support") endif(APPLE) install(DIRECTORY hut DESTINATION ${HID_HUT_PATH} From c365a409382ecc266d2f0ba12b05c1b639b9eff5 Mon Sep 17 00:00:00 2001 From: bagong Date: Thu, 15 Sep 2016 15:14:34 +0200 Subject: [PATCH 22/29] Remove duplicate line regarding cmp0048 --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cceff089..377d8d2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ if(${CMAKE_MAJOR_VERSION} GREATER 2) cmake_policy(SET CMP0048 OLD) endif(${CMAKE_MAJOR_VERSION} GREATER 2) -cmake_policy(SET CMP0048 OLD) project(hidapi) set(VERSION_MAJOR "0") From ce7b972ae4d3b5913b5946587168e5113cec7523 Mon Sep 17 00:00:00 2001 From: James McKernon Date: Sun, 2 Oct 2016 14:20:40 +0100 Subject: [PATCH 23/29] Fix counter bug in hid_parse_input_report() Initialize the counter variable i to zero in hid_parse_input_report(), fixing a bug whereby a segfault can happen when the function is entered more than once. --- hidapi_parser/hidapi_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 38ff3bbe..e400bc31 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -910,7 +910,7 @@ int hid_parse_input_report( unsigned char* buf, int size, struct hid_dev_desc * struct hid_device_collection * device_collection = devdesc->device_collection; struct hid_device_element * cur_element = device_collection->first_element; int newvalue; - int i; + int i = 0; int starti = 0; int reportid = 0; From 38d3d660cde09348fdfb1bc9909a7e045dad9d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rainer=20Sch=C3=BCtz?= Date: Fri, 21 Oct 2016 20:30:18 +0200 Subject: [PATCH 24/29] Include windows.h to fix MinGW32 build, thanks sonoro1234 tested in mingw- and VS-build --- hidapi/hidapi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hidapi/hidapi.h b/hidapi/hidapi.h index f6d6663d..5e70cf3c 100644 --- a/hidapi/hidapi.h +++ b/hidapi/hidapi.h @@ -430,6 +430,7 @@ extern "C" { IOHIDDeviceRef HID_API_EXPORT HID_API_CALL get_device_handle( hid_device *dev ); #endif #ifdef WIN32 + #include HANDLE HID_API_EXPORT HID_API_CALL get_device_handle(hid_device *dev); #endif From 4baeac8a6e30b3dc37e871ed3c8a69895a48440a Mon Sep 17 00:00:00 2001 From: Kyrill Briantsev Date: Wed, 9 Nov 2016 13:40:00 +0300 Subject: [PATCH 25/29] Build hidapi against latest mingw-w64 headers (not guarded, perhaps breaks old headers build). --- hidapi_parser/hidapi_parser.c | 4 ---- windows/hid.c | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index e400bc31..932e456c 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -29,12 +29,8 @@ #ifdef _WIN32 #include -#ifdef __MINGW32__ -#include "../windows/hidsdi.h" -#else #include #endif -#endif #include "hidapi_parser.h" diff --git a/windows/hid.c b/windows/hid.c index 9290f58d..9b9b65e9 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -21,12 +21,7 @@ ********************************************************/ #include - -#ifdef __MINGW32__ -#include "./hidsdi.h" -#else #include -#endif #ifndef _NTDEF_ typedef LONG NTSTATUS; @@ -35,6 +30,7 @@ typedef LONG NTSTATUS; #ifdef __MINGW32__ #include #include +#include #endif #ifdef __CYGWIN__ From 23ab8e241a328dcde5b4eb0b019aeeec03d891e3 Mon Sep 17 00:00:00 2001 From: bagong Date: Mon, 6 Feb 2017 15:33:59 +0100 Subject: [PATCH 26/29] Add comment to switch to global hidsdi.h --- hidapi_parser/hidapi_parser.c | 3 +++ windows/hid.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/hidapi_parser/hidapi_parser.c b/hidapi_parser/hidapi_parser.c index 932e456c..32f9ca12 100644 --- a/hidapi_parser/hidapi_parser.c +++ b/hidapi_parser/hidapi_parser.c @@ -29,6 +29,9 @@ #ifdef _WIN32 #include +// for MinGW < 5.3 include locally provided "../windows hidsdi.h" rather +// than #include : +// #include "../windows/hidsdi.h" #include #endif diff --git a/windows/hid.c b/windows/hid.c index 9b9b65e9..fef1fc83 100755 --- a/windows/hid.c +++ b/windows/hid.c @@ -21,6 +21,9 @@ ********************************************************/ #include +// for MinGW < 5.3 include locally provided "../windows hidsdi.h" rather +// than #include : +// #include "./hidsdi.h" #include #ifndef _NTDEF_ From 0f074b9726075c29be2ee76bac42b287b7417ef2 Mon Sep 17 00:00:00 2001 From: Vasily Postnicov Date: Mon, 10 Apr 2017 07:42:34 +0300 Subject: [PATCH 27/29] Fix Findlibusb cmake module for working on FreeBSD --- cmake_modules/Findlibusb-1.0.cmake | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cmake_modules/Findlibusb-1.0.cmake b/cmake_modules/Findlibusb-1.0.cmake index 405ed516..1ae933dd 100644 --- a/cmake_modules/Findlibusb-1.0.cmake +++ b/cmake_modules/Findlibusb-1.0.cmake @@ -43,13 +43,25 @@ # +if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # Remove prefix "1" as FreeBSD has its own implementation + # of libusb compatible with libusb1. + set(LIBUSB_1_HEADER_NAME "libusb.h") + set(LIBUSB_1_LIBRARY_NAME "usb") +else(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # Just preserve values before my intrusion. 10.04.2017 Vasily + # Can it be just "libusb.h" for Linux also? + set(LIBUSB_1_HEADER_NAME "libusb-1.0/libusb.h") + set(LIBUSB_1_LIBRARY_NAME "usb-1.0") +endif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) # in cache already set(LIBUSB_FOUND TRUE) else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) find_path(LIBUSB_1_INCLUDE_DIR NAMES - libusb-1.0/libusb.h + ${LIBUSB_1_HEADER_NAME} PATHS /usr/include /usr/local/include @@ -61,7 +73,7 @@ else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS) find_library(LIBUSB_1_LIBRARY NAMES - usb-1.0 + ${LIBUSB_1_LIBRARY_NAME} PATHS /usr/lib /usr/local/lib From 78fdae41853a6e7a7c2f16c15693d95f5b460601 Mon Sep 17 00:00:00 2001 From: Brian Heim Date: Mon, 9 Apr 2018 19:03:08 -0400 Subject: [PATCH 28/29] cmake: bump to 3.0, use modern project() syntax --- CMakeLists.txt | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 377d8d2f..b01216f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,6 @@ -cmake_minimum_required(VERSION 2.8) -if(${CMAKE_MAJOR_VERSION} GREATER 2) - cmake_policy(SET CMP0048 OLD) -endif(${CMAKE_MAJOR_VERSION} GREATER 2) - -project(hidapi) - -set(VERSION_MAJOR "0") -set(VERSION_MINOR "7") -set(VERSION_PATCH "1") -set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}") +cmake_minimum_required(VERSION 3.0) +project(hidapi VERSION 0.7.1) option(HID_DEBUG_PARSER "verbose parser debugging output" OFF) From cc8e711f7d28aa83b96ec1c71ae83f151cd46874 Mon Sep 17 00:00:00 2001 From: gurk Date: Wed, 1 Jul 2020 03:50:41 +0100 Subject: [PATCH 29/29] Undo "fix hidapi enumeration bug on OSX" - commit c43255b Caused issues by processing run loop at undesirable moments. --- mac/hid.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/mac/hid.c b/mac/hid.c index 8240f223..439337cd 100644 --- a/mac/hid.c +++ b/mac/hid.c @@ -411,13 +411,6 @@ int HID_API_EXPORT hid_exit(void) return 0; } -static void process_pending_events(void) { - SInt32 res; - do { - res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); - } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); -} - struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct hid_device_info *root = NULL; /* return object */ @@ -429,9 +422,6 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, if (hid_init() < 0) return NULL; - /* give the IOHIDManager a chance to update itself */ - process_pending_events(); - /* Get a list of the Devices */ IOHIDManagerSetDeviceMatching(hid_mgr, NULL); CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); @@ -707,9 +697,6 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path) if (hid_init() < 0) return NULL; - /* give the IOHIDManager a chance to update itself */ - process_pending_events(); - CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); num_devices = CFSetGetCount(device_set);