From ec5d034aa42f9c016bf890d7694fb45628ba8587 Mon Sep 17 00:00:00 2001 From: Lucas Soler Date: Mon, 19 Sep 2022 18:48:22 -0300 Subject: [PATCH 1/4] add support for logitech g535 --- src/device_registry.c | 4 +- src/devices/CMakeLists.txt | 2 + src/devices/logitech_g535.c | 104 ++++++++++++++++++++++++++++++++++++ src/devices/logitech_g535.h | 3 ++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/devices/logitech_g535.c create mode 100644 src/devices/logitech_g535.h diff --git a/src/device_registry.c b/src/device_registry.c index f1e3934e..09d2ee61 100644 --- a/src/device_registry.c +++ b/src/device_registry.c @@ -5,6 +5,7 @@ #include "devices/logitech_g430.h" #include "devices/logitech_g432.h" #include "devices/logitech_g533.h" +#include "devices/logitech_g535.h" #include "devices/logitech_g633_g933_935.h" #include "devices/logitech_g930.h" #include "devices/logitech_gpro.h" @@ -19,7 +20,7 @@ #include -#define NUMDEVICES 16 +#define NUMDEVICES 17 // array of pointers to device static struct device*(devicelist[NUMDEVICES]); @@ -42,6 +43,7 @@ void init_devices() elo71USB_init(&devicelist[13]); arctis_7_plus_init(&devicelist[14]); cflight_init(&devicelist[15]); + g535_init(&devicelist[16]); } int get_device(struct device* device_found, uint16_t idVendor, uint16_t idProduct) diff --git a/src/devices/CMakeLists.txt b/src/devices/CMakeLists.txt index 0b6222a4..410172da 100644 --- a/src/devices/CMakeLists.txt +++ b/src/devices/CMakeLists.txt @@ -11,6 +11,8 @@ set(SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/logitech_g432.h ${CMAKE_CURRENT_SOURCE_DIR}/logitech_g533.c ${CMAKE_CURRENT_SOURCE_DIR}/logitech_g533.h + ${CMAKE_CURRENT_SOURCE_DIR}/logitech_g535.c + ${CMAKE_CURRENT_SOURCE_DIR}/logitech_g535.h ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_1.c ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_1.h ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_7.c diff --git a/src/devices/logitech_g535.c b/src/devices/logitech_g535.c new file mode 100644 index 00000000..08f78ebf --- /dev/null +++ b/src/devices/logitech_g535.c @@ -0,0 +1,104 @@ +#include "../device.h" +#include "../utility.h" +#include "logitech.h" + +#include +#include + +#define MSG_SIZE 20 + +static struct device device_g535; + +static const uint16_t PRODUCT_ID = 0x0ac4; + +static int g535_send_sidetone(hid_device* device_handle, uint8_t num); +// static int g535_request_battery(hid_device* device_handle); + +void g535_init(struct device** device) +{ + device_g535.idVendor = VENDOR_LOGITECH; + device_g535.idProductsSupported = &PRODUCT_ID; + device_g535.numIdProducts = 1; + + strncpy(device_g535.device_name, "Logitech G535", sizeof(device_g535.device_name)); + + device_g535.capabilities = B(CAP_SIDETONE) | B(CAP_BATTERY_STATUS); + device_g535.capability_details[CAP_SIDETONE] = (struct capability_detail) { .usagepage = 0xc, .usageid = 0x1, .interface = 3 }; + device_g535.capability_details[CAP_BATTERY_STATUS] = (struct capability_detail) { .usagepage = 0xff43, .usageid = 0x202, .interface = 3 }; + device_g535.send_sidetone = &g535_send_sidetone; + device_g535.request_battery = &g535_request_battery; + + *device = &device_g535; +} + +static int g535_send_sidetone(hid_device* device_handle, uint8_t num) +{ + uint8_t turn_sidetone_data[MSG_SIZE] = { 0x11, 0xff, 0x04, 0x0e }; + + for (int i = 16; i < MSG_SIZE; i++) + turn_sidetone_data[i] = 0; + + hid_send_feature_report(device_handle, turn_sidetone_data, MSG_SIZE); + + num = map(num, 0, 128, 0, 100); + + uint8_t set_sidetone_data[MSG_SIZE] = { 0x11, 0xff, 0x04, 0x1e, num }; + + for (int i = 16; i < MSG_SIZE; i++) + set_sidetone_data[i] = 0; + + return hid_send_feature_report(device_handle, set_sidetone_data, MSG_SIZE); +} + +// mostly copied from logitech_g933_935.c +static int estimate_battery_level(uint16_t voltage) +{ + if (voltage <= 3618) + return (int)((0.017547 * voltage) - 53.258578); + if (voltage > 4011) + return 100; + + // Interpolated from https://github.com/ashkitten/g933-utils/blob/master/libg933/src/maps/0A66/discharging.csv + // Errors: Min 0.0 Max 14.56 AVG: 3.9485493530204 + return map((int)(round(-0.0000010876 * pow(voltage, 3) + 0.0122392434 * pow(voltage, 2) - 45.6420832787 * voltage + 56445.8517589238)), + 25, 100, 20, 100); +} + +static int g535_request_battery(hid_device* device_handle) +{ + /* + CREDIT GOES TO https://github.com/ashkitten/ for the project + https://github.com/ashkitten/g933-utils/ + I've simply ported that implementation to this project! + */ + + int r = 0; + // request battery voltage + uint8_t data_request[HIDPP_LONG_MESSAGE_LENGTH] = { HIDPP_LONG_MESSAGE, HIDPP_DEVICE_RECEIVER, 0x07, 0x01 }; + + r = hid_write(device_handle, data_request, HIDPP_LONG_MESSAGE_LENGTH); + if (r < 0) + return r; + + uint8_t data_read[7]; + r = hid_read_timeout(device_handle, data_read, 7, hsc_device_timeout); + if (r < 0) + return r; + + if (r == 0) + return HSC_READ_TIMEOUT; + + // Headset offline + if (data_read[2] == 0xFF) + return HSC_ERROR; + + // 6th byte is state; 0x1 for idle, 0x3 for charging + uint8_t state = data_read[6]; + if (state == 0x03) + return BATTERY_CHARGING; + + // actual voltage is byte 4 and byte 5 combined together + const uint16_t voltage = (data_read[4] << 8) | data_read[5]; + + return estimate_battery_level(voltage); +} diff --git a/src/devices/logitech_g535.h b/src/devices/logitech_g535.h new file mode 100644 index 00000000..c9c98dfe --- /dev/null +++ b/src/devices/logitech_g535.h @@ -0,0 +1,3 @@ +#pragma once + +void g535_init(struct device** device); From b6f98f4ea85faea92b704b986218e6c553affa3e Mon Sep 17 00:00:00 2001 From: Lucas Soler Date: Mon, 19 Sep 2022 21:35:30 -0300 Subject: [PATCH 2/4] remove battery related functions because it is not working --- src/devices/logitech_g535.c | 62 ++----------------------------------- 1 file changed, 3 insertions(+), 59 deletions(-) diff --git a/src/devices/logitech_g535.c b/src/devices/logitech_g535.c index 08f78ebf..2693aa5c 100644 --- a/src/devices/logitech_g535.c +++ b/src/devices/logitech_g535.c @@ -12,7 +12,6 @@ static struct device device_g535; static const uint16_t PRODUCT_ID = 0x0ac4; static int g535_send_sidetone(hid_device* device_handle, uint8_t num); -// static int g535_request_battery(hid_device* device_handle); void g535_init(struct device** device) { @@ -22,11 +21,9 @@ void g535_init(struct device** device) strncpy(device_g535.device_name, "Logitech G535", sizeof(device_g535.device_name)); - device_g535.capabilities = B(CAP_SIDETONE) | B(CAP_BATTERY_STATUS); - device_g535.capability_details[CAP_SIDETONE] = (struct capability_detail) { .usagepage = 0xc, .usageid = 0x1, .interface = 3 }; - device_g535.capability_details[CAP_BATTERY_STATUS] = (struct capability_detail) { .usagepage = 0xff43, .usageid = 0x202, .interface = 3 }; - device_g535.send_sidetone = &g535_send_sidetone; - device_g535.request_battery = &g535_request_battery; + device_g535.capabilities = B(CAP_SIDETONE); + device_g535.capability_details[CAP_SIDETONE] = (struct capability_detail) { .usagepage = 0xc, .usageid = 0x1, .interface = 3 }; + device_g535.send_sidetone = &g535_send_sidetone; *device = &device_g535; } @@ -49,56 +46,3 @@ static int g535_send_sidetone(hid_device* device_handle, uint8_t num) return hid_send_feature_report(device_handle, set_sidetone_data, MSG_SIZE); } - -// mostly copied from logitech_g933_935.c -static int estimate_battery_level(uint16_t voltage) -{ - if (voltage <= 3618) - return (int)((0.017547 * voltage) - 53.258578); - if (voltage > 4011) - return 100; - - // Interpolated from https://github.com/ashkitten/g933-utils/blob/master/libg933/src/maps/0A66/discharging.csv - // Errors: Min 0.0 Max 14.56 AVG: 3.9485493530204 - return map((int)(round(-0.0000010876 * pow(voltage, 3) + 0.0122392434 * pow(voltage, 2) - 45.6420832787 * voltage + 56445.8517589238)), - 25, 100, 20, 100); -} - -static int g535_request_battery(hid_device* device_handle) -{ - /* - CREDIT GOES TO https://github.com/ashkitten/ for the project - https://github.com/ashkitten/g933-utils/ - I've simply ported that implementation to this project! - */ - - int r = 0; - // request battery voltage - uint8_t data_request[HIDPP_LONG_MESSAGE_LENGTH] = { HIDPP_LONG_MESSAGE, HIDPP_DEVICE_RECEIVER, 0x07, 0x01 }; - - r = hid_write(device_handle, data_request, HIDPP_LONG_MESSAGE_LENGTH); - if (r < 0) - return r; - - uint8_t data_read[7]; - r = hid_read_timeout(device_handle, data_read, 7, hsc_device_timeout); - if (r < 0) - return r; - - if (r == 0) - return HSC_READ_TIMEOUT; - - // Headset offline - if (data_read[2] == 0xFF) - return HSC_ERROR; - - // 6th byte is state; 0x1 for idle, 0x3 for charging - uint8_t state = data_read[6]; - if (state == 0x03) - return BATTERY_CHARGING; - - // actual voltage is byte 4 and byte 5 combined together - const uint16_t voltage = (data_read[4] << 8) | data_read[5]; - - return estimate_battery_level(voltage); -} From d901b117d9d5366e2ae3918e2c3423443bf33d49 Mon Sep 17 00:00:00 2001 From: Lucas Soler Date: Mon, 19 Sep 2022 21:37:50 -0300 Subject: [PATCH 3/4] add supported device in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4e7b2d04..0be31f69 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ talking. This differs from a simple loopback via PulseAudio as you won't have an - Sidetone (only tested on Linux) - Logitech G533 - Sidetone, Battery (for Wireless) +- Logitech G535 + - Sidetone (only tested on Linux) - Logitech G633 / G635 / G733 / G933 / G935 - Sidetone, Battery (for Wireless), LED on/off - Logitech G930 From 360fc775de6dbcc5ed0aa0dc09c480c726a999d5 Mon Sep 17 00:00:00 2001 From: Lucas Soler Date: Mon, 19 Sep 2022 21:51:35 -0300 Subject: [PATCH 4/4] remove unused code --- src/devices/logitech_g535.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/devices/logitech_g535.c b/src/devices/logitech_g535.c index 2693aa5c..79999366 100644 --- a/src/devices/logitech_g535.c +++ b/src/devices/logitech_g535.c @@ -30,19 +30,12 @@ void g535_init(struct device** device) static int g535_send_sidetone(hid_device* device_handle, uint8_t num) { - uint8_t turn_sidetone_data[MSG_SIZE] = { 0x11, 0xff, 0x04, 0x0e }; - - for (int i = 16; i < MSG_SIZE; i++) - turn_sidetone_data[i] = 0; - - hid_send_feature_report(device_handle, turn_sidetone_data, MSG_SIZE); - num = map(num, 0, 128, 0, 100); - uint8_t set_sidetone_data[MSG_SIZE] = { 0x11, 0xff, 0x04, 0x1e, num }; + uint8_t set_sidetone_level[MSG_SIZE] = { 0x11, 0xff, 0x04, 0x1e, num }; for (int i = 16; i < MSG_SIZE; i++) - set_sidetone_data[i] = 0; + set_sidetone_level[i] = 0; - return hid_send_feature_report(device_handle, set_sidetone_data, MSG_SIZE); + return hid_send_feature_report(device_handle, set_sidetone_level, MSG_SIZE); }