This is the source for the afm_ctl utility.
For information about using this utility, see afm_ctl in the QNX Neutrino Utilities Reference.
/* * 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 -u clear runtime acoustic processing dataset -l <ms_offset> start microphone latency test -r <ms_offset> start reference latency test -v <rpm> set rpm VIN value (diagnostic use only - only applicable if rpm is a base VIN) -x <param_id:chn>[:data] calls set/get data on afm for ap parameters of size int16_t -y <param_id:chn>[:data] calls set/get data on afm for ap parameters of size int32_t -z <param_id>[:data] calls set/get data on afm for afm parameters of size int32_t -s stop AFM #endif /* *INDENT-ON* */ //***************************************************************************** const char* optstring = "a:f:m:sl:r:cv:t:ux:y:z:"; #define LATENCY_TEST_MIC 0 #define LATENCY_TEST_REF 1 static snd_afm_t* setup_afm_handle(char* arg) { int rtn; int dev = 0, card = 0; const char* name = NULL; snd_afm_t* afm_handle = NULL; if (strchr(arg, ':')) { card = atoi(arg); dev = atoi(strchr(arg, ':') + 1); } else if (isalpha(arg[0]) || (arg[0] == '/')) name = arg; else dev = atoi(arg); if (name) { printf("Using %s\n", name); rtn = snd_afm_open_name(&afm_handle, name); } else { printf("Using card %d device %d \n", card, dev); rtn = snd_afm_open(&afm_handle, card, dev); } if (rtn != EOK) { fprintf(stderr, "snd_afm_open failed: (%d) %s\n", rtn, snd_strerror(rtn)); return NULL; } return afm_handle; } static int latency_test(snd_afm_t* afm_handle, int input_device, int ms_offset) { int rtn = EOK; int fd; snd_afm_latency_test_t test; if ((fd = snd_afm_file_descriptor(afm_handle)) > 0) { test.input_device = input_device; /* 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)); rtn = -errno; /* Negate errno to match snd_xxx error codes */ } } else { printf("Failed to get AFM descriptor for latency test (%d) %s\n", errno, strerror(errno)); rtn = -errno; /* Negate errno to match snd_xxx error codes */ } return rtn; } static int set_audio_mode(snd_afm_t* afm_handle, const char* mode) { int rtn; char str[64]; if (mode[0]) { printf("Setting mode to %s\n", mode); } else { printf("Clearing mode\n"); } 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); return rtn; } static int set_dataset(snd_afm_t* afm_handle, const char* dataset) { int rtn; int ap_status = 0; if (dataset[0]) printf("Loading dataset %s\n", dataset); else printf("Clearing dataset\n"); if ((rtn = snd_afm_load_ap_dataset(afm_handle, dataset, &ap_status)) != EOK) printf("Failed to set dataset: (%d) %s\n", rtn, snd_strerror(rtn)); if (ap_status != 0) printf("Acoustic processing returned status=0x%04X\n", ap_status); return rtn; } static int set_rpm_vin(snd_afm_t* afm_handle, int rpm) { int rtn; 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; /* Negate errno to match snd_xxx error codes */ } } if (rtn != EOK) { printf("Failed to set RPM (%d) %s\n", rtn, snd_strerror(rtn)); } return rtn; } /* Set/get acoustic processing parameter */ static int set_ap_data(snd_afm_t* afm_handle, char* arg, size_t data_size) { int set_data, rtn; int32_t data; snd_afm_ap_param_t param = { .size = data_size, }; param.dataId = strtol(arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid ap data id\n"); return 1; } if (*arg) arg++; param.channel = strtol(arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid channel\n"); return 1; } if (*arg) arg++; data = strtol(arg, &arg, 0); set_data = (errno != ERANGE && errno != EINVAL); errno = EOK; if (set_data) { printf("AFM set_ap_data id=0x%04x data=%d ", param.dataId, data); rtn = snd_afm_set_ap_data(afm_handle, ¶m, &data); } else { printf("AFM get_ap_data id=0x%04x ", param.dataId); rtn = snd_afm_get_ap_data(afm_handle, ¶m, &data); } printf("ret=%d ap_ret=%d data_ret=%d -- %s\n", rtn, param.status, data, strerror(-rtn)); return rtn; } /* Set/get acoustic processing parameter */ static int set_afm_param(snd_afm_t* afm_handle, char* arg, size_t data_size) { int set_data, rtn; int32_t data, param_id; param_id = strtol(arg, &arg, 0); if (errno == ERANGE || errno == EINVAL) { fprintf(stderr, "Invalid afm param data id\n"); return 1; } if (*arg) arg++; data = strtol(arg, &arg, 0); set_data = (errno != ERANGE && errno != EINVAL); errno = EOK; if (set_data) { printf("AFM set_param id=0x%04x data=%d ", param_id, data); rtn = snd_afm_set_param(afm_handle, param_id, data_size, &data); } else { printf("AFM get_param id=0x%04x ", param_id); rtn = snd_afm_get_param(afm_handle, param_id, &data_size, &data); } printf("ret=%d data_ret=%d -- %s\n", rtn, data, strerror(-rtn)); return rtn; } int main(int argc, char *argv[]) { int rtn = EOK; snd_afm_t *afm_handle = NULL; int start_afm = 1; int c; /* first setup afm handle */ while ((c = getopt(argc, argv, optstring)) != EOF) { switch (c) { case 'a': if (!(afm_handle = setup_afm_handle(optarg))) { return EXIT_FAILURE; } break; default: /* handle other options instead of starting AFM */ start_afm = 0; break; } } if (!afm_handle) { printf("No AFM specified, use -a option\n"); return EXIT_FAILURE; } if (start_afm) { 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); return (rtn == EOK) ? EXIT_SUCCESS : EXIT_FAILURE; } /* reset optind and handle other options */ optind = 1; while (((c = getopt(argc, argv, optstring)) != EOF) && (rtn == EOK)) { switch (c) { case 'a': break; case 's': printf("Stopping AFM \n"); if ((rtn = snd_afm_stop(afm_handle)) != EOK) printf("Failed to stop AFM: (%d) %s\n", rtn, snd_strerror(rtn)); break; case 'l': rtn = latency_test(afm_handle, LATENCY_TEST_MIC, atoi(optarg)); break; case 'r': rtn = latency_test(afm_handle, LATENCY_TEST_REF, atoi(optarg)); break; case 'f': printf("Setting filename %s, len = %zu\n", optarg, strlen(optarg)); if ((rtn = snd_afm_set_path(afm_handle, SND_AFM_WAV_FILE, optarg)) != EOK) printf("Failed to set filename: (%d) %s\n", rtn, snd_strerror(rtn)); break; case 'm': rtn = set_audio_mode(afm_handle, optarg); break; case 'c': rtn = set_audio_mode(afm_handle, ""); break; case 't': rtn = set_dataset(afm_handle, optarg); break; case 'u': rtn = set_dataset(afm_handle, ""); break; case 'v': rtn = set_rpm_vin(afm_handle, strtoul(optarg, NULL, 0)); break; case 'x': rtn = set_ap_data(afm_handle, optarg, sizeof(uint16_t)); break; case 'y': rtn = set_ap_data(afm_handle, optarg, sizeof(uint32_t)); break; case 'z': rtn = set_afm_param(afm_handle, optarg, sizeof(uint32_t)); break; default: fprintf(stderr, "Invalid option '%c'\n", c); rtn = -1; break; } } snd_afm_close(afm_handle); return (rtn == EOK) ? EXIT_SUCCESS : EXIT_FAILURE; } #if defined(__QNXNTO__) && defined(__USESRCVERSION) #include <sys/srcversion.h> __SRCVERSION("$URL$ $Rev$") #endif