Skip to content

Commit

Permalink
Added support for multiple devices through -d or --device
Browse files Browse the repository at this point in the history
  • Loading branch information
nicola02nb committed Dec 4, 2024
1 parent 6276d20 commit 504407f
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 43 deletions.
127 changes: 95 additions & 32 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -956,6 +1013,12 @@ int main(int argc, char* argv[])
}
free(equalizer);

for(int i=0;i<headset_available;i++)
{
free(devices_found[i].device);
}
free(devices_found);

terminate_hid(&device_handle, &hid_path);
return 0;
}
23 changes: 12 additions & 11 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,25 +730,25 @@ void output_standard(HeadsetControlStatus* status, HeadsetInfo* infos, bool prin
printf("No supported device found\n");
return;
}

bool outputted = false;

printf("Found %d supported device(s):\n", status->device_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;
}

Expand All @@ -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");
}
}
Expand Down

0 comments on commit 504407f

Please sign in to comment.