Path: blob/main/share/examples/sound/sndstat_nv.c
107525 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2024 The FreeBSD Foundation4*5* This software was developed by Christos Margiolis <[email protected]>6* under sponsorship from the FreeBSD Foundation.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions10* are met:11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in the15* documentation and/or other materials provided with the distribution.16*17* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE20* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF27* SUCH DAMAGE.28*/2930#include <sys/sndstat.h>31#include <sys/nv.h>3233#include <err.h>34#include <errno.h>35#include <fcntl.h>36#include <stdlib.h>37#include <unistd.h>3839/*40* Example program showcasing how to use sndstat(4)'s nvlist interface, and how41* to fetch all currently supported fields, with the appropriate error checks.42*43* For more detailed information on what each nvlist field represents, please44* read sndstat(4)'s man page.45*/4647int48main(int argc, char *argv[])49{50nvlist_t *nvl;51const nvlist_t * const *di;52const nvlist_t * const *cdi;53struct sndstioc_nv_arg arg;54size_t nitems, nchans, i, j;55int fd, pchan, rchan;5657if ((fd = open("/dev/sndstat", O_RDONLY)) < 0)58err(1, "open(/dev/sndstat)");5960if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL) < 0)61err(1, "ioctl(SNDSTIOC_REFRESH_DEVS)");6263arg.nbytes = 0;64arg.buf = NULL;65if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg) < 0)66err(1, "ioctl(SNDSTIOC_GET_DEVS#1)");6768if ((arg.buf = malloc(arg.nbytes)) == NULL)69err(1, "malloc");7071if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg) < 0)72err(1, "ioctl(SNDSTIOC_GET_DEVS#2)");7374if ((nvl = nvlist_unpack(arg.buf, arg.nbytes, 0)) == NULL)75err(1, "nvlist_unpack");7677if (nvlist_empty(nvl) || !nvlist_exists(nvl, SNDST_DSPS))78errx(1, "no soundcards attached");7980di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems);81for (i = 0; i < nitems; i++) {82#define NV(type, item) \83nvlist_get_ ## type (di[i], SNDST_DSPS_ ## item)84printf("nameunit=%s\n", NV(string, NAMEUNIT));85printf("\tfrom_user=%d\n", NV(bool, FROM_USER));86printf("\tdevnode=%s\n", NV(string, DEVNODE));87printf("\tdesc=%s\n", NV(string, DESC));88printf("\tprovider=%s\n", NV(string, PROVIDER));89printf("\tpchan=%d\n", (int)NV(number, PCHAN));90printf("\trchan=%d\n", (int)NV(number, RCHAN));91pchan = NV(number, PCHAN);92rchan = NV(number, RCHAN);93#undef NV9495if (pchan && !nvlist_exists(di[i], SNDST_DSPS_INFO_PLAY))96errx(1, "playback channel list empty");97if (rchan && !nvlist_exists(di[i], SNDST_DSPS_INFO_REC))98errx(1, "recording channel list empty");99100#define NV(type, mode, item) \101nvlist_get_ ## type (nvlist_get_nvlist(di[i], \102SNDST_DSPS_INFO_ ## mode), SNDST_DSPS_INFO_ ## item)103if (pchan) {104printf("\tplay_min_rate=%d\n",105(int)NV(number, PLAY, MIN_RATE));106printf("\tplay_max_rate=%d\n",107(int)NV(number, PLAY, MAX_RATE));108printf("\tplay_formats=%#08x\n",109(int)NV(number, PLAY, FORMATS));110printf("\tplay_min_chn=%d\n",111(int)NV(number, PLAY, MIN_CHN));112printf("\tplay_max_chn=%d\n",113(int)NV(number, PLAY, MAX_CHN));114}115if (rchan) {116printf("\trec_min_rate=%d\n",117(int)NV(number, REC, MIN_RATE));118printf("\trec_max_rate=%d\n",119(int)NV(number, REC, MAX_RATE));120printf("\trec_formats=%#08x\n",121(int)NV(number, REC, FORMATS));122printf("\trec_min_chn=%d\n",123(int)NV(number, REC, MIN_CHN));124printf("\trec_max_chn=%d\n",125(int)NV(number, REC, MAX_CHN));126}127#undef NV128129if (!nvlist_exists(di[i], SNDST_DSPS_PROVIDER_INFO))130continue;131132#define NV(type, item) \133nvlist_get_ ## type (nvlist_get_nvlist(di[i], \134SNDST_DSPS_PROVIDER_INFO), SNDST_DSPS_SOUND4_ ## item)135printf("\tunit=%d\n", (int)NV(number, UNIT));136printf("\tstatus=%s\n", NV(string, STATUS));137printf("\tbitperfect=%d\n", NV(bool, BITPERFECT));138printf("\tpvchan=%d\n", (int)NV(number, PVCHAN));139printf("\tpvchanrate=%d\n", (int)NV(number, PVCHANRATE));140printf("\tpvchanformat=%#08x\n", (int)NV(number, PVCHANFORMAT));141printf("\trvchan=%d\n", (int)NV(number, RVCHAN));142printf("\trvchanrate=%d\n", (int)NV(number, RVCHANRATE));143printf("\trvchanformat=%#08x\n", (int)NV(number, RVCHANFORMAT));144#undef NV145146if (!nvlist_exists(nvlist_get_nvlist(di[i],147SNDST_DSPS_PROVIDER_INFO), SNDST_DSPS_SOUND4_CHAN_INFO))148errx(1, "channel info list empty");149150cdi = nvlist_get_nvlist_array(151nvlist_get_nvlist(di[i], SNDST_DSPS_PROVIDER_INFO),152SNDST_DSPS_SOUND4_CHAN_INFO, &nchans);153for (j = 0; j < nchans; j++) {154#define NV(type, item) \155nvlist_get_ ## type (cdi[j], SNDST_DSPS_SOUND4_CHAN_ ## item)156printf("\tchan=%s\n", NV(string, NAME));157printf("\t\tparentchan=%s\n", NV(string, PARENTCHAN));158printf("\t\tunit=%d\n", (int)NV(number, UNIT));159printf("\t\tcaps=%#08x\n", (int)NV(number, CAPS));160printf("\t\tlatency=%d\n", (int)NV(number, LATENCY));161printf("\t\trate=%d\n", (int)NV(number, RATE));162printf("\t\tformat=%#08x\n", (int)NV(number, FORMAT));163printf("\t\tpid=%d\n", (int)NV(number, PID));164printf("\t\tcomm=%s\n", NV(string, COMM));165printf("\t\tintr=%d\n", (int)NV(number, INTR));166printf("\t\txruns=%d\n", (int)NV(number, XRUNS));167printf("\t\tfeedcnt=%d\n", (int)NV(number, FEEDCNT));168printf("\t\tleftvol=%d\n", (int)NV(number, LEFTVOL));169printf("\t\trightvol=%d\n", (int)NV(number, RIGHTVOL));170printf("\t\thwbuf_format=%#08x\n",171(int)NV(number, HWBUF_FORMAT));172printf("\t\thwbuf_size=%d\n",173(int)NV(number, HWBUF_SIZE));174printf("\t\thwbuf_blksz=%d\n",175(int)NV(number, HWBUF_BLKSZ));176printf("\t\thwbuf_blkcnt=%d\n",177(int)NV(number, HWBUF_BLKCNT));178printf("\t\thwbuf_free=%d\n",179(int)NV(number, HWBUF_FREE));180printf("\t\thwbuf_ready=%d\n",181(int)NV(number, HWBUF_READY));182printf("\t\tswbuf_format=%#08x\n",183(int)NV(number, SWBUF_FORMAT));184printf("\t\tswbuf_size=%d\n",185(int)NV(number, SWBUF_SIZE));186printf("\t\tswbuf_blksz=%d\n",187(int)NV(number, SWBUF_BLKSZ));188printf("\t\tswbuf_blkcnt=%d\n",189(int)NV(number, SWBUF_BLKCNT));190printf("\t\tswbuf_free=%d\n",191(int)NV(number, SWBUF_FREE));192printf("\t\tswbuf_ready=%d\n",193(int)NV(number, SWBUF_READY));194printf("\t\tswbuf_feederchain=%s\n",195NV(string, FEEDERCHAIN));196#undef NV197}198}199200free(arg.buf);201nvlist_destroy(nvl);202close(fd);203204return (0);205}206207208