Skip to content

Instantly share code, notes, and snippets.

@takaswie
Last active September 2, 2017 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takaswie/cd670ee88b7fd25c68780610ad8ad54f to your computer and use it in GitHub Desktop.
Save takaswie/cd670ee88b7fd25c68780610ad8ad54f to your computer and use it in GitHub Desktop.
A small program to check logical contradiction between member count and dimension info.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sound/asound.h>
static const char *const elem_iface_labels[] = {
[SNDRV_CTL_ELEM_IFACE_CARD] = "card",
[SNDRV_CTL_ELEM_IFACE_HWDEP] = "hwdep",
[SNDRV_CTL_ELEM_IFACE_MIXER] = "mixer",
[SNDRV_CTL_ELEM_IFACE_PCM] = "pcm",
[SNDRV_CTL_ELEM_IFACE_RAWMIDI] = "rawmidi",
[SNDRV_CTL_ELEM_IFACE_TIMER] = "timer",
[SNDRV_CTL_ELEM_IFACE_SEQUENCER] = "sequencer",
};
static const char *const elem_type_labels[] = {
[SNDRV_CTL_ELEM_TYPE_BOOLEAN] = "boolean",
[SNDRV_CTL_ELEM_TYPE_INTEGER] = "integer",
[SNDRV_CTL_ELEM_TYPE_ENUMERATED] = "enumerated",
[SNDRV_CTL_ELEM_TYPE_BYTES] = "bytes",
[SNDRV_CTL_ELEM_TYPE_IEC958] = "iec60958",
[SNDRV_CTL_ELEM_TYPE_INTEGER64] = "integer64",
};
static void dump_elem_info(struct snd_ctl_elem_info *info)
{
unsigned int cols;
int i;
printf("numid: %u\n", info->id.numid);
printf(" iface: %s\n", elem_iface_labels[info->id.iface]);
printf(" device: %u\n", info->id.device);
printf(" subdevice: %u\n", info->id.subdevice);
printf(" name: %s\n", info->id.name);
printf(" index: %u\n", info->id.index);
printf(" type: %s\n", elem_type_labels[info->type]);
printf(" count: %u\n", info->count);
if (info->dimen.d[0] > 0) {
printf(" dimension:\n");
for (i = 0;
i < sizeof(info->dimen.d) / sizeof(info->dimen.d[0]);
++i) {
cols = info->dimen.d[i];
if (cols == 0)
continue;
printf(" %d: %u %u\n", i, cols, info->count / cols);
info->count /= cols;
}
}
}
static int enumerate_elems(int fd, struct snd_ctl_elem_id *ids,
unsigned int count)
{
struct snd_ctl_elem_info info;
int i;
for (i = 0; i < count; ++i) {
memset(&info, 0, sizeof(info));
info.id = ids[i];
if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &info) < 0) {
printf("ioctl(2) with ELEM_INFO: %s\n",
strerror(errno));
return -errno;
}
dump_elem_info(&info);
}
return 0;
}
static int list_elems(int fd)
{
struct snd_ctl_elem_list list = {0};
int err = 0;
if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &list) < 0) {
printf("ioctl(2) with ELEM_LIST: %s\n", strerror(errno));
return -errno;
}
list.pids = calloc(list.count, sizeof(*list.pids));
if (list.pids == NULL) {
printf("calloc(3): %s\n", strerror(errno));
return -ENOMEM;
}
list.space = list.count;
if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &list) < 0) {
printf("ioctl(2) with ELEM_LIST: %s\n", strerror(errno));
err = -errno;
goto end;
}
err = enumerate_elems(fd, list.pids, list.count);
end:
free(list.pids);
return err;
}
int main(int argc, const char *argv[])
{
const char *path;
int fd;
int err;
if (argc == 1) {
printf("At least, one argument is required for a path of "
"special file for ALSA control character device.\n");
return EXIT_FAILURE;
}
path = argv[1];
fd = open(path, O_RDONLY);
if (fd < 0) {
printf("open(2): %s\n", strerror(errno));
return EXIT_FAILURE;
}
err = list_elems(fd);
end:
close(fd);
if (err < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment