Add Windows driver GUID command-line option on mixer host app

This commit is contained in:
Daniel Pieczko
2024-01-31 14:54:54 +00:00
parent 165417962f
commit 0d913cdce3
4 changed files with 133 additions and 77 deletions

View File

@@ -15,6 +15,7 @@ HEAD
* CHANGED: UserBufferManagementInit() now takes a sample rate parameter * CHANGED: UserBufferManagementInit() now takes a sample rate parameter
* CHANGED: xcore.ai targets use sigma-delta software PLL for clock recovery of * CHANGED: xcore.ai targets use sigma-delta software PLL for clock recovery of
digital Rx streams and synch USB audio by default. digital Rx streams and synch USB audio by default.
* CHANGED: Windows host mixer control application now requires driver GUID option
* Changes to dependencies: * Changes to dependencies:

View File

@@ -1,4 +1,4 @@
// Copyright 2022-2023 XMOS LIMITED. // Copyright 2022-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1. // This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdlib.h> #include <stdlib.h>
@@ -14,10 +14,20 @@
// TODO // TODO
// res, min, max // res, min, max
#ifdef _WIN32
int mixer_init(TCHAR guid[GUID_STR_LEN])
#else
int mixer_init(void) int mixer_init(void)
#endif
{ {
#ifdef _WIN32
int ret = usb_mixer_connect(guid);
#else
int ret = usb_mixer_connect();
#endif
/* Open the connection to the USB mixer */ /* Open the connection to the USB mixer */
if (usb_mixer_connect() == USB_MIXER_FAILURE) if (ret == USB_MIXER_FAILURE)
{ {
return USB_MIXER_FAILURE; return USB_MIXER_FAILURE;
} }
@@ -381,8 +391,15 @@ void print_levels(const char* levelTitle, unsigned char* levels, int levelBytes)
void mixer_display_usage(void) { void mixer_display_usage(void) {
fprintf(stderr, "Usage :\n"); fprintf(stderr, "Usage: xmos_mixer "
fprintf(stderr, #ifdef _WIN32
"-g<GUID> "
#endif
"<options>\n");
fprintf(stderr,
#ifdef _WIN32
" -g<GUID> Driver GUID string, eg. -g{E5A2658B-817D-4A02-A1DE-B628A93DDF5D}\n"
#endif
" --display-info\n" " --display-info\n"
" --display-mixer-nodes mixer_id\n" " --display-mixer-nodes mixer_id\n"
" --display-min mixer_id\n" " --display-min mixer_id\n"
@@ -421,97 +438,124 @@ int main (int argc, char **argv) {
unsigned int mixer_index = 0; unsigned int mixer_index = 0;
unsigned int result = 0; unsigned int result = 0;
int min_argc;
// arg_idx is the position in the arguments to start parsing to skip the "-g" GUID option on Windows
int arg_idx;
#ifdef _WIN32
// Driver GUID string is required on Windows
min_argc = 3;
arg_idx = 2;
#else
min_argc = 2;
arg_idx = 1;
#endif
if (argc < min_argc) {
if (argc < 2) {
fprintf(stderr, "ERROR :: No options passed to mixer application\n"); fprintf(stderr, "ERROR :: No options passed to mixer application\n");
mixer_display_usage(); mixer_display_usage();
return -1; return -1;
} }
#ifdef _WIN32
TCHAR driver_guid[GUID_STR_LEN];
if (strncmp(argv[1], "-g", 2) == 0) {
swprintf(driver_guid, GUID_STR_LEN, L"%hs", argv[1]+2);
} else {
fprintf(stderr, "ERROR :: First option must be driver GUID\n");
return -1;
}
#endif
if (strcmp(argv[1], "--help") == 0) { if (strcmp(argv[1], "--help") == 0) {
mixer_display_usage(); mixer_display_usage();
return 0; return 0;
} }
if (mixer_init() != USB_MIXER_SUCCESS) { #ifdef _WIN32
int ret = mixer_init(driver_guid);
#else
int ret = mixer_init();
#endif
if (ret != USB_MIXER_SUCCESS) {
fprintf(stderr, "ERROR :: Cannot connect\n"); fprintf(stderr, "ERROR :: Cannot connect\n");
return -1; return -1;
} }
if (strcmp(argv[1], "--display-info") == 0) if (strcmp(argv[arg_idx], "--display-info") == 0)
{ {
mixer_display_info(); mixer_display_info();
} }
else if (strcmp(argv[1], "--display-mixer-nodes") == 0) else if (strcmp(argv[arg_idx], "--display-mixer-nodes") == 0)
{ {
if (argv[2]) if (argv[arg_idx+1])
{ {
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
} else { } else {
fprintf(stderr, "ERROR :: No mixer index supplied\n"); fprintf(stderr, "ERROR :: No mixer index supplied\n");
return -1; return -1;
} }
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_VALUE); mixer_display(mixer_index, MIXER_UNIT_DISPLAY_VALUE);
} else if (strcmp(argv[1], "--display-mixer-nodes") == 0) { } else if (strcmp(argv[arg_idx], "--display-mixer-nodes") == 0) {
if (argv[2]) { if (argv[2]) {
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
} else { } else {
fprintf(stderr, "ERROR :: No mixer index supplied\n"); fprintf(stderr, "ERROR :: No mixer index supplied\n");
return -1; return -1;
} }
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_VALUE); mixer_display(mixer_index, MIXER_UNIT_DISPLAY_VALUE);
} else if (strcmp(argv[1], "--display-min") == 0) { } else if (strcmp(argv[arg_idx], "--display-min") == 0) {
if (argv[2]) { if (argv[arg_idx+1]) {
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
} else { } else {
fprintf(stderr, "ERROR :: No mixer index supplied\n"); fprintf(stderr, "ERROR :: No mixer index supplied\n");
return -1; return -1;
} }
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_MIN); mixer_display(mixer_index, MIXER_UNIT_DISPLAY_MIN);
} else if (strcmp(argv[1], "--display-max") == 0) { } else if (strcmp(argv[arg_idx], "--display-max") == 0) {
if (argv[2]) { if (argv[arg_idx+1]) {
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
} else { } else {
fprintf(stderr, "ERROR :: No mixer index supplied\n"); fprintf(stderr, "ERROR :: No mixer index supplied\n");
return -1; return -1;
} }
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_MAX); mixer_display(mixer_index, MIXER_UNIT_DISPLAY_MAX);
} else if (strcmp(argv[1], "--display-res") == 0) { } else if (strcmp(argv[arg_idx], "--display-res") == 0) {
if (argv[2]) { if (argv[arg_idx+1]) {
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
} else { } else {
fprintf(stderr, "ERROR :: No mixer index supplied\n"); fprintf(stderr, "ERROR :: No mixer index supplied\n");
return -1; return -1;
} }
mixer_display(mixer_index, MIXER_UNIT_DISPLAY_RES); mixer_display(mixer_index, MIXER_UNIT_DISPLAY_RES);
} }
else if (strcmp(argv[1], "--set-value") == 0) { else if (strcmp(argv[arg_idx], "--set-value") == 0) {
unsigned int mixer_unit = 0; unsigned int mixer_unit = 0;
double value = 0; double value = 0;
if (argc < 5) { if (argc - arg_idx < 4) {
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n"); fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
return -1; return -1;
} }
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
mixer_unit = atoi(argv[3]); mixer_unit = atoi(argv[arg_idx+2]);
if (strcmp(argv[4],"-inf")==0) if (strcmp(argv[arg_idx+3],"-inf")==0)
value = -128; value = -128;
else else
value = atof(argv[4]); value = atof(argv[arg_idx+3]);
usb_mixer_set_value(mixer_index, mixer_unit, value); usb_mixer_set_value(mixer_index, mixer_unit, value);
} else if (strcmp(argv[1], "--get-value") == 0) { } else if (strcmp(argv[arg_idx], "--get-value") == 0) {
unsigned int mixer_unit = 0; unsigned int mixer_unit = 0;
double result = 0; double result = 0;
if (argc < 4) { if (argc - arg_idx < 3) {
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n"); fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
return -1; return -1;
} }
mixer_index = atoi(argv[2]); mixer_index = atoi(argv[arg_idx+1]);
mixer_unit = atoi(argv[3]); mixer_unit = atoi(argv[arg_idx+2]);
result = usb_mixer_get_value(mixer_index, mixer_unit); result = usb_mixer_get_value(mixer_index, mixer_unit);
if (result <= -127.996) if (result <= -127.996)
@@ -519,99 +563,99 @@ int main (int argc, char **argv) {
else else
printf("%g\n",result); printf("%g\n",result);
} }
else if (strcmp(argv[1], "--display-current-mixer-sources") == 0) else if (strcmp(argv[arg_idx], "--display-current-mixer-sources") == 0)
{ {
if(argc < 3) if(argc - arg_idx < 2)
{ {
usage_error(); usage_error();
return -1; return -1;
} }
display_mixer_sources(atoi(argv[2])); display_mixer_sources(atoi(argv[arg_idx+1]));
} }
else if (strcmp(argv[1], "--display-available-mixer-sources") == 0) else if (strcmp(argv[arg_idx], "--display-available-mixer-sources") == 0)
{ {
if(argc < 3) if(argc - arg_idx < 2)
{ {
usage_error(); usage_error();
return -1; return -1;
} }
display_available_mixer_sources(atoi(argv[2])); display_available_mixer_sources(atoi(argv[arg_idx+1]));
} }
else if(strcmp(argv[1], "--set-mixer-source") == 0) else if(strcmp(argv[arg_idx], "--set-mixer-source") == 0)
{ {
if(argc < 5) if(argc - arg_idx < 4)
{ {
usage_error(); usage_error();
return -1; return -1;
} }
set_mixer_source(atoi(argv[2]), atoi(argv[3]), atoi(argv[4])); set_mixer_source(atoi(argv[arg_idx+1]), atoi(argv[arg_idx+2]), atoi(argv[arg_idx+3]));
} }
else if (strcmp(argv[1], "--display-aud-channel-map") == 0) else if (strcmp(argv[arg_idx], "--display-aud-channel-map") == 0)
{ {
/* Display the channel mapping to the devices audio outputs */ /* Display the channel mapping to the devices audio outputs */
display_aud_channel_map(); display_aud_channel_map();
} }
else if (strcmp(argv[1], "--display-aud-channel-map-sources") == 0) else if (strcmp(argv[arg_idx], "--display-aud-channel-map-sources") == 0)
{ {
display_aud_channel_map_sources(); display_aud_channel_map_sources();
} }
else if (strcmp(argv[1], "--display-daw-channel-map") == 0) else if (strcmp(argv[arg_idx], "--display-daw-channel-map") == 0)
{ {
/* Display the channel mapping to the devices DAW output to host */ /* Display the channel mapping to the devices DAW output to host */
display_daw_channel_map(); display_daw_channel_map();
} }
else if (strcmp(argv[1], "--display-daw-channel-map-sources") == 0) else if (strcmp(argv[arg_idx], "--display-daw-channel-map-sources") == 0)
{ {
display_daw_channel_map_sources(); display_daw_channel_map_sources();
} }
else if (strcmp(argv[1], "--set-aud-channel-map") == 0) else if (strcmp(argv[arg_idx], "--set-aud-channel-map") == 0)
{ {
unsigned int dst = 0; unsigned int dst = 0;
unsigned int src = 0; unsigned int src = 0;
if (argc != 4) if (argc - arg_idx != 3)
{ {
usage_error(); usage_error();
return -1; return -1;
} }
dst = atoi(argv[2]); dst = atoi(argv[arg_idx+1]);
src = atoi(argv[3]); src = atoi(argv[arg_idx+2]);
usb_set_aud_channel_map(dst, src); usb_set_aud_channel_map(dst, src);
} }
else if (strcmp(argv[1], "--set-daw-channel-map") == 0) else if (strcmp(argv[arg_idx], "--set-daw-channel-map") == 0)
{ {
unsigned int dst = 0; unsigned int dst = 0;
unsigned int src = 0; unsigned int src = 0;
if (argc != 4) if (argc - arg_idx != 3)
{ {
usage_error(); usage_error();
return -1; return -1;
} }
dst = atoi(argv[2]); dst = atoi(argv[arg_idx+1]);
src = atoi(argv[3]); src = atoi(argv[arg_idx+2]);
usb_set_usb_channel_map(dst, src); usb_set_usb_channel_map(dst, src);
} }
else if(strcmp(argv[1], "--get-mixer-levels-input") == 0 || else if(strcmp(argv[arg_idx], "--get-mixer-levels-input") == 0 ||
strcmp(argv[1],"--get-mixer-levels-output") == 0) strcmp(argv[arg_idx],"--get-mixer-levels-output") == 0)
{ {
unsigned int dst = 0; unsigned int dst = 0;
unsigned char levels[64]; unsigned char levels[64];
int datalength = 0; int datalength = 0;
int offset = 0; int offset = 0;
if (argc < 3) { if (argc - arg_idx < 2) {
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n"); fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
return -1; return -1;
} }
if(strcmp(argv[1],"--get-mixer-levels-output") == 0) if(strcmp(argv[arg_idx],"--get-mixer-levels-output") == 0)
offset = 1; offset = 1;
for(int i = 0; i < 64; i++) for(int i = 0; i < 64; i++)
levels[i] = 0; levels[i] = 0;
dst = atoi(argv[2]); dst = atoi(argv[arg_idx+1]);
/* Mem request to mixer with offset of 0 gives input levels */ /* Mem request to mixer with offset of 0 gives input levels */
datalength = usb_mixer_mem_get(dst, offset, levels); datalength = usb_mixer_mem_get(dst, offset, levels);
@@ -628,7 +672,7 @@ int main (int argc, char **argv) {
print_levels("Mixer Input", levels, datalength); print_levels("Mixer Input", levels, datalength);
} }
else if(strcmp(argv[1], "--vendor-audio-request-get") == 0) else if(strcmp(argv[arg_idx], "--vendor-audio-request-get") == 0)
{ {
unsigned int bRequest = 0; unsigned int bRequest = 0;
unsigned int cs = 0; unsigned int cs = 0;
@@ -637,7 +681,7 @@ int main (int argc, char **argv) {
int datalength = 0; int datalength = 0;
unsigned char data[64]; unsigned char data[64];
if(argc < 6) if(argc - arg_idx < 5)
{ {
fprintf(stderr, "ERROR :: incorrect number of arguments passed\n"); fprintf(stderr, "ERROR :: incorrect number of arguments passed\n");
return -1; return -1;
@@ -646,10 +690,10 @@ int main (int argc, char **argv) {
for(int i = 0; i < 64; i++) for(int i = 0; i < 64; i++)
data[i] = 0; data[i] = 0;
bRequest = atoi(argv[2]); bRequest = atoi(argv[arg_idx+1]);
cs = atoi(argv[3]); cs = atoi(argv[arg_idx+2]);
cn = atoi(argv[4]); cn = atoi(argv[arg_idx+3]);
unitId = atoi(argv[5]); unitId = atoi(argv[arg_idx+4]);
/* Do request */ /* Do request */
datalength = usb_audio_request_get(bRequest, cs, cn, unitId, data); datalength = usb_audio_request_get(bRequest, cs, cn, unitId, data);
@@ -666,7 +710,7 @@ int main (int argc, char **argv) {
printf("0x%02x\n" ,data[i]); printf("0x%02x\n" ,data[i]);
} }
} }
else if(strcmp(argv[1], "--vendor-audio-request-set") == 0) else if(strcmp(argv[arg_idx], "--vendor-audio-request-set") == 0)
{ {
unsigned int bRequest = 0; unsigned int bRequest = 0;
@@ -680,23 +724,23 @@ int main (int argc, char **argv) {
data[i] = 0; data[i] = 0;
} }
if(argc < 7) if(argc - arg_idx < 6)
{ {
fprintf(stderr, "ERROR :: incorrect number of arguments passed - no data passed\n"); fprintf(stderr, "ERROR :: incorrect number of arguments passed - no data passed\n");
return -1; return -1;
} }
bRequest = atoi(argv[2]); bRequest = atoi(argv[arg_idx+1]);
cs = atoi(argv[3]); cs = atoi(argv[arg_idx+2]);
cn = atoi(argv[4]); cn = atoi(argv[arg_idx+3]);
unitId = atoi(argv[5]); unitId = atoi(argv[arg_idx+4]);
/* Get data */ /* Get data */
for(int i=0; i < argc-6; i++) for(int i=0; i < argc-arg_idx-5; i++)
{ {
data[i] = atoi(argv[i+6]); data[i] = atoi(argv[i+arg_idx+5]);
} }
result = usb_audio_request_set(bRequest, cs, cn, unitId, data, argc-6); result = usb_audio_request_set(bRequest, cs, cn, unitId, data, argc-arg_idx-5);
if(result < 0) if(result < 0)
{ {

View File

@@ -1,4 +1,4 @@
// Copyright 2022-2023 XMOS LIMITED. // Copyright 2022-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1. // This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdlib.h> #include <stdlib.h>
@@ -800,14 +800,18 @@ static int find_xmos_device(unsigned int id)
// End of libusb interface functions // End of libusb interface functions
int usb_mixer_connect() #ifdef _WIN32
int usb_mixer_connect(TCHAR guid[GUID_STR_LEN])
#else
int usb_mixer_connect()
#endif
{ {
// Allocate internal storage // Allocate internal storage
usb_mixers = (usb_mixer_handle *)malloc(sizeof(usb_mixer_handle)); usb_mixers = (usb_mixer_handle *)malloc(sizeof(usb_mixer_handle));
memset(usb_mixers, 0, sizeof(usb_mixer_handle)); memset(usb_mixers, 0, sizeof(usb_mixer_handle));
#if defined(_WIN32) #if defined(_WIN32)
gDrvApi.LoadByGUID(_T("{E5A2658B-817D-4A02-A1DE-B628A93DDF5D}")); gDrvApi.LoadByGUID(guid);
TUsbAudioStatus st = gDrvApi.TUSBAUDIO_EnumerateDevices(); TUsbAudioStatus st = gDrvApi.TUSBAUDIO_EnumerateDevices();
#endif #endif

View File

@@ -1,4 +1,4 @@
// Copyright 2022-2023 XMOS LIMITED. // Copyright 2022-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1. // This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define USB_MIXER_SUCCESS 0 #define USB_MIXER_SUCCESS 0
@@ -22,7 +22,14 @@ enum usb_chan_type {
#define RANGE (2) #define RANGE (2)
#define MEM (3) #define MEM (3)
#ifdef _WIN32
#include <tchar.h>
// GUID strings are 36 characters, plus a pair of braces and NUL-termination
#define GUID_STR_LEN (36+2+1)
int usb_mixer_connect(TCHAR guid[GUID_STR_LEN]);
#else
int usb_mixer_connect(); int usb_mixer_connect();
#endif
int usb_mixer_disconnect(); int usb_mixer_disconnect();
/* MIXER UNIT(s) INTERFACE */ /* MIXER UNIT(s) INTERFACE */