SNDSTAT(4)
π sndstat(4) β nvlist-based PCM audio device enumeration interface β¨
πΈ NAME
sndstat β nvlist-based PCM audio device enumeration interface π
π SYNOPSIS
To compile the driver into the kernel, place the following lines in the kernel configuration file:
device sound
π¦ DESCRIPTION
okay so the ioctl interface that /dev/sndstat hands you lets callers enumerate PCM audio devices available for use. In other words, it's the plug for getting the list of all audio devices available to the system. no cap, it's giving "inventory check but make it audio" π
π IOCTLS
For ioctl calls that take an argument, the following structure is used:
struct sndstioc_nv_arg {
size_t nbytes;
void *buf;
};
Here's an nvlist object example with the common fields explained, bestie β this is the whole vibe of what comes back π«Ά
dsps (NVLIST ARRAY): 1
from_user (BOOL): FALSE
nameunit (STRING): [pcm0]
devnode (STRING): [dsp0]
desc (STRING): [Generic (0x8086) (Analog Line-out)]
pchan (NUMBER): 1
rchan (NUMBER): 0
info_play (NVLIST):
min_rate (NUMBER): 48000
max_rate (NUMBER): 48000
formats (NUMBER): 16
min_chn (NUMBER): 2
max_chn (NUMBER): 2
provider_info (NVLIST):
unit (NUMBER): 0
status (STRING): on hdaa0
bitperfect (BOOL): FALSE
pvchan (BOOL): TRUE
pvchanrate (NUMBER): 48000
pvchanformat (NUMBER): 0x00000010
rvchan (BOOL): TRUE
rvchanrate (NUMBER): 48000
rvchanformat (NUMBER): 0x00000010
channel_info (NVLIST_ARRAY): 1
name (STRING): dsp0.virtual_play.0
parentchan (STRING): dsp0.play.0
unit (NUMBER): 1
caps (NUMBER): 0x073200
latency (NUMBER): 2
rate (NUMBER): 48000
format (NUMBER): 0x201000
pid (NUMBER): 1234
comm (STRING): mpv
interrupts (NUMBER): 0
feedcount (NUMBER): 0
xruns (NUMBER): 0
left_volume (NUMBER): 45
right_volume (NUMBER): 45
hwbuf_fmt (NUMBER): 0x200010
hwbuf_rate (NUMBER): 48000
hwbuf_size (NUMBER): 0
hwbuf_blksz (NUMBER): 0
hwbuf_blkcnt (NUMBER): 0
hwbuf_free (NUMBER): 0
hwbuf_ready (NUMBER): 0
swbuf_fmt (NUMBER): 0x201000
swbuf_rate (NUMBER): 48000
swbuf_size (NUMBER): 16384
swbuf_blksz (NUMBER): 2048
swbuf_blkcnt (NUMBER): 8
swbuf_free (NUMBER): 16384
swbuf_ready (NUMBER): 0
feederchain (STRING):
[userland ->
feeder_root(0x00201000) ->
feeder_format(0x00201000 -> 0x00200010) ->
feeder_volume(0x00200010) -> hardware]
provider (STRING): [sound(4)]
from_userβ whether the PCM audio device node is made by the in-kernel audio subsystem or by userspace providers. lowkey important context πnameunitβ the device identification, shaped like subsystem plus a unit number.devnodeβ the PCM audio device node relative path in devfs.descβ the description of the PCM audio device.pchanβ the number of playback channels supported by hardware. This can be0if this PCM audio device does not support playback at all.rchanβ the number of recording channels supported by hardware. This can be0if this PCM audio device does not support recording at all.info_playβ supported configurations in playback direction. This exists only if this PCM audio device supports playback. There are a number of name/value pairs inside this field:min_rateβ minimum supported sampling rate.max_rateβ maximum supported sampling rate.formatsβ supported sample formats.min_chnβ minimum supported number of channels in channel layout.max_chnβ maximum supported number of channels in channel layout.
info_recβ supported configurations in recording direction. This exists only if this PCM audio device supports recording. There are a number of name/value pairs inside this field:min_rateβ minimum supported sampling rate.max_rateβ maximum supported sampling rate.formatsβ supported sample formats.min_chnβ minimum supported number of channels in channel layout.max_chnβ maximum supported number of channels in channel layout.
provider_infoβ provider-specific fields. This field may not exist if the PCM audio device is not provided by in-kernel interface. This field will not exist if theproviderfield is an empty string. For thesound(4)provider, there are a number of name/value pairs inside this field:unitβ sound card unit.statusβ status string. Usually reports the driver the device is attached on.bitperfectβ whether the sound card has bit-perfect mode enabled.pvchanβ playback virtual channels enabled.pvchanrateβ playback virtual channel sample rate.pvchanformatβ playback virtual channel format.rvchanβ recording virtual channels enabled.rvchanrateβ recording virtual channel sample rate.rvchanformatβ recording virtual channel format.channel_infoβ channel information. There are a number of name/value pairs inside this field:nameβ channel name.parentchanβ parent channel name (e.g., in the case of virtual channels).unitβ channel unit.capsβ OSS capabilities.latencyβ latency.rateβ sampling rate.formatβ sampling format.pidβ PID of the process consuming the channel.commβ name of the process consuming the channel.interruptsβ number of interrupts since the channel has been opened.xrunsβ number of overruns/underruns, depending on channel direction.feedcountβ number of read/written bytes since the channel has been opened.left_volumeβ left volume.right_volumeβ right volume.hwbuf_formatβ hardware buffer format.hwbuf_rateβ hardware buffer sample rate.hwbuf_sizeβ hardware buffer size.hwbuf_blkszβ hardware buffer block size.hwbuf_blkcntβ hardware buffer block count.hwbuf_freeβ free space in hardware buffer (in bytes).hwbuf_readyβ number of bytes ready to be read/written from hardware buffer.swbuf_formatβ software buffer format.swbuf_rateβ software buffer sample rate.swbuf_sizeβ software buffer size.swbuf_blkszβ software buffer block size.swbuf_blkcntβ software buffer block count.swbuf_freeβ free space in software buffer (in bytes).swbuf_readyβ number of bytes ready to be read/written from software buffer.feederchainβ channel feeder chain.
providerβ a string specifying the provider of the PCm audio device. yes bestie, it's literally just the provider name in string form π
The following ioctls are provided for use:
SNDSTIOC_REFRESH_DEVSβ drop any previously fetched PCM audio devices list snapshots. This ioctl takes no arguments. clean slate energy, periodt β¨SNDSTIOC_GET_DEVSβ okay so this one generates and/or returns PCM audio device list snapshots to whoever's calling. It takes a pointer tostruct sndstioc_nv_argas the first and the only argument. You gotta hand it a buffer that's big enough to hold a serialized nvlist. If there's no existing PCM audio device list snapshot sitting in the internal structure of the openedsndstatfd, a brand new PCM audio device list snapshot gets auto-generated for you (slay, no extra work π ). Callers have to setnbytesto either0or the size of the buffer provided. In casenbytesis0, the buffer size required to hold a serialized nvlist stream of the current snapshot comes back innbytes, andbufis literally ignored π. Otherwise, if the buffer isn't sufficiently large, the ioctl returns success andnbytesgets set to0(sneaky but true). If the buffer provided is sufficiently large,nbytesgets set to the size of the serialized nvlist written to the provided buffer. And once a PCM audio device list snapshot is returned to user-space successfully, the snapshot stored in the subsystem's internal structure of the given fd is freed. Cleanup queen behavior πSNDSTIOC_ADD_USER_DEVSβ adds a list of PCM audio devices provided by callers to the/dev/sndstatdevice π«Ά. Takes a pointer tostruct sndstioc_nv_argas the first and the only argument. Callers have to provide a buffer holding a serialized nvlist.nbytesshould be set to the length in bytes of the serialized nvlist, andbufshould be pointed to a buffer storing that serialized nvlist. Userspace-backed PCM audio device nodes should be listed inside the serialized nvlist, iykyk β¨SNDSTIOC_FLUSH_USER_DEVSβ flushes any PCM audio devices previously added by callers. Takes no arguments, zero notes, just vibes π
π FILES π
/dev/sndstat
πΈ EXAMPLES πΈ
The following code enumerates all available PCM audio devices β bestie this whole block is iconic, don't touch a single character of it fr fr:
#include <sys/types.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/nv.h>
#include <sys/sndstat.h>
#include <sysexits.h>
#include <unistd.h>
int
main()
{
int fd;
struct sndstioc_nv_arg arg;
const nvlist_t * const *di;
size_t i, nitems;
nvlist_t *nvl;
/* Open sndstat node in read-only first */
fd = open("/dev/sndstat", O_RDONLY);
if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL))
err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)");
/* Get the size of snapshot, when nbytes = 0 */
arg.nbytes = 0;
arg.buf = NULL;
if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg))
err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)");
/* Get snapshot data */
arg.buf = malloc(arg.nbytes);
if (arg.buf == NULL)
err(EX_OSERR, "malloc");
if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg))
err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)");
/* Deserialize the nvlist stream */
nvl = nvlist_unpack(arg.buf, arg.nbytes, 0);
free(arg.buf);
/* Get DSPs array */
di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems);
for (i = 0; i < nitems; i++) {
const char *nameunit, *devnode, *desc;
/*
* Examine each device nvlist item
*/
nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT);
devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE);
desc = nvlist_get_string(di[i], SNDST_DSPS_DESC);
printf("Name unit: `%s`, Device node: `%s`, Description: `%s`0,
nameunit, devnode, desc);
}
nvlist_destroy(nvl);
return (0);
}
π¦ SEE ALSO π¦
β HISTORY β
The nvlist-based ioctls support for sndstat device first appeared in FreeBSD 13.0 β¨ like, ancient history bestie, but we respect the origin story π
π AUTHORS π
This manual page was written by Ka Ho Ng <khng@FreeBSD.org> β thank you for your service π«Ά
and that's a wrap on SNDSTAT(4), bestie π This little beauty hit the streets via Debian on July 26, 2024, so go forth, read your device lists, and slay β¨ππ¦
π¦ where this page comes from
- freebsd 15.1: base 15.1
- nixpkgs unstable: source
- π the page's license: BSD-2-Clause
- Copyright (c) 2020 The FreeBSD Foundation
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms