From 86e3a3ff5243673ce646e1112759214cf11d8c1d Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 27 Dec 2023 13:27:16 +0100 Subject: [PATCH 1/3] Add Arctis Nova 3 support Signed-off-by: AnErrupTion --- src/device.c | 44 ++++--- src/device.h | 34 ++++- src/device_registry.c | 12 +- src/devices/CMakeLists.txt | 2 + src/devices/steelseries_arctis_nova_3.c | 159 ++++++++++++++++++++++++ src/devices/steelseries_arctis_nova_3.h | 3 + src/main.c | 40 +++++- 7 files changed, 267 insertions(+), 27 deletions(-) create mode 100644 src/devices/steelseries_arctis_nova_3.c create mode 100644 src/devices/steelseries_arctis_nova_3.h diff --git a/src/device.c b/src/device.c index 91dad97..59c0d16 100644 --- a/src/device.c +++ b/src/device.c @@ -2,28 +2,32 @@ const char* const capabilities_str[NUM_CAPABILITIES] = { - [CAP_SIDETONE] = "sidetone", - [CAP_BATTERY_STATUS] = "battery status", - [CAP_NOTIFICATION_SOUND] = "notification sound", - [CAP_LIGHTS] = "lights", - [CAP_INACTIVE_TIME] = "inactive time", - [CAP_CHATMIX_STATUS] = "chatmix", - [CAP_VOICE_PROMPTS] = "voice prompts", - [CAP_ROTATE_TO_MUTE] = "rotate to mute", - [CAP_EQUALIZER_PRESET] = "equalizer preset", - [CAP_EQUALIZER] = "equalizer", + [CAP_SIDETONE] = "sidetone", + [CAP_BATTERY_STATUS] = "battery status", + [CAP_NOTIFICATION_SOUND] = "notification sound", + [CAP_LIGHTS] = "lights", + [CAP_INACTIVE_TIME] = "inactive time", + [CAP_CHATMIX_STATUS] = "chatmix", + [CAP_VOICE_PROMPTS] = "voice prompts", + [CAP_ROTATE_TO_MUTE] = "rotate to mute", + [CAP_EQUALIZER_PRESET] = "equalizer preset", + [CAP_EQUALIZER] = "equalizer", + [CAP_MICROPHONE_MUTE_LED_BRIGHTNESS] = "microphone mute led brightness", + [CAP_MICROPHONE_VOLUME] = "microphone volume" }; const char capabilities_str_short[NUM_CAPABILITIES] = { - [CAP_SIDETONE] = 's', - [CAP_BATTERY_STATUS] = 'b', - [CAP_NOTIFICATION_SOUND] = 'n', - [CAP_LIGHTS] = 'l', - [CAP_INACTIVE_TIME] = 'i', - [CAP_CHATMIX_STATUS] = 'm', - [CAP_VOICE_PROMPTS] = 'v', - [CAP_ROTATE_TO_MUTE] = 'r', - [CAP_EQUALIZER_PRESET] = 'p', - [CAP_EQUALIZER] = 'e' + [CAP_SIDETONE] = 's', + [CAP_BATTERY_STATUS] = 'b', + [CAP_NOTIFICATION_SOUND] = 'n', + [CAP_LIGHTS] = 'l', + [CAP_INACTIVE_TIME] = 'i', + [CAP_CHATMIX_STATUS] = 'm', + [CAP_VOICE_PROMPTS] = 'v', + [CAP_ROTATE_TO_MUTE] = 'r', + [CAP_EQUALIZER_PRESET] = 'p', + [CAP_EQUALIZER] = 'e', + [CAP_MICROPHONE_MUTE_LED_BRIGHTNESS] = 't', + [CAP_MICROPHONE_VOLUME] = 'o' }; \ No newline at end of file diff --git a/src/device.h b/src/device.h index 8243d65..9b13b0c 100644 --- a/src/device.h +++ b/src/device.h @@ -30,6 +30,8 @@ enum capabilities { CAP_ROTATE_TO_MUTE, CAP_EQUALIZER_PRESET, CAP_EQUALIZER, + CAP_MICROPHONE_MUTE_LED_BRIGHTNESS, + CAP_MICROPHONE_VOLUME, NUM_CAPABILITIES }; @@ -209,7 +211,7 @@ struct device { * @param num The preset number, between 0 - 3 * * @returns > 0 on success - * HSC_OUT_OF_BOUNDS on preset parmeter out of range + * HSC_OUT_OF_BOUNDS on preset parameter out of range * specific to this hardware * -1 HIDAPI error */ @@ -230,4 +232,34 @@ struct device { * -1 HIDAPI error */ int (*send_equalizer)(hid_device* hid_device, struct equalizer_settings* settings); + + /** @brief Function pointer for setting headset microphone mute LED brightness + * + * Forwards the request to the device specific implementation + * + * @param device_handle The hidapi handle. Must be the same + * device as defined here (same ids) + * @param num The level number, between 0 - 3 + * + * @returns > 0 on success + * HSC_OUT_OF_BOUNDS on level parameter out of range + * specific to this hardware + * -1 HIDAPI error + */ + int (*send_microphone_mute_led_brightness)(hid_device* hid_device, uint8_t num); + + /** @brief Function pointer for setting headset microphone volume + * + * Forwards the request to the device specific implementation + * + * @param device_handle The hidapi handle. Must be the same + * device as defined here (same ids) + * @param num The volume number, between 0 - 128 + * + * @returns > 0 on success + * HSC_OUT_OF_BOUNDS on volume parameter out of range + * specific to this hardware + * -1 HIDAPI error + */ + int (*send_microphone_volume)(hid_device* hid_device, uint8_t num); }; diff --git a/src/device_registry.c b/src/device_registry.c index 279d629..7743c48 100644 --- a/src/device_registry.c +++ b/src/device_registry.c @@ -18,13 +18,14 @@ #include "devices/steelseries_arctis_7.h" #include "devices/steelseries_arctis_7_plus.h" #include "devices/steelseries_arctis_9.h" +#include "devices/steelseries_arctis_nova_3.h" #include "devices/steelseries_arctis_nova_7.h" #include "devices/steelseries_arctis_nova_pro_wireless.h" #include "devices/steelseries_arctis_pro_wireless.h" #include -#define NUMDEVICES 21 +#define NUMDEVICES 22 // array of pointers to device static struct device*(devicelist[NUMDEVICES]); @@ -48,10 +49,11 @@ void init_devices() arctis_7_plus_init(&devicelist[14]); cflight_init(&devicelist[15]); g535_init(&devicelist[16]); - arctis_nova_7_init(&devicelist[17]); - calphaw_init(&devicelist[18]); - arctis_nova_pro_wireless_init(&devicelist[19]); - gpro_x2_init(&devicelist[20]); + arctis_nova_3_init(&devicelist[17]); + arctis_nova_7_init(&devicelist[18]); + calphaw_init(&devicelist[19]); + arctis_nova_pro_wireless_init(&devicelist[20]); + gpro_x2_init(&devicelist[21]); } 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 427cd73..a722cb3 100644 --- a/src/devices/CMakeLists.txt +++ b/src/devices/CMakeLists.txt @@ -23,6 +23,8 @@ set(SOURCE_FILES ${SOURCE_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_7_plus.c ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_9.c ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_9.h + ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_nova_3.h + ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_nova_3.c ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_nova_7.h ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_nova_7.c ${CMAKE_CURRENT_SOURCE_DIR}/steelseries_arctis_nova_pro_wireless.c diff --git a/src/devices/steelseries_arctis_nova_3.c b/src/devices/steelseries_arctis_nova_3.c new file mode 100644 index 0000000..adec1d4 --- /dev/null +++ b/src/devices/steelseries_arctis_nova_3.c @@ -0,0 +1,159 @@ +#include "../device.h" + +#include +#include +#include + +#define MSG_SIZE 64 + +static struct device device_arctis; + +#define ID_ARCTIS_NOVA_3 0x12ec + +#define EQUALIZER_BANDS_SIZE 6 + +static const uint16_t PRODUCT_IDS[] = { ID_ARCTIS_NOVA_3 }; +static const uint8_t SAVE_DATA[MSG_SIZE] = { 0x06, 0x09 }; // Command to save settings to headset + +static int arctis_nova_3_send_sidetone(hid_device* device_handle, uint8_t num); +static int arctis_nova_3_send_equalizer_preset(hid_device* device_handle, uint8_t num); +static int arctis_nova_3_send_equalizer(hid_device* device_handle, struct equalizer_settings* settings); +static int arctis_nova_3_send_microphone_mute_led_brightness(hid_device* device_handle, uint8_t num); +static int arctis_nova_3_send_microphone_volume(hid_device* device_handle, uint8_t num); + +void arctis_nova_3_init(struct device** device) +{ + device_arctis.idVendor = VENDOR_STEELSERIES; + device_arctis.idProductsSupported = PRODUCT_IDS; + device_arctis.numIdProducts = sizeof(PRODUCT_IDS) / sizeof(PRODUCT_IDS[0]); + + strncpy(device_arctis.device_name, "SteelSeries Arctis Nova 3", sizeof(device_arctis.device_name)); + + device_arctis.capabilities = B(CAP_SIDETONE) | B(CAP_EQUALIZER_PRESET) | B(CAP_EQUALIZER) | B(CAP_MICROPHONE_MUTE_LED_BRIGHTNESS) | B(CAP_MICROPHONE_VOLUME); + // 0xc (3), 0xffc0 (4), 0xff00 (4) + device_arctis.capability_details[CAP_SIDETONE] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_EQUALIZER_PRESET] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_EQUALIZER] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_MICROPHONE_MUTE_LED_BRIGHTNESS] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_MICROPHONE_VOLUME] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + + device_arctis.send_sidetone = &arctis_nova_3_send_sidetone; + device_arctis.send_equalizer_preset = &arctis_nova_3_send_equalizer_preset; + device_arctis.send_equalizer = &arctis_nova_3_send_equalizer; + device_arctis.send_microphone_mute_led_brightness = &arctis_nova_3_send_microphone_mute_led_brightness; + device_arctis.send_microphone_volume = &arctis_nova_3_send_microphone_volume; + + *device = &device_arctis; +} + +static int arctis_nova_3_send_sidetone(hid_device* device_handle, uint8_t num) +{ + // This headset only supports 4 levels of sidetone volume, but we allow a full range of 0-128 for it. Map the volume to the correct numbers. + if (num < 26) { + num = 0x0; + } else if (num < 51) { + num = 0x1; + } else if (num < 76) { + num = 0x2; + } else { + num = 0x3; + } + + uint8_t data[MSG_SIZE] = { 0x06, 0x39, num }; + hid_send_feature_report(device_handle, data, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); +} + +static int arctis_nova_3_send_equalizer_preset(hid_device* device_handle, uint8_t num) +{ + // This headset supports only 4 presets: + // Flat (default), Bass Boost, Smiley, Focus + + switch (num) { + case 0: { + uint8_t flat[MSG_SIZE] = { 0x06, 0x33, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }; + hid_send_feature_report(device_handle, flat, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); + } + case 1: { + uint8_t bass[MSG_SIZE] = { 0x06, 0x33, 0x1c, 0x19, 0x11, 0x14, 0x14, 0x14 }; + hid_send_feature_report(device_handle, bass, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); + } + case 2: { + uint8_t smiley[MSG_SIZE] = { 0x06, 0x33, 0x1a, 0x17, 0x0f, 0x12, 0x17, 0x1a }; + hid_send_feature_report(device_handle, smiley, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); + } + case 3: { + uint8_t focus[MSG_SIZE] = { 0x06, 0x33, 0x0c, 0x0d, 0x11, 0x18, 0x1c, 0x14 }; + hid_send_feature_report(device_handle, focus, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); + } + default: { + printf("Device only supports 0-3 range for presets.\n"); + return HSC_OUT_OF_BOUNDS; + } + } +} + +static int arctis_nova_3_send_equalizer(hid_device* device_handle, struct equalizer_settings* settings) { + if (settings->size != EQUALIZER_BANDS_SIZE) { + printf("Device only supports %d bands.\n", EQUALIZER_BANDS_SIZE); + return HSC_OUT_OF_BOUNDS; + } + + uint8_t data[MSG_SIZE] = { 0x06, 0x33 }; + for (int i = 0; i < settings->size; i++) { + data[i + 2] = (uint8_t)settings->bands_values[i]; + } + + return hid_send_feature_report(device_handle, data, MSG_SIZE); +} + +static int arctis_nova_3_send_microphone_mute_led_brightness(hid_device* device_handle, uint8_t num) { + // This headset only supports 3 levels: + // Off, low, medium (default), high + + uint8_t brightness[MSG_SIZE] = { 0x06, 0xae, num }; + hid_send_feature_report(device_handle, brightness, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); +} + +static int arctis_nova_3_send_microphone_volume(hid_device* device_handle, uint8_t num) { + // This headset only supports 10 levels of microphone volume, but we allow a full range of 0-128 for it. Map the volume to the correct numbers. + if (num < 13) { + num = 0x00; + } else if (num < 25) { + num = 0x01; + } else if (num < 37) { + num = 0x02; + } else if (num < 49) { + num = 0x03; + } else if (num < 61) { + num = 0x04; + } else if (num < 73) { + num = 0x05; + } else if (num < 85) { + num = 0x06; + } else if (num < 97) { + num = 0x07; + } else if (num < 109) { + num = 0x08; + } else if (num < 121) { + num = 0x09; + } else { + num = 0x0a; + } + + uint8_t volume[MSG_SIZE] = { 0x06, 0x37, num }; + hid_send_feature_report(device_handle, volume, MSG_SIZE); + + return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); +} \ No newline at end of file diff --git a/src/devices/steelseries_arctis_nova_3.h b/src/devices/steelseries_arctis_nova_3.h new file mode 100644 index 0000000..5a6edb6 --- /dev/null +++ b/src/devices/steelseries_arctis_nova_3.h @@ -0,0 +1,3 @@ +#pragma once + +void arctis_nova_3_init(struct device** device); diff --git a/src/main.c b/src/main.c index 7d75f34..330b58c 100644 --- a/src/main.c +++ b/src/main.c @@ -248,6 +248,14 @@ static int handle_feature(struct device* device_found, hid_device** device_handl PRINT_INFO("Successfully set equalizer!\n"); break; + case CAP_MICROPHONE_MUTE_LED_BRIGHTNESS: + ret = device_found->send_microphone_mute_led_brightness(*device_handle, *(int*)param); + break; + + case CAP_MICROPHONE_VOLUME: + ret = device_found->send_microphone_volume(*device_handle, *(int*)param); + break; + case NUM_CAPABILITIES: ret = -99; // silence warning @@ -294,6 +302,8 @@ int main(int argc, char* argv[]) int rotate_to_mute = -1; int print_capabilities = -1; int equalizer_preset = -1; + int microphone_mute_led_brightness = -1; + int microphone_volume = -1; int dev_mode = 0; int follow = 0; unsigned follow_sec = 2; @@ -327,7 +337,7 @@ int main(int argc, char* argv[]) // Init all information of supported devices init_devices(); - while ((c = getopt_long(argc, argv, "bchi:l:f::mn:r:s:uv:p:e:?", opts, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "bchi:l:f::mn:r:s:uv:p:t:o:e:?", opts, &option_index)) != -1) { char* endptr = NULL; // for strtol switch (c) { @@ -401,6 +411,22 @@ int main(int argc, char* argv[]) return 1; } break; + case 't': + microphone_mute_led_brightness = strtol(optarg, &endptr, 10); + + if (*endptr != '\0' || endptr == optarg || microphone_mute_led_brightness < 0 || microphone_mute_led_brightness > 3) { + printf("Usage: %s -t 0-3\n", argv[0]); + return 1; + } + break; + case 'o': + microphone_volume = strtol(optarg, &endptr, 10); + + if (*endptr != '\0' || endptr == optarg || microphone_volume < 0 || microphone_volume > 128) { + printf("Usage: %s -o 0-128\n", argv[0]); + return 1; + } + break; case 'r': rotate_to_mute = strtol(optarg, &endptr, 10); if (*endptr != '\0' || endptr == optarg || rotate_to_mute < 0 || rotate_to_mute > 1) { @@ -444,6 +470,8 @@ int main(int argc, char* argv[]) printf(" -r, --rotate-to-mute 0|1\tTurn rotate to mute feature on or off (0 = off, 1 = on)\n"); printf(" -e, --equalizer string\tSets equalizer to specified curve, string must contain band values specific to the device (hex or decimal) delimited by spaces, or commas, or new-lines e.g \"0x18, 0x18, 0x18, 0x18, 0x18\".\n"); printf(" -p, --equalizer-preset number\tSets equalizer preset, number must be between 0 and 3, 0 sets the default\n"); + printf(" -t, --microphone-mute-led-brightness number\tSets microphone mute LED brightness, number must be between 0 and 3\n"); + printf(" -o, --microphone-volume number\tSets microphone volume, number must be between 0 and 128\n"); printf(" -f, --follow [secs timeout]\tRe-run the commands after the specified seconds timeout or 2 by default\n"); printf("\n"); printf(" --timeout 0-100000\t\tSpecifies the timeout in ms for reading data from device (default 5000)\n"); @@ -546,6 +574,16 @@ int main(int argc, char* argv[]) goto error; } + if (microphone_mute_led_brightness != -1) { + if ((error = handle_feature(&device_found, &device_handle, &hid_path, CAP_MICROPHONE_MUTE_LED_BRIGHTNESS, µphone_mute_led_brightness)) != 0) + goto error; + } + + if (microphone_volume != -1) { + if ((error = handle_feature(&device_found, &device_handle, &hid_path, CAP_MICROPHONE_VOLUME, µphone_volume)) != 0) + goto error; + } + if (equalizer != NULL) { error = handle_feature(&device_found, &device_handle, &hid_path, CAP_EQUALIZER, equalizer); free(equalizer); From 50af1f3b1c5af5d7d6521c633f4532ca02f774cf Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 27 Dec 2023 13:49:57 +0100 Subject: [PATCH 2/3] Fix code style Signed-off-by: AnErrupTion --- src/devices/steelseries_arctis_nova_3.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/devices/steelseries_arctis_nova_3.c b/src/devices/steelseries_arctis_nova_3.c index adec1d4..36b218d 100644 --- a/src/devices/steelseries_arctis_nova_3.c +++ b/src/devices/steelseries_arctis_nova_3.c @@ -12,7 +12,7 @@ static struct device device_arctis; #define EQUALIZER_BANDS_SIZE 6 -static const uint16_t PRODUCT_IDS[] = { ID_ARCTIS_NOVA_3 }; +static const uint16_t PRODUCT_IDS[] = { ID_ARCTIS_NOVA_3 }; static const uint8_t SAVE_DATA[MSG_SIZE] = { 0x06, 0x09 }; // Command to save settings to headset static int arctis_nova_3_send_sidetone(hid_device* device_handle, uint8_t num); @@ -29,13 +29,13 @@ void arctis_nova_3_init(struct device** device) strncpy(device_arctis.device_name, "SteelSeries Arctis Nova 3", sizeof(device_arctis.device_name)); - device_arctis.capabilities = B(CAP_SIDETONE) | B(CAP_EQUALIZER_PRESET) | B(CAP_EQUALIZER) | B(CAP_MICROPHONE_MUTE_LED_BRIGHTNESS) | B(CAP_MICROPHONE_VOLUME); + device_arctis.capabilities = B(CAP_SIDETONE) | B(CAP_EQUALIZER_PRESET) | B(CAP_EQUALIZER) | B(CAP_MICROPHONE_MUTE_LED_BRIGHTNESS) | B(CAP_MICROPHONE_VOLUME); // 0xc (3), 0xffc0 (4), 0xff00 (4) - device_arctis.capability_details[CAP_SIDETONE] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; - device_arctis.capability_details[CAP_EQUALIZER_PRESET] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; - device_arctis.capability_details[CAP_EQUALIZER] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_SIDETONE] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_EQUALIZER_PRESET] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_EQUALIZER] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; device_arctis.capability_details[CAP_MICROPHONE_MUTE_LED_BRIGHTNESS] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; - device_arctis.capability_details[CAP_MICROPHONE_VOLUME] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; + device_arctis.capability_details[CAP_MICROPHONE_VOLUME] = (struct capability_detail) { .usagepage = 0xffc0, .usageid = 0x1, .interface = 4 }; device_arctis.send_sidetone = &arctis_nova_3_send_sidetone; device_arctis.send_equalizer_preset = &arctis_nova_3_send_equalizer_preset; @@ -102,7 +102,8 @@ static int arctis_nova_3_send_equalizer_preset(hid_device* device_handle, uint8_ } } -static int arctis_nova_3_send_equalizer(hid_device* device_handle, struct equalizer_settings* settings) { +static int arctis_nova_3_send_equalizer(hid_device* device_handle, struct equalizer_settings* settings) +{ if (settings->size != EQUALIZER_BANDS_SIZE) { printf("Device only supports %d bands.\n", EQUALIZER_BANDS_SIZE); return HSC_OUT_OF_BOUNDS; @@ -116,7 +117,8 @@ static int arctis_nova_3_send_equalizer(hid_device* device_handle, struct equali return hid_send_feature_report(device_handle, data, MSG_SIZE); } -static int arctis_nova_3_send_microphone_mute_led_brightness(hid_device* device_handle, uint8_t num) { +static int arctis_nova_3_send_microphone_mute_led_brightness(hid_device* device_handle, uint8_t num) +{ // This headset only supports 3 levels: // Off, low, medium (default), high @@ -126,7 +128,8 @@ static int arctis_nova_3_send_microphone_mute_led_brightness(hid_device* device_ return hid_send_feature_report(device_handle, SAVE_DATA, MSG_SIZE); } -static int arctis_nova_3_send_microphone_volume(hid_device* device_handle, uint8_t num) { +static int arctis_nova_3_send_microphone_volume(hid_device* device_handle, uint8_t num) +{ // This headset only supports 10 levels of microphone volume, but we allow a full range of 0-128 for it. Map the volume to the correct numbers. if (num < 13) { num = 0x00; From 68c85351c7669052791d1f05423e1231d4c9e84f Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 27 Dec 2023 13:56:36 +0100 Subject: [PATCH 3/3] Don't use short letters for new capabilities Signed-off-by: AnErrupTion --- src/main.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main.c b/src/main.c index 330b58c..ecaa215 100644 --- a/src/main.c +++ b/src/main.c @@ -320,6 +320,8 @@ int main(int argc, char* argv[]) { "help", no_argument, NULL, 'h' }, { "equalizer", required_argument, NULL, 'e' }, { "equalizer-preset", required_argument, NULL, 'p' }, + { "microphone-mute-led-brightness", required_argument, NULL, 0 }, + { "microphone-volume", required_argument, NULL, 0 }, { "inactive-time", required_argument, NULL, 'i' }, { "light", required_argument, NULL, 'l' }, { "follow", optional_argument, NULL, 'f' }, @@ -337,7 +339,7 @@ int main(int argc, char* argv[]) // Init all information of supported devices init_devices(); - while ((c = getopt_long(argc, argv, "bchi:l:f::mn:r:s:uv:p:t:o:e:?", opts, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "bchi:l:f::mn:r:s:uv:p:e:?", opts, &option_index)) != -1) { char* endptr = NULL; // for strtol switch (c) { @@ -411,22 +413,6 @@ int main(int argc, char* argv[]) return 1; } break; - case 't': - microphone_mute_led_brightness = strtol(optarg, &endptr, 10); - - if (*endptr != '\0' || endptr == optarg || microphone_mute_led_brightness < 0 || microphone_mute_led_brightness > 3) { - printf("Usage: %s -t 0-3\n", argv[0]); - return 1; - } - break; - case 'o': - microphone_volume = strtol(optarg, &endptr, 10); - - if (*endptr != '\0' || endptr == optarg || microphone_volume < 0 || microphone_volume > 128) { - printf("Usage: %s -o 0-128\n", argv[0]); - return 1; - } - break; case 'r': rotate_to_mute = strtol(optarg, &endptr, 10); if (*endptr != '\0' || endptr == optarg || rotate_to_mute < 0 || rotate_to_mute > 1) { @@ -470,8 +456,8 @@ int main(int argc, char* argv[]) printf(" -r, --rotate-to-mute 0|1\tTurn rotate to mute feature on or off (0 = off, 1 = on)\n"); printf(" -e, --equalizer string\tSets equalizer to specified curve, string must contain band values specific to the device (hex or decimal) delimited by spaces, or commas, or new-lines e.g \"0x18, 0x18, 0x18, 0x18, 0x18\".\n"); printf(" -p, --equalizer-preset number\tSets equalizer preset, number must be between 0 and 3, 0 sets the default\n"); - printf(" -t, --microphone-mute-led-brightness number\tSets microphone mute LED brightness, number must be between 0 and 3\n"); - printf(" -o, --microphone-volume number\tSets microphone volume, number must be between 0 and 128\n"); + printf(" --microphone-mute-led-brightness number\tSets microphone mute LED brightness, number must be between 0 and 3\n"); + printf(" --microphone-volume number\tSets microphone volume, number must be between 0 and 128\n"); printf(" -f, --follow [secs timeout]\tRe-run the commands after the specified seconds timeout or 2 by default\n"); printf("\n"); printf(" --timeout 0-100000\t\tSpecifies the timeout in ms for reading data from device (default 5000)\n"); @@ -493,6 +479,22 @@ int main(int argc, char* argv[]) return 1; } break; + } else if (strcmp(opts[option_index].name, "microphone-mute-led-brightness") == 0) { + microphone_mute_led_brightness = strtol(optarg, &endptr, 10); + + if (*endptr != '\0' || endptr == optarg || microphone_mute_led_brightness < 0 || microphone_mute_led_brightness > 3) { + printf("Usage: %s --microphone-mute-led-brightness 0-3\n", argv[0]); + return 1; + } + break; + } else if (strcmp(opts[option_index].name, "microphone-volume") == 0) { + microphone_volume = strtol(optarg, &endptr, 10); + + if (*endptr != '\0' || endptr == optarg || microphone_volume < 0 || microphone_volume > 128) { + printf("Usage: %s --microphone-volume 0-128\n", argv[0]); + return 1; + } + break; } // fall through default: