| { | ||
| "git": { | ||
| "sha1": "d74ecdb5d9d9834428a6552d24d1e66929a33c65" | ||
| }, | ||
| "path_in_vcs": "" | ||
| } |
+1
-1
@@ -13,3 +13,3 @@ # This file is automatically @generated by Cargo. | ||
| name = "hidapi" | ||
| version = "1.3.1" | ||
| version = "1.3.2" | ||
| dependencies = [ | ||
@@ -16,0 +16,0 @@ "cc", |
+1
-1
@@ -14,3 +14,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "hidapi" | ||
| version = "1.3.1" | ||
| version = "1.3.2" | ||
| authors = ["Roland Ruckerbauer <roland.rucky@gmail.com>", "Osspial <osspial@gmail.com>", "Artyom Pavlov <newpavlov@gmail.com>", "mberndt123", "niklasad1"] | ||
@@ -17,0 +17,0 @@ build = "build.rs" |
@@ -182,2 +182,8 @@ # Building HIDAPI using CMake | ||
| <details> | ||
| <summary>NOTE</summary> | ||
| If you project happen to use `BUILD_SHARED_LIBS` as a `CACHE` variable globally for you project, setting it as simple variable, as showed above _will have not affect_ up until _CMake 3.13_. See [CMP0077](https://cmake.org/cmake/help/latest/policy/CMP0077.html) for details. | ||
| </details><br> | ||
| There are several important differences in the behavior of HIDAPI CMake build system when CMake is built as standalone package vs subdirectory build: | ||
@@ -184,0 +190,0 @@ |
@@ -56,3 +56,3 @@ /******************************************************* | ||
| */ | ||
| #define HID_API_VERSION_PATCH 0 | ||
| #define HID_API_VERSION_PATCH 2 | ||
@@ -59,0 +59,0 @@ /* Helper macros */ |
@@ -926,3 +926,2 @@ /******************************************************* | ||
| if (res < 0) { | ||
| libusb_close(dev->device_handle); | ||
| LOG("Unable to detach Kernel Driver\n"); | ||
@@ -929,0 +928,0 @@ return 0; |
@@ -65,2 +65,9 @@ /******************************************************* | ||
| // HIDIOCGINPUT is not defined in Linux kernel headers < 5.11. | ||
| // This definition is from hidraw.h in Linux >= 5.11. | ||
| // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f43d3870cafa2a0f3854c1819c8385733db8f9ae | ||
| #ifndef HIDIOCGINPUT | ||
| #define HIDIOCGINPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0A, len) | ||
| #endif | ||
| /* USB HID device property names */ | ||
@@ -1069,9 +1076,11 @@ const char *device_string_names[] = { | ||
| // Not supported by Linux HidRaw yet | ||
| int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length) | ||
| { | ||
| (void)dev; | ||
| (void)data; | ||
| (void)length; | ||
| return -1; | ||
| int res; | ||
| res = ioctl(dev->device_handle, HIDIOCGINPUT(length), data); | ||
| if (res < 0) | ||
| register_device_error_format(dev, "ioctl (GINPUT): %s", strerror(errno)); | ||
| return res; | ||
| } | ||
@@ -1078,0 +1087,0 @@ |
+13
-4
@@ -23,2 +23,3 @@ ## HIDAPI library for Windows, Linux, FreeBSD and macOS | ||
| * [Test GUI](#test-gui) | ||
| * [Console Test App](#console-test-app) | ||
| * [What Does the API Look Like?](#what-does-the-api-look-like) | ||
@@ -32,3 +33,3 @@ * [License](#license) | ||
| HIDAPI has four back-ends: | ||
| ### HIDAPI has four back-ends: | ||
| * Windows (using `hid.dll`) | ||
@@ -50,3 +51,3 @@ * Linux/hidraw (using the Kernel's hidraw driver) | ||
| __Linux/hidraw__ (`linux/hid.c`): | ||
| #### __Linux/hidraw__ (`linux/hid.c`): | ||
@@ -61,3 +62,3 @@ This back-end uses the hidraw interface in the Linux kernel, and supports | ||
| __Linux/FreeBSD/libusb__ (`libusb/hid.c`): | ||
| #### __Linux/FreeBSD/libusb__ (`libusb/hid.c`): | ||
@@ -72,3 +73,3 @@ This back-end uses libusb-1.0 to communicate directly to a USB device. This | ||
| which HIDAPI supports. Since it relies on a 3rd party library, building it | ||
| is optional but recommended because it is so useful when debugging hardware. | ||
| is optional but it is useful when debugging hardware. | ||
@@ -82,2 +83,10 @@ NOTE: Test GUI based on Fox Toolkit is not actively developed nor supported | ||
| ### Console Test App | ||
| If you want to play around with your HID device before starting | ||
| any development with HIDAPI and using a GUI app is not an option for you, you may try [`hidapitester`](https://github.com/todbot/hidapitester). | ||
| This app has a console interface for most of the features supported | ||
| by HIDAPI library. | ||
| ## What Does the API Look Like? | ||
@@ -84,0 +93,0 @@ |
@@ -1,1 +0,1 @@ | ||
| 0.11.0 | ||
| 0.11.2 |
+78
-62
@@ -36,2 +36,3 @@ /******************************************************* | ||
| #ifdef __MINGW32__ | ||
| #include <devpropdef.h> | ||
| #include <ntdef.h> | ||
@@ -225,3 +226,3 @@ #include <winbase.h> | ||
| free(dev->read_buf); | ||
| free(dev->device_info); | ||
| hid_free_enumeration(dev->device_info); | ||
| free(dev); | ||
@@ -416,6 +417,31 @@ } | ||
| /* USB Device Interface Number. | ||
| It can be parsed out of the Hardware ID if a USB device is has multiple interfaces (composite device). | ||
| See https://docs.microsoft.com/windows-hardware/drivers/hid/hidclass-hardware-ids-for-top-level-collections | ||
| and https://docs.microsoft.com/windows-hardware/drivers/install/standard-usb-identifiers | ||
| hardware_id is always expected to be uppercase. | ||
| */ | ||
| static int hid_internal_get_interface_number(const wchar_t* hardware_id) | ||
| { | ||
| int interface_number; | ||
| wchar_t *startptr, *endptr; | ||
| const wchar_t *interface_token = L"&MI_"; | ||
| startptr = wcsstr(hardware_id, interface_token); | ||
| if (!startptr) | ||
| return -1; | ||
| startptr += wcslen(interface_token); | ||
| interface_number = wcstol(startptr, &endptr, 16); | ||
| if (endptr == startptr) | ||
| return -1; | ||
| return interface_number; | ||
| } | ||
| static void hid_internal_get_info(struct hid_device_info* dev) | ||
| { | ||
| const char *tmp = NULL; | ||
| wchar_t *interface_path = NULL, *device_id = NULL, *compatible_ids = NULL; | ||
| wchar_t *interface_path = NULL, *device_id = NULL, *compatible_ids = NULL, *hardware_ids = NULL; | ||
| mbstate_t state; | ||
@@ -428,2 +454,3 @@ ULONG len; | ||
| static DEVPROPKEY DEVPKEY_Device_InstanceId = { { 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57 }, 256 }; // DEVPROP_TYPE_STRING | ||
| static DEVPROPKEY DEVPKEY_Device_HardwareIds = { { 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0}, 3 }; // DEVPROP_TYPE_STRING_LIST | ||
| static DEVPROPKEY DEVPKEY_Device_CompatibleIds = { { 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0}, 4 }; // DEVPROP_TYPE_STRING_LIST | ||
@@ -461,2 +488,23 @@ | ||
| /* Get the hardware ids from devnode */ | ||
| len = 0; | ||
| cr = CM_Get_DevNode_PropertyW(dev_node, &DEVPKEY_Device_HardwareIds, &property_type, NULL, &len, 0); | ||
| if (cr == CR_BUFFER_SMALL && property_type == DEVPROP_TYPE_STRING_LIST) { | ||
| hardware_ids = (wchar_t*)calloc(len, sizeof(BYTE)); | ||
| cr = CM_Get_DevNode_PropertyW(dev_node, &DEVPKEY_Device_HardwareIds, &property_type, (PBYTE)hardware_ids, &len, 0); | ||
| } | ||
| if (cr != CR_SUCCESS) | ||
| goto end; | ||
| // Search for interface number in hardware ids | ||
| for (wchar_t* hardware_id = hardware_ids; *hardware_id; hardware_id += wcslen(hardware_id) + 1) { | ||
| /* Normalize to upper case */ | ||
| for (wchar_t* p = hardware_id; *p; ++p) *p = towupper(*p); | ||
| dev->interface_number = hid_internal_get_interface_number(hardware_id); | ||
| if (dev->interface_number != -1) | ||
| break; | ||
| } | ||
| /* Get devnode parent */ | ||
@@ -494,2 +542,3 @@ cr = CM_Get_Parent(&dev_node, dev_node, 0); | ||
| free(device_id); | ||
| free(hardware_ids); | ||
| free(compatible_ids); | ||
@@ -565,21 +614,2 @@ } | ||
| /* Interface Number. It can sometimes be parsed out of the path | ||
| on Windows if a device has multiple interfaces. See | ||
| https://docs.microsoft.com/windows-hardware/drivers/hid/hidclass-hardware-ids-for-top-level-collections | ||
| or search for "HIDClass Hardware IDs for Top-Level Collections" at Microsoft Docs. If it's not | ||
| in the path, it's set to -1. */ | ||
| dev->interface_number = -1; | ||
| if (dev->path) { | ||
| char* interface_component = strstr(dev->path, "&mi_"); | ||
| if (interface_component) { | ||
| char* hex_str = interface_component + 4; | ||
| char* endptr = NULL; | ||
| dev->interface_number = strtol(hex_str, &endptr, 16); | ||
| if (endptr == hex_str) { | ||
| /* The parsing failed. Set interface_number to -1. */ | ||
| dev->interface_number = -1; | ||
| } | ||
| } | ||
| } | ||
| hid_internal_get_info(dev); | ||
@@ -790,19 +820,15 @@ | ||
| { | ||
| hid_device *dev; | ||
| hid_device *dev = NULL; | ||
| HANDLE device_handle = INVALID_HANDLE_VALUE; | ||
| PHIDP_PREPARSED_DATA pp_data = NULL; | ||
| HIDP_CAPS caps; | ||
| PHIDP_PREPARSED_DATA pp_data = NULL; | ||
| BOOLEAN res; | ||
| NTSTATUS nt_res; | ||
| if (hid_init() < 0) { | ||
| return NULL; | ||
| } | ||
| if (hid_init() < 0) | ||
| goto end_of_function; | ||
| dev = new_hid_device(); | ||
| /* Open a handle to the device */ | ||
| dev->device_handle = open_device(path, TRUE); | ||
| device_handle = open_device(path, TRUE); | ||
| /* Check validity of write_handle. */ | ||
| if (dev->device_handle == INVALID_HANDLE_VALUE) { | ||
| if (device_handle == INVALID_HANDLE_VALUE) { | ||
| /* System devices, such as keyboards and mice, cannot be opened in | ||
@@ -813,46 +839,36 @@ read-write mode, because the system takes exclusive control over | ||
| without read/write access. */ | ||
| dev->device_handle = open_device(path, FALSE); | ||
| device_handle = open_device(path, FALSE); | ||
| /* Check the validity of the limited device_handle. */ | ||
| if (dev->device_handle == INVALID_HANDLE_VALUE) { | ||
| /* Unable to open the device, even without read-write mode. */ | ||
| register_error(dev, "CreateFile"); | ||
| goto err; | ||
| } | ||
| if (device_handle == INVALID_HANDLE_VALUE) | ||
| goto end_of_function; | ||
| } | ||
| /* Set the Input Report buffer size to 64 reports. */ | ||
| res = HidD_SetNumInputBuffers(dev->device_handle, 64); | ||
| if (!res) { | ||
| register_error(dev, "HidD_SetNumInputBuffers"); | ||
| goto err; | ||
| } | ||
| if (!HidD_SetNumInputBuffers(device_handle, 64)) | ||
| goto end_of_function; | ||
| /* Get the Input Report length for the device. */ | ||
| res = HidD_GetPreparsedData(dev->device_handle, &pp_data); | ||
| if (!res) { | ||
| register_error(dev, "HidD_GetPreparsedData"); | ||
| goto err; | ||
| } | ||
| nt_res = HidP_GetCaps(pp_data, &caps); | ||
| if (nt_res != HIDP_STATUS_SUCCESS) { | ||
| register_error(dev, "HidP_GetCaps"); | ||
| goto err_pp_data; | ||
| } | ||
| if (!HidD_GetPreparsedData(device_handle, &pp_data)) | ||
| goto end_of_function; | ||
| if (HidP_GetCaps(pp_data, &caps) != HIDP_STATUS_SUCCESS) | ||
| goto end_of_function; | ||
| dev = new_hid_device(); | ||
| dev->device_handle = device_handle; | ||
| device_handle = INVALID_HANDLE_VALUE; | ||
| dev->output_report_length = caps.OutputReportByteLength; | ||
| dev->input_report_length = caps.InputReportByteLength; | ||
| dev->feature_report_length = caps.FeatureReportByteLength; | ||
| HidD_FreePreparsedData(pp_data); | ||
| dev->read_buf = (char*) malloc(dev->input_report_length); | ||
| dev->device_info = hid_get_device_info(path, dev->device_handle); | ||
| end_of_function: | ||
| CloseHandle(device_handle); | ||
| HidD_FreePreparsedData(pp_data); | ||
| return dev; | ||
| err_pp_data: | ||
| HidD_FreePreparsedData(pp_data); | ||
| err: | ||
| free_hid_device(dev); | ||
| return NULL; | ||
| } | ||
@@ -859,0 +875,0 @@ |
Sorry, the diff of this file is not supported yet