From f0e84da3bdf3da612075af3e8d6f7b9245243340 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:52:16 +0100 Subject: [PATCH 01/28] Added support for multiple devices through -d or --device --- src/main.c | 127 ++++++++++++++++++++++++++++++++++++++------------- src/output.c | 23 +++++----- 2 files changed, 107 insertions(+), 43 deletions(-) diff --git a/src/main.c b/src/main.c index 338521d..a187e9d 100644 --- a/src/main.c +++ b/src/main.c @@ -40,30 +40,65 @@ int test_profile = 0; int hsc_device_timeout = 5000; -/** - * This function iterates through all HID devices. - * - * @return 0 when a supported device is found - */ -static int find_device(struct device* device_found, int test_device) -{ - if (test_device) - return get_device(device_found, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE); +typedef struct DeviceListNode { + struct device* element; + struct DeviceListNode* next; +} DeviceListNode; +static int find_devices(DeviceList** device_list, int test_device) +{ + if (test_device){ + DeviceList* device_element = malloc(sizeof(DeviceList)); + device_element->device = malloc(sizeof(struct device)); + if(!get_device(device_element->device, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE)){ + *device_list = device_element; + return 1; + } else { + free(device_element->device); + free(device_element); + return 0; + } + } struct hid_device_info* devs; struct hid_device_info* cur_dev; - int found = -1; + int found = 0; devs = hid_enumerate(0x0, 0x0); cur_dev = devs; - while (cur_dev) { - found = get_device(device_found, cur_dev->vendor_id, cur_dev->product_id); - if (found == 0) { - break; + DeviceListNode* head = malloc(sizeof(DeviceListNode)); + DeviceListNode* devices_found = head; + devices_found->element = malloc(sizeof (struct device)); + struct device* last_device = NULL; + while (cur_dev) { + if(last_device != NULL && last_device->idVendor == cur_dev->vendor_id && last_device->idProduct == cur_dev->product_id){ + cur_dev = cur_dev->next; + continue; + } + if (!get_device(devices_found->element, cur_dev->vendor_id, cur_dev->product_id)) { + found ++; + last_device = devices_found->element; + devices_found->next = malloc(sizeof(struct DeviceListNode)); + devices_found = devices_found->next; + devices_found->element = malloc(sizeof(struct device)); } - cur_dev = cur_dev->next; } + free(devices_found->element); + free(devices_found); + + *device_list = malloc(sizeof(DeviceList) * found); + devices_found = head; + for(int i = 0; i < found; i++){ + DeviceList* device_element = *device_list + i; + device_element->device = devices_found->element; + device_element->num_devices = found - i; + device_element->featureRequests = NULL; + device_element->size = 0; + + devices_found = devices_found->next; + free(head); + head = devices_found; + } hid_free_enumeration(devs); return found; @@ -365,6 +400,10 @@ void print_help(char* programname, struct device* device_found, bool _show_all) // printf("Usage: %s [options]\n", programname); // printf("Options:\n"); + printf("Select device:\n"); + printf(" -d, --device INDEX\t\t\tSelects to which device send actions from 0 to N-1 (N = # of connected devices)\n"); + printf("\n"); + if (show_all || has_capability(device_found->capabilities, CAP_SIDETONE)) { printf("Sidetone:\n"); printf(" -s, --sidetone LEVEL\t\tSet sidetone level (0-128)\n"); @@ -521,6 +560,8 @@ int main(int argc, char* argv[]) { int c; + int selected_device = 0; + int should_print_help = 0; int should_print_help_all = 0; int print_udev_rules = 0; @@ -551,6 +592,7 @@ int main(int argc, char* argv[]) float* read_buffer = calloc(BUFFERLENGTH, sizeof(float)); struct option opts[] = { + { "device", required_argument, NULL, 'd' }, { "battery", no_argument, NULL, 'b' }, { "bt-call-volume", required_argument, NULL, 0 }, { "bt-when-powered-on", required_argument, NULL, 0 }, @@ -582,10 +624,17 @@ int main(int argc, char* argv[]) int option_index = 0; - while ((c = getopt_long(argc, argv, "bchi:l:f::mn:o::r:s:uv:p:e:?", opts, &option_index)) != -1) { + while ((c = getopt_long(argc, argv, "d:bchi:l:f::mn:o::r:s:uv:p:e:?", opts, &option_index)) != -1) { char* endptr = NULL; // for strtol switch (c) { + case 'd': + selected_device = strtol(optarg, &endptr, 10); + + if (*endptr != '\0' || endptr == optarg || selected_device < 0) { + fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); + return 1; + } case 'b': request_battery = 1; break; @@ -824,20 +873,31 @@ int main(int argc, char* argv[]) fprintf(stderr, "Non-option argument %s\n", argv[index]); } + DeviceList* devices_found = NULL; // describes the headsetcontrol device, when a headset was found - static struct device device_found; + struct device* device_selected = NULL; // Look for a supported device - int headset_available = find_device(&device_found, test_device); + int headset_available = find_devices(&devices_found, test_device); + + // User selected a device-index that is out of bounds + if(selected_device < 0 || headset_available < selected_device) { + fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); + return 1; + } + // User selected a device-index that is available + if( headset_available > 0 ){ + device_selected = devices_found[selected_device].device; + } if (should_print_help || should_print_help_all) { - if (headset_available == 0) - print_help(argv[0], &device_found, should_print_help_all); + if (headset_available > 0) + print_help(argv[0], device_selected, should_print_help_all); else print_help(argv[0], NULL, should_print_help_all); return 0; - } else if (headset_available != 0) { + } else if (headset_available == 0) { output(NULL, false, output_format); return 1; } @@ -879,7 +939,7 @@ int main(int argc, char* argv[]) if (output_format == OUTPUT_YAML || output_format == OUTPUT_JSON || output_format == OUTPUT_ENV) { for (int i = 0; i < numFeatures; i++) { if (featureRequests[i].type == CAPABILITYTYPE_INFO && !featureRequests[i].should_process) { - if ((device_found.capabilities & B(featureRequests[i].cap)) == B(featureRequests[i].cap)) { + if ((device_selected->capabilities & B(featureRequests[i].cap)) == B(featureRequests[i].cap)) { featureRequests[i].should_process = true; } } @@ -897,12 +957,12 @@ int main(int argc, char* argv[]) // probably wired meaning it is connected int battery_error = 0; - if ((device_found.capabilities & B(CAP_BATTERY_STATUS)) == B(CAP_BATTERY_STATUS)) { - device_handle = dynamic_connect(&hid_path, device_handle, &device_found, CAP_BATTERY_STATUS); + if ((device_selected->capabilities & B(CAP_BATTERY_STATUS)) == B(CAP_BATTERY_STATUS)) { + device_handle = dynamic_connect(&hid_path, device_handle, device_selected, CAP_BATTERY_STATUS); if (!device_handle) return 1; - BatteryInfo info = device_found.request_battery(device_handle); + BatteryInfo info = device_selected->request_battery(device_handle); if (info.status != BATTERY_AVAILABLE) { battery_error = 1; @@ -924,7 +984,7 @@ int main(int argc, char* argv[]) for (int i = 0; i < numFeatures; i++) { if (featureRequests[i].should_process) { // Assuming handle_feature now returns FeatureResult - featureRequests[i].result = handle_feature(&device_found, &device_handle, &hid_path, featureRequests[i].cap, featureRequests[i].param); + featureRequests[i].result = handle_feature(device_selected, &device_handle, &hid_path, featureRequests[i].cap, featureRequests[i].param); } else { // Populate with a default "not processed" result featureRequests[i].result.status = FEATURE_NOT_PROCESSED; @@ -933,13 +993,10 @@ int main(int argc, char* argv[]) } } - DeviceList deviceList; - deviceList.device = &device_found; - deviceList.num_devices = 1; - deviceList.featureRequests = featureRequests; - deviceList.size = numFeatures; + devices_found[selected_device].featureRequests = featureRequests; + devices_found[selected_device].size = numFeatures; - output(&deviceList, print_capabilities != -1, output_format); + output(devices_found, print_capabilities != -1, output_format); if (follow) sleep(follow_sec); @@ -956,6 +1013,12 @@ int main(int argc, char* argv[]) } free(equalizer); + for(int i=0;idevice_count); + for (int i = 0; i < status->device_count; i++) { HeadsetInfo* info = &infos[i]; if (info->product_name != NULL && wcslen(info->product_name) > 0) - printf("Found %s (%ls)!\n\n", info->device_name, info->product_name); + printf("[%d]%s (%ls)\n", i, info->device_name, info->product_name); else - printf("Found %s!\n\n", info->device_name); + printf("[%d]%s\n", i, info->device_name); if (print_capabilities) { - printf("Capabilities:\n"); + printf("\tCapabilities:\n"); for (int j = 0; j < info->capabilities_amount; j++) { - printf("* %s\n", info->capabilities_str[j]); + printf("\t* %s\n", info->capabilities_str[j]); } outputted = true; - - printf("\nHint: Use --help while the device is connected to get a filtered list of parameters\n"); + printf("\n"); continue; } @@ -772,22 +772,23 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin outputted = true; } - - break; // list info only one device supported for now + } + if(print_capabilities){ + printf("Hint: Use --help while the device is connected to get a filtered list of parameters\n"); } for (int i = 0; i < infos->action_count; i++) { outputted = true; if (infos->actions[i].status == STATUS_SUCCESS) { - printf("Successfully set %s!\n", infos->actions[i].capability_str); + printf("\nSuccessfully set %s!\n", infos->actions[i].capability_str); } else { printf("%s\n", infos->actions[i].error_message); } } if (!outputted) { - printf("HeadsetControl (%s) written by Sapd (Denis Arnst)\n\thttps://github.com/Sapd/HeadsetControl\n\n", VERSION); + printf("\nHeadsetControl (%s) written by Sapd (Denis Arnst)\n\thttps://github.com/Sapd/HeadsetControl\n\n", VERSION); printf("You didn't set any arguments, so nothing happened.\nUse -h for help.\n"); } } From 148f4490c2f299d87973b0b947605dffa4bf93f3 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Wed, 4 Dec 2024 18:54:33 +0100 Subject: [PATCH 02/28] clangd-formay fix --- src/main.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/main.c b/src/main.c index a187e9d..290ef8d 100644 --- a/src/main.c +++ b/src/main.c @@ -41,16 +41,16 @@ int test_profile = 0; int hsc_device_timeout = 5000; typedef struct DeviceListNode { - struct device* element; - struct DeviceListNode* next; + struct device* element; + struct DeviceListNode* next; } DeviceListNode; static int find_devices(DeviceList** device_list, int test_device) { - if (test_device){ + if (test_device) { DeviceList* device_element = malloc(sizeof(DeviceList)); - device_element->device = malloc(sizeof(struct device)); - if(!get_device(device_element->device, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE)){ + device_element->device = malloc(sizeof(struct device)); + if (!get_device(device_element->device, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE)) { *device_list = device_element; return 1; } else { @@ -65,20 +65,20 @@ static int find_devices(DeviceList** device_list, int test_device) devs = hid_enumerate(0x0, 0x0); cur_dev = devs; - DeviceListNode* head = malloc(sizeof(DeviceListNode)); + DeviceListNode* head = malloc(sizeof(DeviceListNode)); DeviceListNode* devices_found = head; - devices_found->element = malloc(sizeof (struct device)); - struct device* last_device = NULL; + devices_found->element = malloc(sizeof(struct device)); + struct device* last_device = NULL; while (cur_dev) { - if(last_device != NULL && last_device->idVendor == cur_dev->vendor_id && last_device->idProduct == cur_dev->product_id){ + if (last_device != NULL && last_device->idVendor == cur_dev->vendor_id && last_device->idProduct == cur_dev->product_id) { cur_dev = cur_dev->next; continue; } if (!get_device(devices_found->element, cur_dev->vendor_id, cur_dev->product_id)) { - found ++; - last_device = devices_found->element; - devices_found->next = malloc(sizeof(struct DeviceListNode)); - devices_found = devices_found->next; + found++; + last_device = devices_found->element; + devices_found->next = malloc(sizeof(struct DeviceListNode)); + devices_found = devices_found->next; devices_found->element = malloc(sizeof(struct device)); } cur_dev = cur_dev->next; @@ -86,14 +86,14 @@ static int find_devices(DeviceList** device_list, int test_device) free(devices_found->element); free(devices_found); - *device_list = malloc(sizeof(DeviceList) * found); + *device_list = malloc(sizeof(DeviceList) * found); devices_found = head; - for(int i = 0; i < found; i++){ - DeviceList* device_element = *device_list + i; - device_element->device = devices_found->element; - device_element->num_devices = found - i; + for (int i = 0; i < found; i++) { + DeviceList* device_element = *device_list + i; + device_element->device = devices_found->element; + device_element->num_devices = found - i; device_element->featureRequests = NULL; - device_element->size = 0; + device_element->size = 0; devices_found = devices_found->next; free(head); @@ -881,12 +881,12 @@ int main(int argc, char* argv[]) int headset_available = find_devices(&devices_found, test_device); // User selected a device-index that is out of bounds - if(selected_device < 0 || headset_available < selected_device) { + if (selected_device < 0 || headset_available < selected_device) { fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); return 1; } // User selected a device-index that is available - if( headset_available > 0 ){ + if (headset_available > 0) { device_selected = devices_found[selected_device].device; } @@ -1013,8 +1013,7 @@ int main(int argc, char* argv[]) } free(equalizer); - for(int i=0;i Date: Wed, 4 Dec 2024 18:55:35 +0100 Subject: [PATCH 03/28] Update output.c --- src/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/output.c b/src/output.c index 38ce662..23beb1a 100644 --- a/src/output.c +++ b/src/output.c @@ -773,7 +773,7 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin outputted = true; } } - if(print_capabilities){ + if (print_capabilities) { printf("Hint: Use --help while the device is connected to get a filtered list of parameters\n"); } From 0167b11b71444f45892dafc8d564737110de46cf Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:24:53 +0100 Subject: [PATCH 04/28] Fixed output of actions for multiple devices --- src/main.c | 1 + src/output.c | 142 +++++++++++++++++++++++++++++---------------------- 2 files changed, 82 insertions(+), 61 deletions(-) diff --git a/src/main.c b/src/main.c index 290ef8d..4c79f00 100644 --- a/src/main.c +++ b/src/main.c @@ -873,6 +873,7 @@ int main(int argc, char* argv[]) fprintf(stderr, "Non-option argument %s\n", argv[index]); } + // The array list of compatible devices DeviceList* devices_found = NULL; // describes the headsetcontrol device, when a headset was found struct device* device_selected = NULL; diff --git a/src/output.c b/src/output.c index 23beb1a..2a75b0b 100644 --- a/src/output.c +++ b/src/output.c @@ -305,33 +305,39 @@ void output_json(HeadsetControlStatus* status, HeadsetInfo* infos) json_print_key_value("hidapi_version", status->hid_version, 2); printf(",\n"); - if (infos && infos->action_count > 0) { - printf(" \"actions\": [\n"); - for (int i = 0; i < infos->action_count; i++) { - printf(" {\n"); - - json_print_key_value("capability", infos->actions[i].capability, 6); - printf(",\n"); - json_print_key_value("device", infos->actions[i].device, 6); - printf(",\n"); - json_print_key_value("status", status_to_string(infos->actions[i].status), 6); + if (infos != NULL) { + for (int j = 0; j < status->device_count; j++) { + HeadsetInfo* info = &infos[j]; + if (info->action_count > 0) { + printf(" \"actions\": [\n"); + for (int i = 0; i < info->action_count; i++) { + printf(" {\n"); + + json_print_key_value("capability", info->actions[i].capability, 6); + printf(",\n"); + json_print_key_value("device", info->actions[i].device, 6); + printf(",\n"); + json_print_key_value("status", status_to_string(info->actions[i].status), 6); - if (infos->actions[i].value > 0) { - printf(",\n"); - json_printint_key_value("value", infos->actions[i].value, 6); - } + if (info->actions[i].value > 0) { + printf(",\n"); + json_printint_key_value("value", info->actions[i].value, 6); + } - if (infos->actions[i].error_message != NULL && strlen(infos->actions[i].error_message) > 0) { - printf(",\n"); - json_print_key_value("error_message", infos->actions[i].error_message, 6); - } + if (info->actions[i].error_message != NULL && strlen(info->actions[i].error_message) > 0) { + printf(",\n"); + json_print_key_value("error_message", info->actions[i].error_message, 6); + } - printf("\n }"); - if (i < infos->action_count - 1) { - printf(",\n"); + printf("\n }"); + if (i < info->action_count - 1) { + printf(",\n"); + } + } + printf("\n ],\n"); + break; } } - printf("\n ],\n"); } // For integers, direct printing is still simplest @@ -527,17 +533,22 @@ void output_yaml(HeadsetControlStatus* status, HeadsetInfo* infos) yaml_print("api_version", status->api_version, 0); yaml_print("hidapi_version", status->hid_version, 0); - if (infos && infos->action_count > 0) { - yaml_print("actions", "", 0); - - for (int i = 0; i < infos->action_count; i++) { - yaml_print("- capability", infos->actions[i].capability, 2); - yaml_print("device", infos->actions[i].device, 4); - yaml_print("status", status_to_string(infos->actions[i].status), 4); - if (infos->actions[i].value > 0) - yaml_printint("value", infos->actions[i].value, 4); - if (infos->actions[i].error_message != NULL && strlen(infos->actions[i].error_message) > 0) { - yaml_print("error_message", infos->actions[i].error_message, 4); + if (infos != NULL) { + for (int j = 0; j < status->device_count; j++) { + HeadsetInfo* info = &infos[j]; + if (info->action_count > 0) { + yaml_print("actions", "", 0); + for (int i = 0; i < info->action_count; i++) { + yaml_print("- capability", info->actions[i].capability, 2); + yaml_print("device", info->actions[i].device, 4); + yaml_print("status", status_to_string(info->actions[i].status), 4); + if (info->actions[i].value > 0) + yaml_printint("value", info->actions[i].value, 4); + if (info->actions[i].error_message != NULL && strlen(info->actions[i].error_message) > 0) { + yaml_print("error_message", info->actions[i].error_message, 4); + } + } + break; } } } @@ -653,29 +664,35 @@ void output_env(HeadsetControlStatus* status, HeadsetInfo* infos) env_print("HEADSETCONTROL_API_VERSION", status->api_version); env_print("HEADSETCONTROL_HIDAPI_VERSION", status->hid_version); - if (infos) { - env_printint("ACTION_COUNT", infos->action_count); - for (int i = 0; i < infos->action_count; i++) { - char prefix[64]; - sprintf(prefix, "ACTION_%d", i); - - char key[128]; - - sprintf(key, "%s_CAPABILITY", prefix); - env_print(key, infos->actions[i].capability); - sprintf(key, "%s_DEVICE", prefix); - env_print(key, infos->actions[i].device); - sprintf(key, "%s_STATUS", prefix); - env_print(key, status_to_string(infos->actions[i].status)); - - if (infos->actions[i].value > 0) { - sprintf(key, "%s_VALUE", prefix); - env_printint(key, infos->actions[i].value); - } + if (infos != NULL) { + for (int j = 0; j < status->device_count; j++) { + HeadsetInfo* info = &infos[j]; + if (info->action_count > 0) { + env_printint("ACTION_COUNT", info->action_count); + for (int i = 0; i < info->action_count; i++) { + char prefix[64]; + sprintf(prefix, "ACTION_%d", i); + + char key[128]; + + sprintf(key, "%s_CAPABILITY", prefix); + env_print(key, info->actions[i].capability); + sprintf(key, "%s_DEVICE", prefix); + env_print(key, info->actions[i].device); + sprintf(key, "%s_STATUS", prefix); + env_print(key, status_to_string(info->actions[i].status)); + + if (info->actions[i].value > 0) { + sprintf(key, "%s_VALUE", prefix); + env_printint(key, info->actions[i].value); + } - if (infos->actions[i].error_message != NULL && strlen(infos->actions[i].error_message) > 0) { - sprintf(key, "%s_ERROR_MESSAGE", prefix); - env_print(key, infos->actions[i].error_message); + if (info->actions[i].error_message != NULL && strlen(info->actions[i].error_message) > 0) { + sprintf(key, "%s_ERROR_MESSAGE", prefix); + env_print(key, info->actions[i].error_message); + } + } + break; } } } else { @@ -777,13 +794,16 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin printf("Hint: Use --help while the device is connected to get a filtered list of parameters\n"); } - for (int i = 0; i < infos->action_count; i++) { - outputted = true; + for (int j = 0; j < status->device_count; j++) { + HeadsetInfo* info = &infos[j]; + for (int i = 0; i < info->action_count; i++) { + outputted = true; - if (infos->actions[i].status == STATUS_SUCCESS) { - printf("\nSuccessfully set %s!\n", infos->actions[i].capability_str); - } else { - printf("%s\n", infos->actions[i].error_message); + if (info->actions[i].status == STATUS_SUCCESS) { + printf("\nSuccessfully set %s!", info->actions[i].capability_str); + } else { + printf("\n%s", info->actions[i].error_message); + } } } From c3f7cb041f5961dc1c5292ada56649b20f99fddd Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 14:56:35 +0100 Subject: [PATCH 05/28] Small fix --- src/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 4c79f00..53423a6 100644 --- a/src/main.c +++ b/src/main.c @@ -882,14 +882,12 @@ int main(int argc, char* argv[]) int headset_available = find_devices(&devices_found, test_device); // User selected a device-index that is out of bounds - if (selected_device < 0 || headset_available < selected_device) { + if (selected_device < 0 || selected_device >= headset_available) { fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); return 1; } // User selected a device-index that is available - if (headset_available > 0) { - device_selected = devices_found[selected_device].device; - } + device_selected = devices_found[selected_device].device; if (should_print_help || should_print_help_all) { if (headset_available > 0) From bae379c4f0c595b33b5658bb3bbef565d1b11da2 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 14:57:16 +0100 Subject: [PATCH 06/28] Adding test_device to connected device list --- src/main.c | 62 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/main.c b/src/main.c index 53423a6..3f8649f 100644 --- a/src/main.c +++ b/src/main.c @@ -47,57 +47,59 @@ typedef struct DeviceListNode { static int find_devices(DeviceList** device_list, int test_device) { + DeviceListNode* devices_found = malloc(sizeof(DeviceListNode)); + devices_found->element = malloc(sizeof(struct device)); + DeviceListNode* curr_node = devices_found; + + int found = 0; + + // Adding test device if (test_device) { - DeviceList* device_element = malloc(sizeof(DeviceList)); - device_element->device = malloc(sizeof(struct device)); - if (!get_device(device_element->device, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE)) { - *device_list = device_element; - return 1; - } else { - free(device_element->device); - free(device_element); - return 0; + if (!get_device(devices_found->element, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE)) { + curr_node->next = malloc(sizeof(struct DeviceListNode)); + curr_node->next->element = malloc(sizeof(struct device)); + curr_node = devices_found->next; + found++; } } + struct hid_device_info* devs; struct hid_device_info* cur_dev; - int found = 0; - devs = hid_enumerate(0x0, 0x0); - cur_dev = devs; + struct device* last_device = NULL; + devs = hid_enumerate(0x0, 0x0); + cur_dev = devs; - DeviceListNode* head = malloc(sizeof(DeviceListNode)); - DeviceListNode* devices_found = head; - devices_found->element = malloc(sizeof(struct device)); - struct device* last_device = NULL; + // Iterate through all devices and the compatible to device_found list while (cur_dev) { - if (last_device != NULL && last_device->idVendor == cur_dev->vendor_id && last_device->idProduct == cur_dev->product_id) { + if (false && last_device != NULL && last_device->idVendor == cur_dev->vendor_id && last_device->idProduct == cur_dev->product_id) { cur_dev = cur_dev->next; continue; } - if (!get_device(devices_found->element, cur_dev->vendor_id, cur_dev->product_id)) { + if (!get_device(curr_node->element, cur_dev->vendor_id, cur_dev->product_id)) { found++; - last_device = devices_found->element; - devices_found->next = malloc(sizeof(struct DeviceListNode)); - devices_found = devices_found->next; - devices_found->element = malloc(sizeof(struct device)); + last_device = curr_node->element; + curr_node->next = malloc(sizeof(struct DeviceListNode)); + curr_node->next->element = malloc(sizeof(struct device)); + curr_node = curr_node->next; } cur_dev = cur_dev->next; } - free(devices_found->element); - free(devices_found); + free(curr_node->element); + free(curr_node); - *device_list = malloc(sizeof(DeviceList) * found); - devices_found = head; + // Copy by address the found devices to the device_list + *device_list = malloc(sizeof(DeviceList) * found); + curr_node = devices_found; for (int i = 0; i < found; i++) { DeviceList* device_element = *device_list + i; - device_element->device = devices_found->element; + device_element->device = curr_node->element; device_element->num_devices = found - i; device_element->featureRequests = NULL; device_element->size = 0; - devices_found = devices_found->next; - free(head); - head = devices_found; + curr_node = curr_node->next; + free(devices_found); + devices_found = curr_node; } hid_free_enumeration(devs); From 63c82700e4f76caca5d26c0a7dcdd8726139e6d8 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 14:57:52 +0100 Subject: [PATCH 07/28] Improved --connected for test_device --- src/main.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index 3f8649f..df6cf26 100644 --- a/src/main.c +++ b/src/main.c @@ -948,30 +948,31 @@ int main(int argc, char* argv[]) } if (request_connected) { - if (test_device) { - printf("true\n"); - return 0; - } - + int is_test_device = selected_device == 0 && test_device; // Check if battery status can be read // If it isn't supported, the device is // probably wired meaning it is connected int battery_error = 0; + BatteryInfo info; if ((device_selected->capabilities & B(CAP_BATTERY_STATUS)) == B(CAP_BATTERY_STATUS)) { - device_handle = dynamic_connect(&hid_path, device_handle, device_selected, CAP_BATTERY_STATUS); - if (!device_handle) - return 1; - - BatteryInfo info = device_selected->request_battery(device_handle); + if (!is_test_device) { + device_handle = dynamic_connect(&hid_path, device_handle, device_selected, CAP_BATTERY_STATUS); + if (!device_handle) { + fprintf(stderr, "Error while getting device handle.\n"); + return 1; + } + info = device_selected->request_battery(device_handle); + terminate_hid(&device_handle, &hid_path); + } else { + info = device_selected->request_battery(device_handle); + } if (info.status != BATTERY_AVAILABLE) { battery_error = 1; } } - terminate_hid(&device_handle, &hid_path); - if (battery_error != 0) { printf("false\n"); return 1; From 7056ae178c842c112382bb00493355db7c7422e0 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:34:15 +0100 Subject: [PATCH 08/28] Added support for -d [vendorId:productId] --- src/dev.c | 2 +- src/dev.h | 2 ++ src/main.c | 35 +++++++++++++++++++++++++---------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/dev.c b/src/dev.c index fea8d74..1fbce77 100644 --- a/src/dev.c +++ b/src/dev.c @@ -69,7 +69,7 @@ int check_range(int number, int low, int high) * @param id2 the secound it * @return int 0 if successfull, or 1 if not two ids provided */ -static int get_two_ids(char* input, int* id1, int* id2) +int get_two_ids(char* input, int* id1, int* id2) { const char* delim = " :.,"; diff --git a/src/dev.h b/src/dev.h index b7db835..4dd83b4 100644 --- a/src/dev.h +++ b/src/dev.h @@ -1,3 +1,5 @@ #pragma once +int get_two_ids(char* input, int* id1, int* id2); + int dev_main(int argc, char* argv[]); diff --git a/src/main.c b/src/main.c index df6cf26..d9be658 100644 --- a/src/main.c +++ b/src/main.c @@ -66,8 +66,8 @@ static int find_devices(DeviceList** device_list, int test_device) struct hid_device_info* devs; struct hid_device_info* cur_dev; struct device* last_device = NULL; - devs = hid_enumerate(0x0, 0x0); - cur_dev = devs; + devs = hid_enumerate(0x0, 0x0); + cur_dev = devs; // Iterate through all devices and the compatible to device_found list while (cur_dev) { @@ -562,7 +562,9 @@ int main(int argc, char* argv[]) { int c; - int selected_device = 0; + int selected_device = 0; + int selected_device_id1 = -1; + int selected_device_id2 = -1; int should_print_help = 0; int should_print_help_all = 0; @@ -630,13 +632,17 @@ int main(int argc, char* argv[]) char* endptr = NULL; // for strtol switch (c) { - case 'd': - selected_device = strtol(optarg, &endptr, 10); - - if (*endptr != '\0' || endptr == optarg || selected_device < 0) { - fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); - return 1; + case 'd': { + int parsed_correctly = get_two_ids(optarg, &selected_device_id1, &selected_device_id2); + if (parsed_correctly == 1) { + selected_device = strtol(optarg, &endptr, 10); + if (*endptr != '\0' || endptr == optarg || selected_device < 0) { + fprintf(stderr, "Usage: %s -d [0-N] | [vendorid:deviceid] (N = Number of connected devices - 1)\n", argv[0]); + return 1; + } } + break; + } case 'b': request_battery = 1; break; @@ -877,7 +883,7 @@ int main(int argc, char* argv[]) // The array list of compatible devices DeviceList* devices_found = NULL; - // describes the headsetcontrol device, when a headset was found + // Describes the headsetcontrol device, when a headset was found struct device* device_selected = NULL; // Look for a supported device @@ -888,6 +894,15 @@ int main(int argc, char* argv[]) fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); return 1; } + + if (selected_device_id1 != -1 && selected_device_id2 != -1) { + for (int i = 0; i < headset_available; i++) { + if (devices_found[i].device->idVendor == selected_device_id1 && devices_found[i].device->idProduct == selected_device_id2) { + selected_device = i; + break; + } + } + } // User selected a device-index that is available device_selected = devices_found[selected_device].device; From e55daa30e8b9ac32c81968423a8cde9f87b6682f Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 15:46:43 +0100 Subject: [PATCH 09/28] Fixed for test --- src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index d9be658..785b42b 100644 --- a/src/main.c +++ b/src/main.c @@ -890,8 +890,8 @@ int main(int argc, char* argv[]) int headset_available = find_devices(&devices_found, test_device); // User selected a device-index that is out of bounds - if (selected_device < 0 || selected_device >= headset_available) { - fprintf(stderr, "Usage: %s -d 0-N (N = Number of connected devices - 1)\n", argv[0]); + if (selected_device != 0 && (selected_device < 0 || selected_device >= headset_available)) { + fprintf(stderr, "Usage: %s -d [0-N] | [vendorid:deviceid] (N = Number of connected devices - 1)\n", argv[0]); return 1; } From 4139f14ea1cd9bda9b23205eb84e519411ea49b0 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 16:53:45 +0100 Subject: [PATCH 10/28] Updated find_devices() to recognise devices only once --- src/main.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 785b42b..8597b98 100644 --- a/src/main.c +++ b/src/main.c @@ -50,7 +50,6 @@ static int find_devices(DeviceList** device_list, int test_device) DeviceListNode* devices_found = malloc(sizeof(DeviceListNode)); devices_found->element = malloc(sizeof(struct device)); DeviceListNode* curr_node = devices_found; - int found = 0; // Adding test device @@ -65,19 +64,27 @@ static int find_devices(DeviceList** device_list, int test_device) struct hid_device_info* devs; struct hid_device_info* cur_dev; - struct device* last_device = NULL; devs = hid_enumerate(0x0, 0x0); cur_dev = devs; + bool already_found = false; // Iterate through all devices and the compatible to device_found list while (cur_dev) { - if (false && last_device != NULL && last_device->idVendor == cur_dev->vendor_id && last_device->idProduct == cur_dev->product_id) { + already_found = false; + DeviceListNode* temp_node = devices_found; + while (temp_node != curr_node) { + if (temp_node->element->idVendor == cur_dev->vendor_id && temp_node->element->idProduct == cur_dev->product_id) { + already_found = true; + break; + } + temp_node = temp_node->next; + } + if (already_found) { cur_dev = cur_dev->next; continue; } if (!get_device(curr_node->element, cur_dev->vendor_id, cur_dev->product_id)) { found++; - last_device = curr_node->element; curr_node->next = malloc(sizeof(struct DeviceListNode)); curr_node->next->element = malloc(sizeof(struct device)); curr_node = curr_node->next; From 9681924f294df094fc6180b047cc54a35819e96e Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:09:51 +0100 Subject: [PATCH 11/28] clangd-format-fix --- src/main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.c b/src/main.c index 8597b98..ea2b9af 100644 --- a/src/main.c +++ b/src/main.c @@ -50,7 +50,7 @@ static int find_devices(DeviceList** device_list, int test_device) DeviceListNode* devices_found = malloc(sizeof(DeviceListNode)); devices_found->element = malloc(sizeof(struct device)); DeviceListNode* curr_node = devices_found; - int found = 0; + int found = 0; // Adding test device if (test_device) { @@ -64,13 +64,13 @@ static int find_devices(DeviceList** device_list, int test_device) struct hid_device_info* devs; struct hid_device_info* cur_dev; - devs = hid_enumerate(0x0, 0x0); - cur_dev = devs; - bool already_found = false; + devs = hid_enumerate(0x0, 0x0); + cur_dev = devs; + bool already_found = false; // Iterate through all devices and the compatible to device_found list while (cur_dev) { - already_found = false; + already_found = false; DeviceListNode* temp_node = devices_found; while (temp_node != curr_node) { if (temp_node->element->idVendor == cur_dev->vendor_id && temp_node->element->idProduct == cur_dev->product_id) { From 54ba1c97148e3a0b458d3408670ded8cc55bbdca Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:22:54 +0100 Subject: [PATCH 12/28] Moved get_two_ids() from dev.c to utility.c --- src/dev.c | 39 --------------------------------------- src/dev.h | 2 -- src/utility.c | 31 +++++++++++++++++++++++++++++++ src/utility.h | 10 ++++++++++ 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/dev.c b/src/dev.c index 1fbce77..0707d7d 100644 --- a/src/dev.c +++ b/src/dev.c @@ -61,45 +61,6 @@ int check_range(int number, int low, int high) return 0; } -/** - * @brief Accept an string input like 123:456 and splits them into two ids - * - * @param input input string - * @param id1 the first (left) id - * @param id2 the secound it - * @return int 0 if successfull, or 1 if not two ids provided - */ -int get_two_ids(char* input, int* id1, int* id2) -{ - const char* delim = " :.,"; - - size_t sz = strlen(input); - char* str = (char*)malloc(sz + 1); - strcpy(str, input); - - char* token = strtok(input, delim); - int i = 0; - while (token) { - char* endptr; - long int val = strtol(token, &endptr, 0); - - if (i == 0) - *id1 = val; - else if (i == 1) - *id2 = val; - - i++; - token = strtok(NULL, delim); - } - - free(str); - - if (i != 2) // not exactly supplied two ids - return 1; - - return 0; -} - static void print_help() { printf("HeadsetControl Developer menu. Take caution.\n\n"); diff --git a/src/dev.h b/src/dev.h index 4dd83b4..b7db835 100644 --- a/src/dev.h +++ b/src/dev.h @@ -1,5 +1,3 @@ #pragma once -int get_two_ids(char* input, int* id1, int* id2); - int dev_main(int argc, char* argv[]); diff --git a/src/utility.c b/src/utility.c index b618563..0e5c79d 100644 --- a/src/utility.c +++ b/src/utility.c @@ -137,6 +137,37 @@ int get_float_data_from_parameter(char* input, float* dest, size_t len) return i; } +int get_two_ids(char* input, int* id1, int* id2) +{ + const char* delim = " :.,"; + + size_t sz = strlen(input); + char* str = (char*)malloc(sz + 1); + strcpy(str, input); + + char* token = strtok(input, delim); + int i = 0; + while (token) { + char* endptr; + long int val = strtol(token, &endptr, 0); + + if (i == 0) + *id1 = val; + else if (i == 1) + *id2 = val; + + i++; + token = strtok(NULL, delim); + } + + free(str); + + if (i != 2) // not exactly supplied two ids + return 1; + + return 0; +} + // ----------------- asprintf / vasprintf ----------------- /* * Copyright (c) 2004 Darren Tucker. diff --git a/src/utility.h b/src/utility.h index f12568d..5e23114 100644 --- a/src/utility.h +++ b/src/utility.h @@ -92,6 +92,16 @@ int get_byte_data_from_parameter(char* input, unsigned char* dest, size_t len); */ int get_float_data_from_parameter(char* input, float* dest, size_t len); +/** + * @brief Accept an string input like 123:456 and splits them into two ids + * + * @param input input string + * @param id1 the first (left) id + * @param id2 the secound it + * @return int 0 if successfull, or 1 if not two ids provided + */ +int get_two_ids(char* input, int* id1, int* id2); + int vasprintf(char** str, const char* fmt, va_list ap); int _asprintf(char** str, const char* fmt, ...); From 855b7dfc99e2785272e8668b917dbafa7a175104 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Tue, 10 Dec 2024 14:46:41 +0100 Subject: [PATCH 13/28] Added comment to find_devices(), moved DeviceListNode to device.h --- src/device.h | 11 +++++++++++ src/main.c | 15 ++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/device.h b/src/device.h index 71f6f60..f8f49b1 100644 --- a/src/device.h +++ b/src/device.h @@ -394,3 +394,14 @@ struct device { */ int (*send_bluetooth_call_volume)(hid_device* hid_device, uint8_t num); }; + +/** + * @brief Node structure for a linked list of devices. + * + * This structure represents a node in a linked list where each node contains a pointer to a device + * and a pointer to the next node in the list. + */ +typedef struct DeviceListNode { + struct device* element; + struct DeviceListNode* next; +} DeviceListNode; diff --git a/src/main.c b/src/main.c index ea2b9af..52a3c4f 100644 --- a/src/main.c +++ b/src/main.c @@ -40,11 +40,16 @@ int test_profile = 0; int hsc_device_timeout = 5000; -typedef struct DeviceListNode { - struct device* element; - struct DeviceListNode* next; -} DeviceListNode; - +/** + * @brief Finds and initializes a list of devices. + * + * This function allocates a list of devices. + * If the test_device flag is set, it attempts to add a test device to the list. + * + * @param device_list A pointer to the list of devices to be populated. + * @param test_device A flag indicating whether to add a test device to the list. + * @return The number of devices found and added to the list. + */ static int find_devices(DeviceList** device_list, int test_device) { DeviceListNode* devices_found = malloc(sizeof(DeviceListNode)); From 6470bc07ccb231804eddcb484a14b7969ea29820 Mon Sep 17 00:00:00 2001 From: Denis Arnst Date: Tue, 14 Jan 2025 16:48:32 +0100 Subject: [PATCH 14/28] Tidy up texts --- src/main.c | 3 ++- src/output.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.c b/src/main.c index 52a3c4f..62745ec 100644 --- a/src/main.c +++ b/src/main.c @@ -415,7 +415,8 @@ void print_help(char* programname, struct device* device_found, bool _show_all) // printf("Options:\n"); printf("Select device:\n"); - printf(" -d, --device INDEX\t\t\tSelects to which device send actions from 0 to N-1 (N = # of connected devices)\n"); + printf(" -d, --device INDEX|vendorid:productid\n"); + printf("\t\t\t\tSpecify either an index (0 to N-1) or a vendor ID and product ID separated by a colon.\n"); printf("\n"); if (show_all || has_capability(device_found->capabilities, CAP_SIDETONE)) { diff --git a/src/output.c b/src/output.c index 2a75b0b..eb77f4c 100644 --- a/src/output.c +++ b/src/output.c @@ -754,9 +754,9 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin for (int i = 0; i < status->device_count; i++) { HeadsetInfo* info = &infos[i]; if (info->product_name != NULL && wcslen(info->product_name) > 0) - printf("[%d]%s (%ls)\n", i, info->device_name, info->product_name); + printf(" [%d] %s (%ls)\n", i, info->device_name, info->product_name); else - printf("[%d]%s\n", i, info->device_name); + printf(" [%d] %s\n", i, info->device_name); if (print_capabilities) { printf("\tCapabilities:\n"); From 312a42bf93f58d966e6eec21e8b8d1039a0133c6 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 2 Feb 2025 22:35:09 +0100 Subject: [PATCH 15/28] Improved help printing --- src/device.c | 7 ++++++ src/device.h | 7 ++---- src/main.c | 70 ++++++++++++++++++++++++---------------------------- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/device.c b/src/device.c index 6c22f40..0769635 100644 --- a/src/device.c +++ b/src/device.c @@ -57,3 +57,10 @@ const char capabilities_str_short[NUM_CAPABILITIES] [CAP_BT_WHEN_POWERED_ON] = '\0', [CAP_BT_CALL_VOLUME] = '\0' }; + +bool device_has_capability(struct device* device, enum capabilities cap) +{ + if (device == NULL) + return false; + return (device->capabilities & B(cap)) == B(cap); +} \ No newline at end of file diff --git a/src/device.h b/src/device.h index f8f49b1..dc56abb 100644 --- a/src/device.h +++ b/src/device.h @@ -54,11 +54,6 @@ extern const char capabilities_str_short[NUM_CAPABILITIES]; /// Enum name of every capability extern const char* const capabilities_str_enum[NUM_CAPABILITIES]; -static inline bool has_capability(int device_capabilities, enum capabilities cap) -{ - return (device_capabilities & B(cap)) == B(cap); -} - struct capability_detail { // Usage page, only used when usageid is not 0; HID Protocol specific uint16_t usagepage; @@ -405,3 +400,5 @@ typedef struct DeviceListNode { struct device* element; struct DeviceListNode* next; } DeviceListNode; + +bool device_has_capability(struct device* device, enum capabilities cap); \ No newline at end of file diff --git a/src/main.c b/src/main.c index 62745ec..2d57e0b 100644 --- a/src/main.c +++ b/src/main.c @@ -165,7 +165,7 @@ static void print_readmetable() printf("| %s |", device_found->device_name); for (int j = 0; j < NUM_CAPABILITIES; j++) { - if (has_capability(device_found->capabilities, j)) { + if (device_has_capability(device_found, j)) { printf(" x |"); } else { printf(" |"); @@ -405,10 +405,8 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de return result; } -void print_help(char* programname, struct device* device_found, bool _show_all) +void print_help(char* programname, struct device* device_found, bool show_all) { - bool show_all = !device_found || _show_all; - printf("HeadsetControl by Sapd (Denis Arnst)\n\thttps://github.com/Sapd/HeadsetControl\n\n"); printf("Version: %s\n\n", VERSION); // printf("Usage: %s [options]\n", programname); @@ -419,21 +417,21 @@ void print_help(char* programname, struct device* device_found, bool _show_all) printf("\t\t\t\tSpecify either an index (0 to N-1) or a vendor ID and product ID separated by a colon.\n"); printf("\n"); - if (show_all || has_capability(device_found->capabilities, CAP_SIDETONE)) { + if (show_all || device_has_capability(device_found, CAP_SIDETONE)) { printf("Sidetone:\n"); printf(" -s, --sidetone LEVEL\t\tSet sidetone level (0-128)\n"); printf("\n"); } - if (show_all || has_capability(device_found->capabilities, CAP_BATTERY_STATUS)) { + if (show_all || device_has_capability(device_found, CAP_BATTERY_STATUS)) { printf("Battery:\n"); printf(" -b, --battery\t\t\tCheck battery level\n"); printf("\n"); } // ------ Category: lights and notifications - bool show_lights = show_all || has_capability(device_found->capabilities, CAP_LIGHTS); - bool show_voice_prompts = show_all || has_capability(device_found->capabilities, CAP_VOICE_PROMPTS); + bool show_lights = show_all || device_has_capability(device_found, CAP_LIGHTS); + bool show_voice_prompts = show_all || device_has_capability(device_found, CAP_VOICE_PROMPTS); if (show_lights || show_voice_prompts) { printf("%s:\n", (show_lights && show_voice_prompts) ? "Lights and Voice Prompts" : (show_lights ? "Lights" : "Voice Prompts")); @@ -448,10 +446,10 @@ void print_help(char* programname, struct device* device_found, bool _show_all) // ------ // ------ Category: Features - bool show_inactive_time = show_all || has_capability(device_found->capabilities, CAP_INACTIVE_TIME); - bool show_chatmix_status = show_all || has_capability(device_found->capabilities, CAP_CHATMIX_STATUS); - bool show_notification_sound = show_all || has_capability(device_found->capabilities, CAP_NOTIFICATION_SOUND); - bool show_volume_limiter = show_all || has_capability(device_found->capabilities, CAP_VOLUME_LIMITER); + bool show_inactive_time = show_all || device_has_capability(device_found, CAP_INACTIVE_TIME); + bool show_chatmix_status = show_all || device_has_capability(device_found, CAP_CHATMIX_STATUS); + bool show_notification_sound = show_all || device_has_capability(device_found, CAP_NOTIFICATION_SOUND); + bool show_volume_limiter = show_all || device_has_capability(device_found, CAP_VOLUME_LIMITER); if (show_inactive_time || show_chatmix_status || show_notification_sound) { printf("Features:\n"); @@ -472,8 +470,8 @@ void print_help(char* programname, struct device* device_found, bool _show_all) // ------ // ------ Category: Equalizer - bool show_equalizer = show_all || has_capability(device_found->capabilities, CAP_EQUALIZER); - bool show_equalizer_preset = show_all || has_capability(device_found->capabilities, CAP_EQUALIZER_PRESET); + bool show_equalizer = show_all || device_has_capability(device_found, CAP_EQUALIZER); + bool show_equalizer_preset = show_all || device_has_capability(device_found, CAP_EQUALIZER_PRESET); if (show_equalizer || show_equalizer_preset) { printf("Equalizer:\n"); @@ -488,9 +486,9 @@ void print_help(char* programname, struct device* device_found, bool _show_all) // ------ // ------ Category: Microphone - bool show_rotate_to_mute = show_all || has_capability(device_found->capabilities, CAP_ROTATE_TO_MUTE); - bool show_microphone_mute_led_brightness = show_all || has_capability(device_found->capabilities, CAP_MICROPHONE_MUTE_LED_BRIGHTNESS); - bool show_microphone_volume = show_all || has_capability(device_found->capabilities, CAP_MICROPHONE_VOLUME); + bool show_rotate_to_mute = show_all || device_has_capability(device_found, CAP_ROTATE_TO_MUTE); + bool show_microphone_mute_led_brightness = show_all || device_has_capability(device_found, CAP_MICROPHONE_MUTE_LED_BRIGHTNESS); + bool show_microphone_volume = show_all || device_has_capability(device_found, CAP_MICROPHONE_VOLUME); if (show_rotate_to_mute || show_microphone_mute_led_brightness || show_microphone_volume) { printf("Microphone:\n"); @@ -508,8 +506,8 @@ void print_help(char* programname, struct device* device_found, bool _show_all) // ------ // ------ Category: Bluetooth - bool show_bt_when_powered_on = show_all || has_capability(device_found->capabilities, CAP_BT_WHEN_POWERED_ON); - bool show_bt_call_volume = show_all || has_capability(device_found->capabilities, CAP_BT_CALL_VOLUME); + bool show_bt_when_powered_on = show_all || device_has_capability(device_found, CAP_BT_WHEN_POWERED_ON); + bool show_bt_call_volume = show_all || device_has_capability(device_found, CAP_BT_CALL_VOLUME); if (show_bt_when_powered_on || show_bt_call_volume) { printf("Bluetooth:\n"); @@ -540,19 +538,19 @@ void print_help(char* programname, struct device* device_found, bool _show_all) printf("\n"); } - if (show_all || has_capability(device_found->capabilities, CAP_SIDETONE) || has_capability(device_found->capabilities, CAP_BATTERY_STATUS)) { + if (show_all || device_has_capability(device_found, CAP_SIDETONE) || device_has_capability(device_found, CAP_BATTERY_STATUS)) { printf("Examples:\n"); - if (show_all || has_capability(device_found->capabilities, CAP_BATTERY_STATUS)) + if (show_all || device_has_capability(device_found, CAP_BATTERY_STATUS)) printf(" %s -b\t\tCheck the battery level\n", programname); - if (show_all || has_capability(device_found->capabilities, CAP_SIDETONE)) + if (show_all || device_has_capability(device_found, CAP_SIDETONE)) printf(" %s -s 64\tSet sidetone level to 64\n", programname); - if (show_all || (has_capability(device_found->capabilities, CAP_LIGHTS) && has_capability(device_found->capabilities, CAP_SIDETONE))) + if (show_all || (device_has_capability(device_found, CAP_LIGHTS) && device_has_capability(device_found, CAP_SIDETONE))) printf(" %s -l 1 -s 0\tTurn on lights and deactivate sidetone\n", programname); printf("\n"); } if (!show_all && device_found) - printf("\nHint:\tOptions were filtered to your device (%s)\n\tUse --help-all to show all options (including advanced ones)\n", device_found->device_name); + printf("Hint:\tOptions were filtered to your device (%s)\n\tUse --help-all to show all options (including advanced ones)\n", device_found->device_name); } // for --follow @@ -575,7 +573,7 @@ int main(int argc, char* argv[]) { int c; - int selected_device = 0; + int selected_device = -1; int selected_device_id1 = -1; int selected_device_id2 = -1; @@ -902,12 +900,6 @@ int main(int argc, char* argv[]) // Look for a supported device int headset_available = find_devices(&devices_found, test_device); - // User selected a device-index that is out of bounds - if (selected_device != 0 && (selected_device < 0 || selected_device >= headset_available)) { - fprintf(stderr, "Usage: %s -d [0-N] | [vendorid:deviceid] (N = Number of connected devices - 1)\n", argv[0]); - return 1; - } - if (selected_device_id1 != -1 && selected_device_id2 != -1) { for (int i = 0; i < headset_available; i++) { if (devices_found[i].device->idVendor == selected_device_id1 && devices_found[i].device->idProduct == selected_device_id2) { @@ -916,15 +908,17 @@ int main(int argc, char* argv[]) } } } - // User selected a device-index that is available - device_selected = devices_found[selected_device].device; + // Check user selected a device-index that is out of bounds + if (selected_device >= headset_available) { + fprintf(stderr, "Device index out of bounds\n"); + return 1; + } else if (selected_device != -1) { + // User selected a device-index that is available + device_selected = devices_found[selected_device].device; + } if (should_print_help || should_print_help_all) { - if (headset_available > 0) - print_help(argv[0], device_selected, should_print_help_all); - else - print_help(argv[0], NULL, should_print_help_all); - + print_help(argv[0], device_selected, should_print_help_all); return 0; } else if (headset_available == 0) { output(NULL, false, output_format); From 73115743ac49a2488bd77be3ce9c9695bdcca412 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Wed, 22 Jan 2025 15:11:03 +0100 Subject: [PATCH 16/28] Added showing info for all devices detected --- src/main.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/main.c b/src/main.c index 2d57e0b..06ac2af 100644 --- a/src/main.c +++ b/src/main.c @@ -928,6 +928,7 @@ int main(int argc, char* argv[]) // We open connection to HID devices on demand hid_device* device_handle = NULL; char* hid_path = NULL; + FeatureRequest* feature_requests[headset_available]; // Initialize signal handler for CTRL + C #ifdef _WIN32 @@ -960,16 +961,30 @@ int main(int argc, char* argv[]) // For specific output types, like YAML, we will do all actions - even when not specified - to aggreate all information if (output_format == OUTPUT_YAML || output_format == OUTPUT_JSON || output_format == OUTPUT_ENV) { - for (int i = 0; i < numFeatures; i++) { - if (featureRequests[i].type == CAPABILITYTYPE_INFO && !featureRequests[i].should_process) { - if ((device_selected->capabilities & B(featureRequests[i].cap)) == B(featureRequests[i].cap)) { - featureRequests[i].should_process = true; + for(int i=0; icapabilities & B(feature_requests[i][j].cap)) == B(feature_requests[i][j].cap)) { + feature_requests[i][j].should_process = true; + feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handle, &hid_path, feature_requests[i][j].cap, feature_requests[i][j].param); + } } } + devices_found[i].featureRequests = feature_requests[i]; + devices_found[i].size = numFeatures; + + terminate_hid(&device_handle, &hid_path); + device_handle = NULL; + hid_path = NULL; } } if (request_connected) { + if(device_selected == NULL) { + fprintf(stderr, "Error: No device has been selected.\n"); + return 1; + } int is_test_device = selected_device == 0 && test_device; // Check if battery status can be read // If it isn't supported, the device is @@ -1005,20 +1020,22 @@ int main(int argc, char* argv[]) } do { - for (int i = 0; i < numFeatures; i++) { - if (featureRequests[i].should_process) { - // Assuming handle_feature now returns FeatureResult - featureRequests[i].result = handle_feature(device_selected, &device_handle, &hid_path, featureRequests[i].cap, featureRequests[i].param); - } else { - // Populate with a default "not processed" result - featureRequests[i].result.status = FEATURE_NOT_PROCESSED; - featureRequests[i].result.message = strdup("Not processed"); - featureRequests[i].result.value = 0; + if (device_selected != NULL) { + for (int i = 0; i < numFeatures; i++) { + if (featureRequests[i].should_process) { + // Assuming handle_feature now returns FeatureResult + featureRequests[i].result = handle_feature(device_selected, &device_handle, &hid_path, featureRequests[i].cap, featureRequests[i].param); + } else { + // Populate with a default "not processed" result + featureRequests[i].result.status = FEATURE_NOT_PROCESSED; + featureRequests[i].result.message = strdup("Not processed"); + featureRequests[i].result.value = 0; + } } - } - devices_found[selected_device].featureRequests = featureRequests; - devices_found[selected_device].size = numFeatures; + devices_found[selected_device].featureRequests = featureRequests; + devices_found[selected_device].size = numFeatures; + } output(devices_found, print_capabilities != -1, output_format); From b27acdd68634deb9d92c8d4dfb02a9374ad51db8 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:58:45 +0100 Subject: [PATCH 17/28] Preventing get_two_ids to change values in case it gives errors --- src/utility.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/utility.c b/src/utility.c index 0e5c79d..e618bbd 100644 --- a/src/utility.c +++ b/src/utility.c @@ -145,6 +145,8 @@ int get_two_ids(char* input, int* id1, int* id2) char* str = (char*)malloc(sz + 1); strcpy(str, input); + int v1,v2; + char* token = strtok(input, delim); int i = 0; while (token) { @@ -152,9 +154,9 @@ int get_two_ids(char* input, int* id1, int* id2) long int val = strtol(token, &endptr, 0); if (i == 0) - *id1 = val; + v1 = val; else if (i == 1) - *id2 = val; + v2 = val; i++; token = strtok(NULL, delim); @@ -165,6 +167,9 @@ int get_two_ids(char* input, int* id1, int* id2) if (i != 2) // not exactly supplied two ids return 1; + *id1 = v1; + *id2 = v2; + return 0; } From 5461745fdd2668bff90c8501d8ff5606e4c1f394 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Tue, 28 Jan 2025 17:59:33 +0100 Subject: [PATCH 18/28] Added printing vendor and product id with OUTPUT_STANDARD --- src/output.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/output.c b/src/output.c index eb77f4c..fcb5bba 100644 --- a/src/output.c +++ b/src/output.c @@ -754,9 +754,9 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin for (int i = 0; i < status->device_count; i++) { HeadsetInfo* info = &infos[i]; if (info->product_name != NULL && wcslen(info->product_name) > 0) - printf(" [%d] %s (%ls)\n", i, info->device_name, info->product_name); + printf(" [%d] %s (%ls) [%s:%s]\n", i, info->device_name, info->product_name, info->idVendor, info->idProduct); else - printf(" [%d] %s\n", i, info->device_name); + printf(" [%d] %s [%s:%s]\n", i, info->device_name, info->idVendor, info->idProduct); if (print_capabilities) { printf("\tCapabilities:\n"); From 65d6751a1f451dd212b2bd32ad7f0b97d9debc62 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Tue, 28 Jan 2025 19:01:33 +0100 Subject: [PATCH 19/28] Added terminate_device_hid function that does not clear static hid memory --- src/hid_utility.c | 16 +++++++++++++--- src/hid_utility.h | 5 +++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/hid_utility.c b/src/hid_utility.c index d6c74a3..0537647 100644 --- a/src/hid_utility.c +++ b/src/hid_utility.c @@ -97,10 +97,9 @@ char* get_hid_path(uint16_t vid, uint16_t pid, int iid, uint16_t usagepageid, ui } /** - * Helper freeing HID data and terminating HID usage. + * Helper freeing HID data. */ -/* This function is explicitly called terminate_hid to avoid HIDAPI clashes. */ -void terminate_hid(hid_device** handle, char** path) +void terminate_device_hid(hid_device** handle, char** path) { if (handle) { if (*handle) { @@ -112,7 +111,18 @@ void terminate_hid(hid_device** handle, char** path) if (path) { free(*path); + + *path = NULL; } +} + +/** + * Helper freeing HID data and terminating HID usage. + */ +/* This function is explicitly called terminate_hid to avoid HIDAPI clashes. */ +void terminate_hid(hid_device** handle, char** path) +{ + terminate_device_hid(handle, path); hid_exit(); } diff --git a/src/hid_utility.h b/src/hid_utility.h index a5575df..8a8d3cf 100644 --- a/src/hid_utility.h +++ b/src/hid_utility.h @@ -25,6 +25,11 @@ */ char* get_hid_path(uint16_t vid, uint16_t pid, int iid, uint16_t usagepageid, uint16_t usageid); +/** + * Helper freeing HID data. + */ +void terminate_device_hid(hid_device** handle, char** path); + /** * Helper freeing HID data and terminating HID usage. */ From 512e16e8cc04076bc6b863439b9c2f01654fab2b Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:30:57 +0100 Subject: [PATCH 20/28] Removed -d INDEX support --- src/main.c | 116 +++++++++++++++++++++++++-------------------------- src/output.c | 4 +- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/main.c b/src/main.c index 06ac2af..fe4185d 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,12 @@ int test_profile = 0; int hsc_device_timeout = 5000; +typedef struct { + int vendor_id; + int product_id; + int test_device; +} SearchParameters; + /** * @brief Finds and initializes a list of devices. * @@ -50,7 +56,7 @@ int hsc_device_timeout = 5000; * @param test_device A flag indicating whether to add a test device to the list. * @return The number of devices found and added to the list. */ -static int find_devices(DeviceList** device_list, int test_device) +static int find_devices(DeviceList** device_list, SearchParameters parameters) { DeviceListNode* devices_found = malloc(sizeof(DeviceListNode)); devices_found->element = malloc(sizeof(struct device)); @@ -58,7 +64,7 @@ static int find_devices(DeviceList** device_list, int test_device) int found = 0; // Adding test device - if (test_device) { + if (parameters.test_device) { if (!get_device(devices_found->element, VENDOR_TESTDEVICE, PRODUCT_TESTDEVICE)) { curr_node->next = malloc(sizeof(struct DeviceListNode)); curr_node->next->element = malloc(sizeof(struct device)); @@ -69,7 +75,7 @@ static int find_devices(DeviceList** device_list, int test_device) struct hid_device_info* devs; struct hid_device_info* cur_dev; - devs = hid_enumerate(0x0, 0x0); + devs = hid_enumerate(parameters.vendor_id, parameters.product_id); cur_dev = devs; bool already_found = false; @@ -265,7 +271,7 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de switch (cap) { case CAP_SIDETONE: - ret = device_found->send_sidetone(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_sidetone(*device_handle, (uint8_t)*(int*)param); break; case CAP_BATTERY_STATUS: { @@ -301,15 +307,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de } case CAP_NOTIFICATION_SOUND: - ret = device_found->notifcation_sound(*device_handle, (uint8_t) * (int*)param); + ret = device_found->notifcation_sound(*device_handle, (uint8_t)*(int*)param); break; case CAP_LIGHTS: - ret = device_found->switch_lights(*device_handle, (uint8_t) * (int*)param); + ret = device_found->switch_lights(*device_handle, (uint8_t)*(int*)param); break; case CAP_INACTIVE_TIME: - ret = device_found->send_inactive_time(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_inactive_time(*device_handle, (uint8_t)*(int*)param); break; case CAP_CHATMIX_STATUS: @@ -328,15 +334,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de return result; case CAP_VOICE_PROMPTS: - ret = device_found->switch_voice_prompts(*device_handle, (uint8_t) * (int*)param); + ret = device_found->switch_voice_prompts(*device_handle, (uint8_t)*(int*)param); break; case CAP_ROTATE_TO_MUTE: - ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t) * (int*)param); + ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t)*(int*)param); break; case CAP_EQUALIZER_PRESET: - ret = device_found->send_equalizer_preset(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_equalizer_preset(*device_handle, (uint8_t)*(int*)param); break; case CAP_EQUALIZER: @@ -344,23 +350,23 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de break; case CAP_MICROPHONE_MUTE_LED_BRIGHTNESS: - ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t)*(int*)param); break; case CAP_MICROPHONE_VOLUME: - ret = device_found->send_microphone_volume(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_microphone_volume(*device_handle, (uint8_t)*(int*)param); break; case CAP_VOLUME_LIMITER: - ret = device_found->send_volume_limiter(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_volume_limiter(*device_handle, (uint8_t)*(int*)param); break; case CAP_BT_WHEN_POWERED_ON: - ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t)*(int*)param); break; case CAP_BT_CALL_VOLUME: - ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t)*(int*)param); break; case NUM_CAPABILITIES: @@ -413,8 +419,8 @@ void print_help(char* programname, struct device* device_found, bool show_all) // printf("Options:\n"); printf("Select device:\n"); - printf(" -d, --device INDEX|vendorid:productid\n"); - printf("\t\t\t\tSpecify either an index (0 to N-1) or a vendor ID and product ID separated by a colon.\n"); + printf(" -d, --device vendorid:productid\n"); + printf("\t\t\t\tVendor ID and product ID separated by a colon.\n"); printf("\n"); if (show_all || device_has_capability(device_found, CAP_SIDETONE)) { @@ -573,9 +579,8 @@ int main(int argc, char* argv[]) { int c; - int selected_device = -1; - int selected_device_id1 = -1; - int selected_device_id2 = -1; + int selected_vendor_id = 0; + int selected_product_id = 0; int should_print_help = 0; int should_print_help_all = 0; @@ -644,13 +649,10 @@ int main(int argc, char* argv[]) switch (c) { case 'd': { - int parsed_correctly = get_two_ids(optarg, &selected_device_id1, &selected_device_id2); + int parsed_correctly = get_two_ids(optarg, &selected_vendor_id, &selected_product_id); if (parsed_correctly == 1) { - selected_device = strtol(optarg, &endptr, 10); - if (*endptr != '\0' || endptr == optarg || selected_device < 0) { - fprintf(stderr, "Usage: %s -d [0-N] | [vendorid:deviceid] (N = Number of connected devices - 1)\n", argv[0]); - return 1; - } + fprintf(stderr, "Usage: %s -d [vendorid:deviceid] (N = Number of connected devices - 1)\n", argv[0]); + return 1; } break; } @@ -895,30 +897,30 @@ int main(int argc, char* argv[]) // The array list of compatible devices DeviceList* devices_found = NULL; // Describes the headsetcontrol device, when a headset was found - struct device* device_selected = NULL; + DeviceList* device_selected = NULL; + // Search parameters for the devices + SearchParameters search_parameters = { selected_vendor_id, selected_product_id, test_device }; // Look for a supported device - int headset_available = find_devices(&devices_found, test_device); + int headset_available = find_devices(&devices_found, search_parameters); - if (selected_device_id1 != -1 && selected_device_id2 != -1) { + // Check if the user specified a vendorId and productId + if (selected_vendor_id != 0 && selected_product_id != 0) { + // Find the device with the specified vendorId and productId for (int i = 0; i < headset_available; i++) { - if (devices_found[i].device->idVendor == selected_device_id1 && devices_found[i].device->idProduct == selected_device_id2) { - selected_device = i; + if (devices_found[i].device->idVendor == selected_vendor_id && devices_found[i].device->idProduct == selected_product_id) { + device_selected = devices_found + i; break; } } } - // Check user selected a device-index that is out of bounds - if (selected_device >= headset_available) { - fprintf(stderr, "Device index out of bounds\n"); - return 1; - } else if (selected_device != -1) { - // User selected a device-index that is available - device_selected = devices_found[selected_device].device; - } if (should_print_help || should_print_help_all) { - print_help(argv[0], device_selected, should_print_help_all); + if (device_selected == NULL) { + print_help(argv[0], NULL, should_print_help_all); + } else { + print_help(argv[0], device_selected->device, should_print_help_all); + } return 0; } else if (headset_available == 0) { output(NULL, false, output_format); @@ -974,9 +976,7 @@ int main(int argc, char* argv[]) devices_found[i].featureRequests = feature_requests[i]; devices_found[i].size = numFeatures; - terminate_hid(&device_handle, &hid_path); - device_handle = NULL; - hid_path = NULL; + terminate_device_hid(&device_handle, &hid_path); } } @@ -985,24 +985,25 @@ int main(int argc, char* argv[]) fprintf(stderr, "Error: No device has been selected.\n"); return 1; } - int is_test_device = selected_device == 0 && test_device; + struct device* device = device_selected->device; + int is_test_device = test_device && device->idVendor == VENDOR_TESTDEVICE && device->idProduct == PRODUCT_TESTDEVICE; // Check if battery status can be read // If it isn't supported, the device is // probably wired meaning it is connected int battery_error = 0; BatteryInfo info; - if ((device_selected->capabilities & B(CAP_BATTERY_STATUS)) == B(CAP_BATTERY_STATUS)) { + if (device_has_capability(device, CAP_BATTERY_STATUS)) { if (!is_test_device) { - device_handle = dynamic_connect(&hid_path, device_handle, device_selected, CAP_BATTERY_STATUS); + device_handle = dynamic_connect(&hid_path, device_handle, device, CAP_BATTERY_STATUS); if (!device_handle) { fprintf(stderr, "Error while getting device handle.\n"); return 1; } - info = device_selected->request_battery(device_handle); + info = device->request_battery(device_handle); terminate_hid(&device_handle, &hid_path); } else { - info = device_selected->request_battery(device_handle); + info = device->request_battery(device_handle); } if (info.status != BATTERY_AVAILABLE) { @@ -1021,20 +1022,18 @@ int main(int argc, char* argv[]) do { if (device_selected != NULL) { + FeatureRequest* deviceFeatureRequests = device_selected->featureRequests; for (int i = 0; i < numFeatures; i++) { - if (featureRequests[i].should_process) { + if (deviceFeatureRequests[i].should_process) { // Assuming handle_feature now returns FeatureResult - featureRequests[i].result = handle_feature(device_selected, &device_handle, &hid_path, featureRequests[i].cap, featureRequests[i].param); + deviceFeatureRequests[i].result = handle_feature(device_selected->device, &device_handle, &hid_path, deviceFeatureRequests[i].cap, deviceFeatureRequests[i].param); } else { // Populate with a default "not processed" result - featureRequests[i].result.status = FEATURE_NOT_PROCESSED; - featureRequests[i].result.message = strdup("Not processed"); - featureRequests[i].result.value = 0; + deviceFeatureRequests[i].result.status = FEATURE_NOT_PROCESSED; + deviceFeatureRequests[i].result.message = strdup("Not processed"); + deviceFeatureRequests[i].result.value = 0; } } - - devices_found[selected_device].featureRequests = featureRequests; - devices_found[selected_device].size = numFeatures; } output(devices_found, print_capabilities != -1, output_format); @@ -1046,7 +1045,7 @@ int main(int argc, char* argv[]) // Free memory from features for (int i = 0; i < numFeatures; i++) { - free(featureRequests[i].result.message); + //free(devices_found[device_index].featureRequests[i].result.message); } if (equalizer != NULL) { @@ -1055,9 +1054,10 @@ int main(int argc, char* argv[]) free(equalizer); for (int i = 0; i < headset_available; i++) { + if (output_format != OUTPUT_STANDARD) + free(feature_requests[i]); free(devices_found[i].device); } - free(devices_found); terminate_hid(&device_handle, &hid_path); return 0; diff --git a/src/output.c b/src/output.c index fcb5bba..a6d4125 100644 --- a/src/output.c +++ b/src/output.c @@ -754,9 +754,9 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin for (int i = 0; i < status->device_count; i++) { HeadsetInfo* info = &infos[i]; if (info->product_name != NULL && wcslen(info->product_name) > 0) - printf(" [%d] %s (%ls) [%s:%s]\n", i, info->device_name, info->product_name, info->idVendor, info->idProduct); + printf(" %s (%ls) [%s:%s]\n", info->device_name, info->product_name, info->idVendor, info->idProduct); else - printf(" [%d] %s [%s:%s]\n", i, info->device_name, info->idVendor, info->idProduct); + printf(" %s [%s:%s]\n", info->device_name, info->idVendor, info->idProduct); if (print_capabilities) { printf("\tCapabilities:\n"); From 819a9e6c444e73e1e2309896b573007abbe2b34b Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:37:46 +0100 Subject: [PATCH 21/28] Improved memory freeing --- src/main.c | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/main.c b/src/main.c index fe4185d..9c00734 100644 --- a/src/main.c +++ b/src/main.c @@ -651,7 +651,7 @@ int main(int argc, char* argv[]) case 'd': { int parsed_correctly = get_two_ids(optarg, &selected_vendor_id, &selected_product_id); if (parsed_correctly == 1) { - fprintf(stderr, "Usage: %s -d [vendorid:deviceid] (N = Number of connected devices - 1)\n", argv[0]); + fprintf(stderr, "Usage: %s -d, --device [vendorid:deviceid]\n", argv[0]); return 1; } break; @@ -930,7 +930,6 @@ int main(int argc, char* argv[]) // We open connection to HID devices on demand hid_device* device_handle = NULL; char* hid_path = NULL; - FeatureRequest* feature_requests[headset_available]; // Initialize signal handler for CTRL + C #ifdef _WIN32 @@ -961,10 +960,16 @@ int main(int argc, char* argv[]) int numFeatures = sizeof(featureRequests) / sizeof(featureRequests[0]); assert(numFeatures == NUM_CAPABILITIES); + FeatureRequest* feature_requests[headset_available]; + for (int i = 0; i < headset_available; i++) { + feature_requests[i] = memcpy(malloc(sizeof(featureRequests)), featureRequests, sizeof(featureRequests)); + devices_found[i].featureRequests = feature_requests[i]; + devices_found[i].size = numFeatures; + } + // For specific output types, like YAML, we will do all actions - even when not specified - to aggreate all information if (output_format == OUTPUT_YAML || output_format == OUTPUT_JSON || output_format == OUTPUT_ENV) { for(int i=0; icapabilities & B(feature_requests[i][j].cap)) == B(feature_requests[i][j].cap)) { @@ -973,9 +978,6 @@ int main(int argc, char* argv[]) } } } - devices_found[i].featureRequests = feature_requests[i]; - devices_found[i].size = numFeatures; - terminate_device_hid(&device_handle, &hid_path); } } @@ -1013,39 +1015,32 @@ int main(int argc, char* argv[]) if (battery_error != 0) { printf("false\n"); - return 1; } else { printf("true\n"); - return 0; } - } - - do { - if (device_selected != NULL) { - FeatureRequest* deviceFeatureRequests = device_selected->featureRequests; - for (int i = 0; i < numFeatures; i++) { - if (deviceFeatureRequests[i].should_process) { - // Assuming handle_feature now returns FeatureResult - deviceFeatureRequests[i].result = handle_feature(device_selected->device, &device_handle, &hid_path, deviceFeatureRequests[i].cap, deviceFeatureRequests[i].param); - } else { - // Populate with a default "not processed" result - deviceFeatureRequests[i].result.status = FEATURE_NOT_PROCESSED; - deviceFeatureRequests[i].result.message = strdup("Not processed"); - deviceFeatureRequests[i].result.value = 0; + } else{ + do { + if (device_selected != NULL) { + FeatureRequest* deviceFeatureRequests = device_selected->featureRequests; + for (int i = 0; i < numFeatures; i++) { + if (deviceFeatureRequests[i].should_process) { + // Assuming handle_feature now returns FeatureResult + deviceFeatureRequests[i].result = handle_feature(device_selected->device, &device_handle, &hid_path, deviceFeatureRequests[i].cap, deviceFeatureRequests[i].param); + } else { + // Populate with a default "not processed" result + deviceFeatureRequests[i].result.status = FEATURE_NOT_PROCESSED; + deviceFeatureRequests[i].result.message = strdup("Not processed"); + deviceFeatureRequests[i].result.value = 0; + } } } - } - output(devices_found, print_capabilities != -1, output_format); + output(devices_found, print_capabilities != -1, output_format); - if (follow) - sleep(follow_sec); + if (follow) + sleep(follow_sec); - } while (follow); - - // Free memory from features - for (int i = 0; i < numFeatures; i++) { - //free(devices_found[device_index].featureRequests[i].result.message); + } while (follow); } if (equalizer != NULL) { @@ -1054,8 +1049,13 @@ int main(int argc, char* argv[]) free(equalizer); for (int i = 0; i < headset_available; i++) { - if (output_format != OUTPUT_STANDARD) - free(feature_requests[i]); + if (output_format != OUTPUT_STANDARD){ + // Free memory from features + for (int j = 0; j < numFeatures; j++) { + free(devices_found[i].featureRequests[j].result.message); + } + } + free(devices_found[i].featureRequests); free(devices_found[i].device); } From c92ea2598190001d7f0ccf16a7aeed9cb55e1da2 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Mon, 3 Feb 2025 12:51:15 +0100 Subject: [PATCH 22/28] Clangd fix --- src/device.c | 2 +- src/device.h | 2 +- src/main.c | 44 ++++++++++++++++++++++---------------------- src/utility.c | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/device.c b/src/device.c index 0769635..19a62d6 100644 --- a/src/device.c +++ b/src/device.c @@ -63,4 +63,4 @@ bool device_has_capability(struct device* device, enum capabilities cap) if (device == NULL) return false; return (device->capabilities & B(cap)) == B(cap); -} \ No newline at end of file +} diff --git a/src/device.h b/src/device.h index dc56abb..acc3cba 100644 --- a/src/device.h +++ b/src/device.h @@ -401,4 +401,4 @@ typedef struct DeviceListNode { struct DeviceListNode* next; } DeviceListNode; -bool device_has_capability(struct device* device, enum capabilities cap); \ No newline at end of file +bool device_has_capability(struct device* device, enum capabilities cap); diff --git a/src/main.c b/src/main.c index 9c00734..b7a6710 100644 --- a/src/main.c +++ b/src/main.c @@ -271,7 +271,7 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de switch (cap) { case CAP_SIDETONE: - ret = device_found->send_sidetone(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_sidetone(*device_handle, (uint8_t) * (int*)param); break; case CAP_BATTERY_STATUS: { @@ -307,15 +307,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de } case CAP_NOTIFICATION_SOUND: - ret = device_found->notifcation_sound(*device_handle, (uint8_t)*(int*)param); + ret = device_found->notifcation_sound(*device_handle, (uint8_t) * (int*)param); break; case CAP_LIGHTS: - ret = device_found->switch_lights(*device_handle, (uint8_t)*(int*)param); + ret = device_found->switch_lights(*device_handle, (uint8_t) * (int*)param); break; case CAP_INACTIVE_TIME: - ret = device_found->send_inactive_time(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_inactive_time(*device_handle, (uint8_t) * (int*)param); break; case CAP_CHATMIX_STATUS: @@ -334,15 +334,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de return result; case CAP_VOICE_PROMPTS: - ret = device_found->switch_voice_prompts(*device_handle, (uint8_t)*(int*)param); + ret = device_found->switch_voice_prompts(*device_handle, (uint8_t) * (int*)param); break; case CAP_ROTATE_TO_MUTE: - ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t)*(int*)param); + ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t) * (int*)param); break; case CAP_EQUALIZER_PRESET: - ret = device_found->send_equalizer_preset(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_equalizer_preset(*device_handle, (uint8_t) * (int*)param); break; case CAP_EQUALIZER: @@ -350,23 +350,23 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de break; case CAP_MICROPHONE_MUTE_LED_BRIGHTNESS: - ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t) * (int*)param); break; case CAP_MICROPHONE_VOLUME: - ret = device_found->send_microphone_volume(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_microphone_volume(*device_handle, (uint8_t) * (int*)param); break; case CAP_VOLUME_LIMITER: - ret = device_found->send_volume_limiter(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_volume_limiter(*device_handle, (uint8_t) * (int*)param); break; case CAP_BT_WHEN_POWERED_ON: - ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t) * (int*)param); break; case CAP_BT_CALL_VOLUME: - ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t) * (int*)param); break; case NUM_CAPABILITIES: @@ -579,7 +579,7 @@ int main(int argc, char* argv[]) { int c; - int selected_vendor_id = 0; + int selected_vendor_id = 0; int selected_product_id = 0; int should_print_help = 0; @@ -962,19 +962,19 @@ int main(int argc, char* argv[]) FeatureRequest* feature_requests[headset_available]; for (int i = 0; i < headset_available; i++) { - feature_requests[i] = memcpy(malloc(sizeof(featureRequests)), featureRequests, sizeof(featureRequests)); + feature_requests[i] = memcpy(malloc(sizeof(featureRequests)), featureRequests, sizeof(featureRequests)); devices_found[i].featureRequests = feature_requests[i]; - devices_found[i].size = numFeatures; + devices_found[i].size = numFeatures; } // For specific output types, like YAML, we will do all actions - even when not specified - to aggreate all information if (output_format == OUTPUT_YAML || output_format == OUTPUT_JSON || output_format == OUTPUT_ENV) { - for(int i=0; icapabilities & B(feature_requests[i][j].cap)) == B(feature_requests[i][j].cap)) { feature_requests[i][j].should_process = true; - feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handle, &hid_path, feature_requests[i][j].cap, feature_requests[i][j].param); + feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handle, &hid_path, feature_requests[i][j].cap, feature_requests[i][j].param); } } } @@ -983,12 +983,12 @@ int main(int argc, char* argv[]) } if (request_connected) { - if(device_selected == NULL) { + if (device_selected == NULL) { fprintf(stderr, "Error: No device has been selected.\n"); return 1; } struct device* device = device_selected->device; - int is_test_device = test_device && device->idVendor == VENDOR_TESTDEVICE && device->idProduct == PRODUCT_TESTDEVICE; + int is_test_device = test_device && device->idVendor == VENDOR_TESTDEVICE && device->idProduct == PRODUCT_TESTDEVICE; // Check if battery status can be read // If it isn't supported, the device is // probably wired meaning it is connected @@ -1018,7 +1018,7 @@ int main(int argc, char* argv[]) } else { printf("true\n"); } - } else{ + } else { do { if (device_selected != NULL) { FeatureRequest* deviceFeatureRequests = device_selected->featureRequests; @@ -1049,7 +1049,7 @@ int main(int argc, char* argv[]) free(equalizer); for (int i = 0; i < headset_available; i++) { - if (output_format != OUTPUT_STANDARD){ + if (output_format != OUTPUT_STANDARD) { // Free memory from features for (int j = 0; j < numFeatures; j++) { free(devices_found[i].featureRequests[j].result.message); diff --git a/src/utility.c b/src/utility.c index e618bbd..7c8d20d 100644 --- a/src/utility.c +++ b/src/utility.c @@ -145,7 +145,7 @@ int get_two_ids(char* input, int* id1, int* id2) char* str = (char*)malloc(sz + 1); strcpy(str, input); - int v1,v2; + int v1, v2; char* token = strtok(input, delim); int i = 0; From cdad9e84b4af58a76b6fa40040459cf1d3020aba Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Thu, 6 Feb 2025 19:43:26 +0100 Subject: [PATCH 23/28] Update GitHub Actions to use upload-artifact@v4 (#394) --- .github/workflows/build-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 58075a2..e059b2d 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -27,7 +27,7 @@ jobs: cd build make test - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: headsetcontrol.exe path: build/headsetcontrol.exe From d18add1a9036d4bab8c143e15a9e39e3459992ee Mon Sep 17 00:00:00 2001 From: Denis Arnst Date: Fri, 21 Feb 2025 23:08:49 +0100 Subject: [PATCH 24/28] Format --- src/main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index b7a6710..36c14db 100644 --- a/src/main.c +++ b/src/main.c @@ -271,7 +271,7 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de switch (cap) { case CAP_SIDETONE: - ret = device_found->send_sidetone(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_sidetone(*device_handle, (uint8_t)*(int*)param); break; case CAP_BATTERY_STATUS: { @@ -307,15 +307,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de } case CAP_NOTIFICATION_SOUND: - ret = device_found->notifcation_sound(*device_handle, (uint8_t) * (int*)param); + ret = device_found->notifcation_sound(*device_handle, (uint8_t)*(int*)param); break; case CAP_LIGHTS: - ret = device_found->switch_lights(*device_handle, (uint8_t) * (int*)param); + ret = device_found->switch_lights(*device_handle, (uint8_t)*(int*)param); break; case CAP_INACTIVE_TIME: - ret = device_found->send_inactive_time(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_inactive_time(*device_handle, (uint8_t)*(int*)param); break; case CAP_CHATMIX_STATUS: @@ -334,15 +334,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de return result; case CAP_VOICE_PROMPTS: - ret = device_found->switch_voice_prompts(*device_handle, (uint8_t) * (int*)param); + ret = device_found->switch_voice_prompts(*device_handle, (uint8_t)*(int*)param); break; case CAP_ROTATE_TO_MUTE: - ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t) * (int*)param); + ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t)*(int*)param); break; case CAP_EQUALIZER_PRESET: - ret = device_found->send_equalizer_preset(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_equalizer_preset(*device_handle, (uint8_t)*(int*)param); break; case CAP_EQUALIZER: @@ -350,23 +350,23 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de break; case CAP_MICROPHONE_MUTE_LED_BRIGHTNESS: - ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t)*(int*)param); break; case CAP_MICROPHONE_VOLUME: - ret = device_found->send_microphone_volume(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_microphone_volume(*device_handle, (uint8_t)*(int*)param); break; case CAP_VOLUME_LIMITER: - ret = device_found->send_volume_limiter(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_volume_limiter(*device_handle, (uint8_t)*(int*)param); break; case CAP_BT_WHEN_POWERED_ON: - ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t)*(int*)param); break; case CAP_BT_CALL_VOLUME: - ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t) * (int*)param); + ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t)*(int*)param); break; case NUM_CAPABILITIES: From 07221157504d55d994bc8f2f6f17972e0abaf283 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sat, 22 Feb 2025 09:40:28 +0100 Subject: [PATCH 25/28] Fixed action running on test device when different device was selected --- src/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.c b/src/main.c index 36c14db..979ead4 100644 --- a/src/main.c +++ b/src/main.c @@ -976,6 +976,8 @@ int main(int argc, char* argv[]) feature_requests[i][j].should_process = true; feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handle, &hid_path, feature_requests[i][j].cap, feature_requests[i][j].param); } + } else if(feature_requests[i][j].type == CAPABILITYTYPE_ACTION && feature_requests[i][j].should_process && devices_found+i != device_selected) { + feature_requests[i][j].should_process = false; } } terminate_device_hid(&device_handle, &hid_path); From fc1aea5d31212e257275c1599e54c89d0053fa31 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sat, 22 Feb 2025 09:43:56 +0100 Subject: [PATCH 26/28] Fixed spacing for clangd --- src/main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main.c b/src/main.c index 979ead4..ca993b1 100644 --- a/src/main.c +++ b/src/main.c @@ -271,7 +271,7 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de switch (cap) { case CAP_SIDETONE: - ret = device_found->send_sidetone(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_sidetone(*device_handle, (uint8_t) * (int*)param); break; case CAP_BATTERY_STATUS: { @@ -307,15 +307,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de } case CAP_NOTIFICATION_SOUND: - ret = device_found->notifcation_sound(*device_handle, (uint8_t)*(int*)param); + ret = device_found->notifcation_sound(*device_handle, (uint8_t) * (int*)param); break; case CAP_LIGHTS: - ret = device_found->switch_lights(*device_handle, (uint8_t)*(int*)param); + ret = device_found->switch_lights(*device_handle, (uint8_t) * (int*)param); break; case CAP_INACTIVE_TIME: - ret = device_found->send_inactive_time(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_inactive_time(*device_handle, (uint8_t) * (int*)param); break; case CAP_CHATMIX_STATUS: @@ -334,15 +334,15 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de return result; case CAP_VOICE_PROMPTS: - ret = device_found->switch_voice_prompts(*device_handle, (uint8_t)*(int*)param); + ret = device_found->switch_voice_prompts(*device_handle, (uint8_t) * (int*)param); break; case CAP_ROTATE_TO_MUTE: - ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t)*(int*)param); + ret = device_found->switch_rotate_to_mute(*device_handle, (uint8_t) * (int*)param); break; case CAP_EQUALIZER_PRESET: - ret = device_found->send_equalizer_preset(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_equalizer_preset(*device_handle, (uint8_t) * (int*)param); break; case CAP_EQUALIZER: @@ -350,23 +350,23 @@ static FeatureResult handle_feature(struct device* device_found, hid_device** de break; case CAP_MICROPHONE_MUTE_LED_BRIGHTNESS: - ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_microphone_mute_led_brightness(*device_handle, (uint8_t) * (int*)param); break; case CAP_MICROPHONE_VOLUME: - ret = device_found->send_microphone_volume(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_microphone_volume(*device_handle, (uint8_t) * (int*)param); break; case CAP_VOLUME_LIMITER: - ret = device_found->send_volume_limiter(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_volume_limiter(*device_handle, (uint8_t) * (int*)param); break; case CAP_BT_WHEN_POWERED_ON: - ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_bluetooth_when_powered_on(*device_handle, (uint8_t) * (int*)param); break; case CAP_BT_CALL_VOLUME: - ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t)*(int*)param); + ret = device_found->send_bluetooth_call_volume(*device_handle, (uint8_t) * (int*)param); break; case NUM_CAPABILITIES: @@ -976,7 +976,7 @@ int main(int argc, char* argv[]) feature_requests[i][j].should_process = true; feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handle, &hid_path, feature_requests[i][j].cap, feature_requests[i][j].param); } - } else if(feature_requests[i][j].type == CAPABILITYTYPE_ACTION && feature_requests[i][j].should_process && devices_found+i != device_selected) { + } else if (feature_requests[i][j].type == CAPABILITYTYPE_ACTION && feature_requests[i][j].should_process && devices_found + i != device_selected) { feature_requests[i][j].should_process = false; } } From 7cbaf74771ab097f81320146daad5c4390055014 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sat, 22 Feb 2025 18:04:11 +0100 Subject: [PATCH 27/28] Original single device feature restored --- src/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.c b/src/main.c index ca993b1..a631a42 100644 --- a/src/main.c +++ b/src/main.c @@ -904,6 +904,10 @@ int main(int argc, char* argv[]) // Look for a supported device int headset_available = find_devices(&devices_found, search_parameters); + if (headset_available == 1) { + device_selected = devices_found; + } + // Check if the user specified a vendorId and productId if (selected_vendor_id != 0 && selected_product_id != 0) { // Find the device with the specified vendorId and productId From 46fc7b83975a4fb9749dba2450f1d63d6b98df37 Mon Sep 17 00:00:00 2001 From: Nicola <61830443+nicola02nb@users.noreply.github.com> Date: Sun, 23 Feb 2025 22:03:23 +0100 Subject: [PATCH 28/28] Improved main logic, added some device helper function and remove unnecessary break statements in output functions --- src/device.c | 5 ++++ src/device.h | 2 ++ src/main.c | 72 ++++++++++++++++++++++++++++------------------------ src/output.c | 3 --- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/device.c b/src/device.c index 19a62d6..9fbfb11 100644 --- a/src/device.c +++ b/src/device.c @@ -58,6 +58,11 @@ const char capabilities_str_short[NUM_CAPABILITIES] [CAP_BT_CALL_VOLUME] = '\0' }; +bool device_check_ids(struct device* device, uint16_t vid, uint16_t pid) +{ + return device->idVendor == vid && device->idProduct == pid; +} + bool device_has_capability(struct device* device, enum capabilities cap) { if (device == NULL) diff --git a/src/device.h b/src/device.h index acc3cba..9fe7201 100644 --- a/src/device.h +++ b/src/device.h @@ -401,4 +401,6 @@ typedef struct DeviceListNode { struct DeviceListNode* next; } DeviceListNode; +bool device_check_ids(struct device* device, uint16_t vid, uint16_t pid); + bool device_has_capability(struct device* device, enum capabilities cap); diff --git a/src/main.c b/src/main.c index a631a42..00544b2 100644 --- a/src/main.c +++ b/src/main.c @@ -906,13 +906,9 @@ int main(int argc, char* argv[]) if (headset_available == 1) { device_selected = devices_found; - } - - // Check if the user specified a vendorId and productId - if (selected_vendor_id != 0 && selected_product_id != 0) { - // Find the device with the specified vendorId and productId + } else if (selected_vendor_id != 0 && selected_product_id != 0) { for (int i = 0; i < headset_available; i++) { - if (devices_found[i].device->idVendor == selected_vendor_id && devices_found[i].device->idProduct == selected_product_id) { + if (device_check_ids(devices_found[i].device, selected_vendor_id, selected_product_id)) { device_selected = devices_found + i; break; } @@ -932,8 +928,8 @@ int main(int argc, char* argv[]) } // We open connection to HID devices on demand - hid_device* device_handle = NULL; - char* hid_path = NULL; + hid_device* device_handles[headset_available]; + char* hid_paths[headset_available]; // Initialize signal handler for CTRL + C #ifdef _WIN32 @@ -964,27 +960,36 @@ int main(int argc, char* argv[]) int numFeatures = sizeof(featureRequests) / sizeof(featureRequests[0]); assert(numFeatures == NUM_CAPABILITIES); + // Initialize all handles, hid_paths and feature requests for all devices FeatureRequest* feature_requests[headset_available]; for (int i = 0; i < headset_available; i++) { + device_handles[i] = NULL; + hid_paths[i] = NULL; feature_requests[i] = memcpy(malloc(sizeof(featureRequests)), featureRequests, sizeof(featureRequests)); devices_found[i].featureRequests = feature_requests[i]; devices_found[i].size = numFeatures; } - // For specific output types, like YAML, we will do all actions - even when not specified - to aggreate all information - if (output_format == OUTPUT_YAML || output_format == OUTPUT_JSON || output_format == OUTPUT_ENV) { - for (int i = 0; i < headset_available; i++) { - for (int j = 0; j < numFeatures; j++) { - if (feature_requests[i][j].type == CAPABILITYTYPE_INFO && !feature_requests[i][j].should_process) { - if ((devices_found[i].device->capabilities & B(feature_requests[i][j].cap)) == B(feature_requests[i][j].cap)) { - feature_requests[i][j].should_process = true; - feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handle, &hid_path, feature_requests[i][j].cap, feature_requests[i][j].param); + bool isExtendedOutput = output_format == OUTPUT_YAML || output_format == OUTPUT_JSON || output_format == OUTPUT_ENV; + for (int i = 0; i < headset_available; i++) { + for (int j = 0; j < numFeatures; j++) { + // For specific output types, like YAML, we will do all actions - even when not specified - to aggreate all information + if (isExtendedOutput && feature_requests[i][j].type == CAPABILITYTYPE_INFO && !feature_requests[i][j].should_process) { + if (device_has_capability(devices_found[i].device, feature_requests[i][j].cap)) { + feature_requests[i][j].should_process = true; + feature_requests[i][j].result = handle_feature(devices_found[i].device, &device_handles[i], &hid_paths[i], feature_requests[i][j].cap, feature_requests[i][j].param); + } + } else if (feature_requests[i][j].type == CAPABILITYTYPE_ACTION && feature_requests[i][j].should_process) { + if (headset_available > 1) { + if (selected_vendor_id == 0 && selected_product_id == 0) { + feature_requests[i][j].result.status = FEATURE_NOT_PROCESSED; + feature_requests[i][j].result.message = strdup("Not processed, multiple devices detected,you need to specify a device with -d"); + feature_requests[i][j].result.value = -1; + } else if (!device_check_ids(devices_found[i].device, selected_vendor_id, selected_product_id)) { + feature_requests[i][j].should_process = false; } - } else if (feature_requests[i][j].type == CAPABILITYTYPE_ACTION && feature_requests[i][j].should_process && devices_found + i != device_selected) { - feature_requests[i][j].should_process = false; } } - terminate_device_hid(&device_handle, &hid_path); } } @@ -993,8 +998,11 @@ int main(int argc, char* argv[]) fprintf(stderr, "Error: No device has been selected.\n"); return 1; } - struct device* device = device_selected->device; - int is_test_device = test_device && device->idVendor == VENDOR_TESTDEVICE && device->idProduct == PRODUCT_TESTDEVICE; + int selected_device_index = device_selected - devices_found; + hid_device* device_handle = device_handles[selected_device_index]; + char* hid_path = hid_paths[selected_device_index]; + struct device* device = device_selected->device; + int is_test_device = test_device && device->idVendor == VENDOR_TESTDEVICE && device->idProduct == PRODUCT_TESTDEVICE; // Check if battery status can be read // If it isn't supported, the device is // probably wired meaning it is connected @@ -1009,7 +1017,6 @@ int main(int argc, char* argv[]) return 1; } info = device->request_battery(device_handle); - terminate_hid(&device_handle, &hid_path); } else { info = device->request_battery(device_handle); } @@ -1026,17 +1033,15 @@ int main(int argc, char* argv[]) } } else { do { - if (device_selected != NULL) { - FeatureRequest* deviceFeatureRequests = device_selected->featureRequests; - for (int i = 0; i < numFeatures; i++) { - if (deviceFeatureRequests[i].should_process) { + // Process all features for all devices + for (int i = 0; i < headset_available; i++) { + if (!device_check_ids(devices_found[i].device, selected_vendor_id, selected_product_id)) + continue; + FeatureRequest* deviceFeatureRequests = devices_found[i].featureRequests; + for (int j = 0; j < numFeatures; j++) { + if (deviceFeatureRequests[j].should_process && deviceFeatureRequests[j].result.status != FEATURE_NOT_PROCESSED) { // Assuming handle_feature now returns FeatureResult - deviceFeatureRequests[i].result = handle_feature(device_selected->device, &device_handle, &hid_path, deviceFeatureRequests[i].cap, deviceFeatureRequests[i].param); - } else { - // Populate with a default "not processed" result - deviceFeatureRequests[i].result.status = FEATURE_NOT_PROCESSED; - deviceFeatureRequests[i].result.message = strdup("Not processed"); - deviceFeatureRequests[i].result.value = 0; + deviceFeatureRequests[j].result = handle_feature(devices_found[i].device, &device_handles[i], &hid_paths[i], deviceFeatureRequests[j].cap, deviceFeatureRequests[j].param); } } } @@ -1061,10 +1066,11 @@ int main(int argc, char* argv[]) free(devices_found[i].featureRequests[j].result.message); } } + terminate_device_hid(&device_handles[i], &hid_paths[i]); free(devices_found[i].featureRequests); free(devices_found[i].device); } - terminate_hid(&device_handle, &hid_path); + hid_exit(); return 0; } diff --git a/src/output.c b/src/output.c index a6d4125..62d3c18 100644 --- a/src/output.c +++ b/src/output.c @@ -335,7 +335,6 @@ void output_json(HeadsetControlStatus* status, HeadsetInfo* infos) } } printf("\n ],\n"); - break; } } } @@ -548,7 +547,6 @@ void output_yaml(HeadsetControlStatus* status, HeadsetInfo* infos) yaml_print("error_message", info->actions[i].error_message, 4); } } - break; } } } @@ -692,7 +690,6 @@ void output_env(HeadsetControlStatus* status, HeadsetInfo* infos) env_print(key, info->actions[i].error_message); } } - break; } } } else {