diff --git a/Controllers/LogitechController/LogitechG203LController.cpp b/Controllers/LogitechController/LogitechG203LController.cpp index dda8bc94..da353774 100644 --- a/Controllers/LogitechController/LogitechG203LController.cpp +++ b/Controllers/LogitechController/LogitechG203LController.cpp @@ -2,15 +2,36 @@ #include +#define PACKET_SIZE 20 + + LogitechG203LController::LogitechG203LController(hid_device* dev_handle, const char* path) { dev = dev_handle; location = path; + + // enable software control + unsigned char usb_buf[PACKET_SIZE]; + + memset(usb_buf, 0x00, PACKET_SIZE); + + usb_buf[0x00] = 0x11; + usb_buf[0x01] = 0xFF; + usb_buf[0x02] = 0x0E; + usb_buf[0x03] = 0x50; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x03; + usb_buf[0x06] = 0x07; + + SendPacket(usb_buf); } LogitechG203LController::~LogitechG203LController() { - hid_close(dev); + if(dev != nullptr) + { + hid_close(dev); + } } std::string LogitechG203LController::GetDeviceLocation() @@ -36,29 +57,28 @@ std::string LogitechG203LController::GetSerialString() void LogitechG203LController::SendApply() { - unsigned char usb_buf[20]; + unsigned char usb_buf[PACKET_SIZE]; - memset(usb_buf, 0x00, sizeof(usb_buf)); + memset(usb_buf, 0x00, PACKET_SIZE); usb_buf[0x00] = 0x11; usb_buf[0x01] = 0xFF; usb_buf[0x02] = 0x12; - usb_buf[0x03] = 0x7A; + usb_buf[0x03] = 0x70; - hid_write(dev, usb_buf, 20); - hid_read(dev, usb_buf, 20); + SendPacket(usb_buf); } void LogitechG203LController::SetSingleLED(int led, unsigned char red, unsigned char green, unsigned char blue) { - unsigned char usb_buf[20]; + unsigned char usb_buf[PACKET_SIZE]; - memset(usb_buf, 0x00, sizeof(usb_buf)); + memset(usb_buf, 0x00, PACKET_SIZE); usb_buf[0x00] = 0x11; usb_buf[0x01] = 0xFF; usb_buf[0x02] = 0x12; - usb_buf[0x03] = 0x19; + usb_buf[0x03] = 0x10; usb_buf[0x04] = (unsigned char)led; usb_buf[0x05] = red; @@ -67,8 +87,7 @@ void LogitechG203LController::SetSingleLED(int led, unsigned char red, unsigned usb_buf[0x08] = 0xFF; - hid_write(dev, usb_buf, 20); - hid_read(dev, usb_buf, 20); + SendPacket(usb_buf); SendApply(); } @@ -82,15 +101,21 @@ void LogitechG203LController::SetMode( unsigned char green, unsigned char blue) { - unsigned char usb_buf[20]; + unsigned char usb_buf[PACKET_SIZE]; + unsigned char brightness = bright * 5; - memset(usb_buf, 0x00, sizeof(usb_buf)); + if(brightness == 0) + { + brightness = 1; + } + + memset(usb_buf, 0x00, PACKET_SIZE); //Header usb_buf[0x00] = 0x11; usb_buf[0x01] = 0xFF; usb_buf[0x02] = 0x0E; - usb_buf[0x03] = 0x1A; + usb_buf[0x03] = 0x10; //Common Data usb_buf[0x04] = 0x00; usb_buf[0x05] = (unsigned char)mode; @@ -103,45 +128,44 @@ void LogitechG203LController::SetMode( { usb_buf[0x0B] = (unsigned char)((speed>>8) & 0x000000FF); usb_buf[0x0C] = (unsigned char)(speed & 0x000000FF); - usb_buf[0x0D] = bright; + usb_buf[0x0D] = brightness; } if(mode == LOGITECH_G203L_MODE_BREATHING) { usb_buf[0x09] = (unsigned char)((speed>>8) & 0x000000FF); usb_buf[0x0A] = (unsigned char)(speed & 0x000000FF); - usb_buf[0x0C] = bright; + usb_buf[0x0C] = brightness; } if(mode == LOGITECH_G203L_MODE_WAVE) { usb_buf[0x0C] = (unsigned char)(speed & 0x000000FF); usb_buf[0x0D] = dir ? 0x01 : 0x06; //0x01: Left->Right 0x06: Right->Left - usb_buf[0x0E] = bright; + usb_buf[0x0E] = brightness; usb_buf[0x0F] = (unsigned char)((speed>>8) & 0x000000FF); } if(mode == LOGITECH_G203L_MODE_COLORMIXING) { usb_buf[0x0C] = (unsigned char)(speed & 0x000000FF); usb_buf[0x0D] = (unsigned char)((speed>>8) & 0x000000FF); - usb_buf[0x0E] = bright; + usb_buf[0x0E] = brightness; } //END BYTE usb_buf[0x10] = 0x01; - hid_write(dev, usb_buf, 20); - hid_read(dev, usb_buf, 20); + SendPacket(usb_buf); } void LogitechG203LController::SetDevice(std::vector colors) { - unsigned char usb_buf[20]; + unsigned char usb_buf[PACKET_SIZE]; - memset(usb_buf, 0x00, sizeof(usb_buf)); + memset(usb_buf, 0x00, PACKET_SIZE); usb_buf[0x00] = 0x11; usb_buf[0x01] = 0xFF; usb_buf[0x02] = 0x12; - usb_buf[0x03] = 0x1A; + usb_buf[0x03] = 0x10; usb_buf[0x04] = 0x01; usb_buf[0x05] = RGBGetRValue(colors[0]); @@ -160,8 +184,30 @@ void LogitechG203LController::SetDevice(std::vector colors) usb_buf[0x10] = 0xFF; - hid_write(dev, usb_buf, 20); - hid_read(dev, usb_buf, 20); + SendPacket(usb_buf); SendApply(); } + +void LogitechG203LController::SendPacket(unsigned char* buffer) +{ + if(dev != nullptr) + { + if(hid_write(dev, buffer, PACKET_SIZE) == -1) + { + hid_close(dev); + dev = hid_open_path(location.c_str()); + return; + } + } + + if(dev != nullptr) + { + if(hid_read_timeout(dev, buffer, PACKET_SIZE, 10) <= 0) + { + hid_close(dev); + dev = hid_open_path(location.c_str()); + return; + } + } +} diff --git a/Controllers/LogitechController/LogitechG203LController.h b/Controllers/LogitechController/LogitechG203LController.h index 84dd0ab1..82fcea34 100644 --- a/Controllers/LogitechController/LogitechG203LController.h +++ b/Controllers/LogitechController/LogitechG203LController.h @@ -34,4 +34,5 @@ private: std::string location; void SendApply(); + void SendPacket(unsigned char* buffer); }; diff --git a/Controllers/LogitechController/RGBController_LogitechG203L.cpp b/Controllers/LogitechController/RGBController_LogitechG203L.cpp index dd0fec6d..4f3d53ab 100644 --- a/Controllers/LogitechController/RGBController_LogitechG203L.cpp +++ b/Controllers/LogitechController/RGBController_LogitechG203L.cpp @@ -23,62 +23,74 @@ RGBController_LogitechG203L::RGBController_LogitechG203L(LogitechG203LController serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = LOGITECH_G203L_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = LOGITECH_G203L_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Off; - Off.name = "Off"; - Off.value = LOGITECH_G203L_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; + Off.name = "Off"; + Off.value = LOGITECH_G203L_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); mode Static; - Static.name = "Static"; - Static.value = LOGITECH_G203L_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.name = "Static"; + Static.value = LOGITECH_G203L_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; Static.colors.resize(1); modes.push_back(Static); mode Cycle; - Cycle.name = "Cycle"; - Cycle.value = LOGITECH_G203L_MODE_CYCLE; - Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Cycle.color_mode = MODE_COLORS_NONE; - Cycle.speed_min = 0x4E20; - Cycle.speed_max = 0x03E8; + Cycle.name = "Cycle"; + Cycle.value = LOGITECH_G203L_MODE_CYCLE; + Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Cycle.color_mode = MODE_COLORS_NONE; + Cycle.speed_min = 0x4E20; + Cycle.speed_max = 0x03E8; + Cycle.brightness = 20; + Cycle.brightness_min = 0; + Cycle.brightness_max = 20; modes.push_back(Cycle); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = LOGITECH_G203L_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed_min = 0x4E20; - Breathing.speed_max = 0x03E8; + Breathing.name = "Breathing"; + Breathing.value = LOGITECH_G203L_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed_min = 0x4E20; + Breathing.speed_max = 0x03E8; + Breathing.brightness = 20; + Breathing.brightness_min = 0; + Breathing.brightness_max = 20; Breathing.colors.resize(1); modes.push_back(Breathing); mode Wave; - Wave.name = "Wave"; - Wave.value = LOGITECH_G203L_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; - Wave.color_mode = MODE_COLORS_NONE; - Wave.speed_min = 0x4E20; - Wave.speed_max = 0x03E8; + Wave.name = "Wave"; + Wave.value = LOGITECH_G203L_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Wave.color_mode = MODE_COLORS_NONE; + Wave.speed_min = 0x4E20; + Wave.speed_max = 0x03E8; + Wave.brightness = 20; + Wave.brightness_min = 0; + Wave.brightness_max = 20; modes.push_back(Wave); mode Colormixing; - Colormixing.name = "Colormixing"; - Colormixing.value = LOGITECH_G203L_MODE_COLORMIXING; - Colormixing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Colormixing.color_mode = MODE_COLORS_NONE; - Colormixing.speed_min = 0x4E20; - Colormixing.speed_max = 0x03E8; + Colormixing.name = "Colormixing"; + Colormixing.value = LOGITECH_G203L_MODE_COLORMIXING; + Colormixing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Colormixing.color_mode = MODE_COLORS_NONE; + Colormixing.speed_min = 0x4E20; + Colormixing.speed_max = 0x03E8; + Colormixing.brightness = 20; + Colormixing.brightness_min = 0; + Colormixing.brightness_max = 20; modes.push_back(Colormixing); SetupZones(); @@ -152,7 +164,6 @@ void RGBController_LogitechG203L::DeviceUpdateMode() unsigned char grn = 0; unsigned char blu = 0; unsigned char dir = 0; - unsigned char val = 0xFF; if(modes[active_mode].color_mode & MODE_COLORS_MODE_SPECIFIC) { @@ -177,6 +188,6 @@ void RGBController_LogitechG203L::DeviceUpdateMode() } else { - controller->SetMode(modes[active_mode].value, modes[active_mode].speed, val, dir, red, grn, blu); + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, dir, red, grn, blu); } } diff --git a/dependencies/hidapi-win/x64/hidapi.dll b/dependencies/hidapi-win/x64/hidapi.dll index cea5b091..68d7a898 100644 Binary files a/dependencies/hidapi-win/x64/hidapi.dll and b/dependencies/hidapi-win/x64/hidapi.dll differ diff --git a/dependencies/hidapi-win/x64/hidapi.lib b/dependencies/hidapi-win/x64/hidapi.lib index eeebe386..041bdf96 100644 Binary files a/dependencies/hidapi-win/x64/hidapi.lib and b/dependencies/hidapi-win/x64/hidapi.lib differ diff --git a/dependencies/hidapi-win/x86/hidapi.dll b/dependencies/hidapi-win/x86/hidapi.dll index 9998cca0..21674b5c 100644 Binary files a/dependencies/hidapi-win/x86/hidapi.dll and b/dependencies/hidapi-win/x86/hidapi.dll differ diff --git a/dependencies/hidapi-win/x86/hidapi.lib b/dependencies/hidapi-win/x86/hidapi.lib index 10e80895..a1c38297 100644 Binary files a/dependencies/hidapi-win/x86/hidapi.lib and b/dependencies/hidapi-win/x86/hidapi.lib differ diff --git a/dependencies/hidapi/hidapi/hidapi.h b/dependencies/hidapi/hidapi/hidapi.h index 722611e5..3cee21db 100644 --- a/dependencies/hidapi/hidapi/hidapi.h +++ b/dependencies/hidapi/hidapi/hidapi.h @@ -5,9 +5,9 @@ Alan Ott Signal 11 Software - 8/22/2009 + libusb/hidapi Team - Copyright 2009, All Rights Reserved. + Copyright 2022, All Rights Reserved. At the discretion of the user of this library, this software may be licensed under the terms of the @@ -17,7 +17,7 @@ files located at the root of the source distribution. These files may also be found in the public source code repository located at: - http://github.com/signal11/hidapi . + https://github.com/libusb/hidapi . ********************************************************/ /** @file @@ -30,7 +30,7 @@ #include #ifdef _WIN32 - #define HID_API_EXPORT + #define HID_API_EXPORT __declspec(dllexport) #define HID_API_CALL #else #define HID_API_EXPORT /**< API export macro */ @@ -39,9 +39,64 @@ #define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ +/** @brief Static/compile-time major version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_MAJOR 0 +/** @brief Static/compile-time minor version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_MINOR 13 +/** @brief Static/compile-time patch version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_PATCH 0 + +/* Helper macros */ +#define HID_API_AS_STR_IMPL(x) #x +#define HID_API_AS_STR(x) HID_API_AS_STR_IMPL(x) +#define HID_API_TO_VERSION_STR(v1, v2, v3) HID_API_AS_STR(v1.v2.v3) + +/** @brief Coverts a version as Major/Minor/Patch into a number: + <8 bit major><16 bit minor><8 bit patch>. + + This macro was added in version 0.12.0. + + Convenient function to be used for compile-time checks, like: + #if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0) + + @ingroup API +*/ +#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p)) + +/** @brief Static/compile-time version of the library. + + This macro was added in version 0.12.0. + + @see @ref HID_API_MAKE_VERSION. + + @ingroup API +*/ +#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) + +/** @brief Static/compile-time string version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) + #ifdef __cplusplus extern "C" { #endif + struct hid_api_version { + int major; + int minor; + int patch; + }; + struct hid_device_; typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ @@ -63,15 +118,19 @@ extern "C" { /** Product string */ wchar_t *product_string; /** Usage Page for this Device/Interface - (Windows/Mac only). */ + (Windows/Mac/hidraw only) */ unsigned short usage_page; /** Usage for this Device/Interface - (Windows/Mac only).*/ + (Windows/Mac/hidraw only) */ unsigned short usage; /** The USB interface which this logical device - represents. Valid on both Linux implementations - in all cases, and valid on the Windows implementation - only if the device contains more than one interface. */ + represents. + + * Valid on both Linux implementations in all cases. + * Valid on the Windows implementation only if the device + contains more than one interface. + * Valid on the Mac implementation if and only if the device + is a USB HID device. */ int interface_number; /** Pointer to the next device */ @@ -87,11 +146,12 @@ extern "C" { needed. This function should be called at the beginning of execution however, if there is a chance of HIDAPI handles being opened by different threads simultaneously. - + @ingroup API @returns This function returns 0 on success and -1 on error. + Call hid_error(NULL) to get the failure reason. */ int HID_API_EXPORT HID_API_CALL hid_init(void); @@ -103,7 +163,7 @@ extern "C" { @ingroup API - @returns + @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_exit(void); @@ -123,21 +183,25 @@ extern "C" { @param product_id The Product ID (PID) of the types of device to open. - @returns - This function returns a pointer to a linked list of type - struct #hid_device, containing information about the HID devices - attached to the system, or NULL in the case of failure. Free - this linked list by calling hid_free_enumeration(). + @returns + This function returns a pointer to a linked list of type + struct #hid_device_info, containing information about the HID devices + attached to the system, + or NULL in the case of failure or if no HID devices present in the system. + Call hid_error(NULL) to get the failure reason. + + @note The returned value by this function must to be freed by calling hid_free_enumeration(), + when not needed anymore. */ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); /** @brief Free an enumeration Linked List - This function frees a linked list created by hid_enumerate(). + This function frees a linked list created by hid_enumerate(). @ingroup API - @param devs Pointer to a list of struct_device returned from - hid_enumerate(). + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). */ void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); @@ -151,11 +215,15 @@ extern "C" { @param vendor_id The Vendor ID (VID) of the device to open. @param product_id The Product ID (PID) of the device to open. @param serial_number The Serial Number of the device to open - (Optionally NULL). + (Optionally NULL). @returns This function returns a pointer to a #hid_device object on success or NULL on failure. + Call hid_error(NULL) to get the failure reason. + + @note The returned object must be freed by calling hid_close(), + when not needed anymore. */ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); @@ -166,11 +234,15 @@ extern "C" { Linux). @ingroup API - @param path The path name of the device to open + @param path The path name of the device to open @returns This function returns a pointer to a #hid_device object on success or NULL on failure. + Call hid_error(NULL) to get the failure reason. + + @note The returned object must be freed by calling hid_close(), + when not needed anymore. */ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); @@ -191,7 +263,7 @@ extern "C" { the Control Endpoint (Endpoint 0). @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param data The data to send, including the report number as the first byte. @param length The length in bytes of the data to send. @@ -199,8 +271,9 @@ extern "C" { @returns This function returns the actual number of bytes written and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length); /** @brief Read an Input report from a HID device with timeout. @@ -209,7 +282,7 @@ extern "C" { contain the Report number if the device uses numbered reports. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param data A buffer to put the read data into. @param length The number of bytes to read. For devices with multiple reports, make sure to read an extra byte for @@ -218,7 +291,9 @@ extern "C" { @returns This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read within + -1 on error. + Call hid_error(dev) to get the failure reason. + If no packet was available to be read within the timeout period, this function returns 0. */ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); @@ -226,11 +301,11 @@ extern "C" { /** @brief Read an Input report from a HID device. Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will + to the host through the INTERRUPT IN endpoint. The first byte will contain the Report number if the device uses numbered reports. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param data A buffer to put the read data into. @param length The number of bytes to read. For devices with multiple reports, make sure to read an extra byte for @@ -238,10 +313,12 @@ extern "C" { @returns This function returns the actual number of bytes read and - -1 on error. If no packet was available to be read and + -1 on error. + Call hid_error(dev) to get the failure reason. + If no packet was available to be read and the handle is in non-blocking mode, this function returns 0. */ - int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length); /** @brief Set the device handle to be non-blocking. @@ -253,15 +330,16 @@ extern "C" { Nonblocking can be turned on and off at any time. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param nonblock enable or not the nonblocking reads - 1 to enable nonblocking - 0 to disable nonblocking. @returns This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock); /** @brief Send a Feature report to the device. @@ -279,7 +357,7 @@ extern "C" { in would be 17. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param data The data to send, including the report number as the first byte. @param length The length in bytes of the data to send, including @@ -288,8 +366,9 @@ extern "C" { @returns This function returns the actual number of bytes written and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length); /** @brief Get a feature report from a HID device. @@ -299,6 +378,34 @@ extern "C" { still contain the Report ID, and the report data will start in data[1]. + @ingroup API + @param dev A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length); + + /** @brief Get a input report from a HID device. + + Since version 0.10.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 10, 0) + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + @ingroup API @param device A device handle returned from hid_open(). @param data A buffer to put the read data into, including @@ -313,75 +420,136 @@ extern "C" { This function returns the number of bytes read plus one for the report ID (which is still in the first byte), or -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length); /** @brief Close a HID device. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). */ - void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev); /** @brief Get The Manufacturer String from a HID device. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen); /** @brief Get The Product String from a HID device. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen); /** @brief Get The Serial Number String from a HID device. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen); + + /** @brief Get The struct #hid_device_info from a HID device. + + Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0) + + @ingroup API + @param dev A device handle returned from hid_open(). + + @returns + This function returns a pointer to the struct #hid_device_info + for this hid_device, or NULL in the case of failure. + Call hid_error(dev) to get the failure reason. + This struct is valid until the device is closed with hid_close(). + + @note The returned object is owned by the @p dev, and SHOULD NOT be freed by the user. + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev); /** @brief Get a string from a HID device, based on its string index. @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(). @param string_index The index of the string to get. @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. */ - int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen); /** @brief Get a string describing the last error which occurred. + This function is intended for logging/debugging purposes. + + This function guarantees to never return NULL. + If there was no error in the last function call - + the returned string clearly indicates that. + + Any HIDAPI function that can explicitly indicate an execution failure + (e.g. by an error code, or by returning NULL) - may set the error string, + to be returned by this function. + + Strings returned from hid_error() must not be freed by the user, + i.e. owned by HIDAPI library. + Device-specific error string may remain allocated at most until hid_close() is called. + Global error string may remain allocated at most until hid_exit() is called. + @ingroup API - @param device A device handle returned from hid_open(). + @param dev A device handle returned from hid_open(), + or NULL to get the last non-device-specific error + (e.g. for errors in hid_open() or hid_enumerate()). @returns - This function returns a string containing the last error - which occurred or NULL if none has occurred. + A string describing the last error (if any). */ - HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev); + + /** @brief Get a runtime version of the library. + + This function is thread-safe. + + @ingroup API + + @returns + Pointer to statically allocated struct, that contains version. + */ + HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void); + + + /** @brief Get a runtime version string of the library. + + This function is thread-safe. + + @ingroup API + + @returns + Pointer to statically allocated string, that contains version string. + */ + HID_API_EXPORT const char* HID_API_CALL hid_version_str(void); #ifdef __cplusplus }