This is the source for the afm_ctl utility.
/*
* Copyright 2016, QNX Software Systems Ltd. All Rights Reserved.
*
* This source code may contain confidential information of QNX Software
* Systems Ltd. (QSSL) and its licensors. Any use, reproduction,
* modification, disclosure, distribution or transfer of this software,
* or any software which includes or is based upon any of this code, is
* prohibited unless expressly authorized by QSSL by written agreement. For
* more information (including whether this source code file has been
* published) please email licensing@qnx.com.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/asoundlib.h>
#include <string.h>
#include <devctl.h>
#include <errno.h>
#include <ctype.h>
#include <ioctl.h>
//*****************************************************************************
/* *INDENT-OFF* */
#ifdef __USAGE
%C [Options]
Options:
-a [card#:]<dev#> the AFM card & device number to start/issue command
OR
-a [name] the AFM card name (e.g. voice, icc) to start/issue command
-f <filename> set wav file (full path) (recorder/player AFMs only)
-m <mode> set audio mode
-c reset audio mode
-t <dataset> load runtime acoustic processing dataset
-l <ms_offset> start microphone latency test
-r <ms_offset> start reference latency test
-v <rpm> set rpm vin
-s stop AFM
#endif
/* *INDENT-ON* */
//*****************************************************************************
int main(int argc, char *argv[])
{
int c;
int card = 0;
int dev = 0;
int rtn = 0;
int reset_mode = 0;
int stop = 0;
int latencyTest = 0;
int ms_offset = 0;
int rpm = -1;
char *filename = NULL;
char *mode = NULL;
char *dataset = NULL;
snd_afm_t *afm_handle;
char name[_POSIX_PATH_MAX] = { 0 };
optind = 1;
while ((c = getopt(argc, argv, "a:f:m:sl:r:cv:t:")) != EOF)
{
switch (c)
{
case 'a':
if (strchr(optarg, ':'))
{
card = atoi(optarg);
dev = atoi(strchr(optarg, ':') + 1);
}
else if (isalpha(optarg[0]))
strlcpy(name, optarg, sizeof(name));
else
dev = atoi(optarg);
break;
case 's':
stop = 1;
break;
case 'l':
ms_offset = atoi(optarg);
latencyTest = 1;
break;
case 'r':
ms_offset = atoi(optarg);
latencyTest = 2;
break;
case 'f':
filename = strdup(optarg);
break;
case 'm':
mode = strdup(optarg);
break;
case 'c':
reset_mode = 1;
break;
case 't':
dataset = strdup(optarg);
break;
case 'v':
rpm = strtoul(optarg, NULL, 0);
break;
default:
printf("Invalid option '%c'", c);
return EINVAL;
}
}
if (name[0] != '\0')
{
card = snd_card_name(name);
printf("Using %s - card %d\n", name, card);
}
else
{
printf("Using card %d device %d \n", card, dev);
}
if ((rtn = snd_afm_open(&afm_handle, card, dev)) != EOK)
{
fprintf(stderr, "snd_afm_open failed: (%d) %s\n", rtn, snd_strerror(rtn));
free(filename);
free(mode);
return -rtn;
}
if (filename != NULL)
{
printf("Setting filename %s, len = %zu\n", filename, strlen(filename));
if ((rtn = snd_afm_set_path(afm_handle, SND_AFM_WAV_FILE, filename)) != EOK)
printf("Failed to set filename: (%d) %s\n", rtn, snd_strerror(rtn));
}
if (reset_mode)
{
printf("Clearing mode\n");
if ((rtn = snd_afm_set_audio_mode(afm_handle, "")) != EOK)
printf("Failed to clear mode: (%d) %s\n", rtn, snd_strerror(rtn));
}
else if (mode != NULL)
{
char str[64];
printf("Setting mode to %s\n", mode);
if ((rtn = snd_afm_set_audio_mode(afm_handle, mode)) != EOK)
printf("Failed to set mode: (%d) %s\n", rtn, snd_strerror(rtn));
if ((rtn = snd_afm_get_audio_mode(afm_handle, str, sizeof(str))) != EOK)
printf("Failed to get mode: (%d) %s\n", rtn, snd_strerror(rtn));
else
printf("Audio Mode = %s\n", str);
}
else if (dataset != NULL)
{
int ap_status = 0;
printf("Loading dataset %s\n", dataset);
if ((rtn = snd_afm_load_ap_dataset(afm_handle, dataset, &ap_status)) != EOK)
printf("Failed to load dataset: (%d) %s\n", rtn, snd_strerror(rtn));
if (ap_status != 0) {
printf("Acoustic processing returned status=0x%04X\n", ap_status);
}
}
else if (latencyTest)
{
int fd;
snd_afm_latency_test_t test;
if ((fd = snd_afm_file_descriptor(afm_handle)) > 0)
{
test.input_device = latencyTest-1; /* 0 = mic, 1 = ref */
test.input_voice = 0;
test.ms_offset = ms_offset;
if (ioctl(fd, SND_AFM_IOCTL_START_LATENCY_TEST, &test) < 0) {
printf("Failed to start latency test: (%d) %s\n", errno, strerror(errno));
return errno;
}
}
else
{
printf("Failed to get AFM descriptor for latency test (%d) %s\n", errno, strerror(errno));
return errno;
}
}
else if (rpm >= 0)
{
int vinCount = 0;
if ((rtn = snd_afm_get_vin_list_count(afm_handle, &vinCount)) == EOK) {
snd_afm_vin_list_item_t* vin_items = alloca( sizeof(snd_afm_vin_list_item_t) * vinCount);
snd_afm_vin_pair_t* vin_pairs = alloca( sizeof(snd_afm_vin_pair_t) * vinCount);
if (vin_items && vin_pairs)
{
memset(vin_pairs, 0, sizeof(snd_afm_vin_pair_t) * vinCount);
if ((rtn = snd_afm_get_vin_list(afm_handle, vin_items, vinCount)) == EOK) {
int i;
for (i=0; i<vinCount; i++) {
vin_pairs[i].key = vin_items[i].key;
if (vin_items[i].is_rpm) {
vin_pairs[i].value = rpm;
printf("Vin 0x%X set to %d\n", vin_pairs[i].key, vin_pairs[i].value);
}
}
rtn = snd_afm_set_vin_stream(afm_handle, vin_pairs, vinCount);
}
} else {
rtn = -errno;
}
}
if (rtn != EOK)
{
printf("Failed to set RPM (%d) %s\n", rtn, snd_strerror(rtn));
}
}
else if (stop)
{
printf("Stopping AFM \n");
if ((rtn = snd_afm_stop(afm_handle)) != EOK)
printf("Failed to stop AFM: (%d) %s\n", rtn, snd_strerror(rtn));
}
else
{
printf("Starting AFM \n");
if ((rtn = snd_afm_start(afm_handle)) != EOK)
printf("Failed to start AFM: (%d) %s\n", rtn, snd_strerror(rtn));
}
snd_afm_close(afm_handle);
free(filename);
free(mode);
return -rtn;
}
#if defined(__QNXNTO__) && defined(__USESRCVERSION)
#include <sys/srcversion.h>
__SRCVERSION("$URL$ $Rev$")
#endif