1.\" 2.\" SPDX-License-Identifier: BSD-2-Clause 3.\" 4.\" This software was developed by Ka Ho Ng 5.\" under sponsorship from the FreeBSD Foundation. 6.\" 7.\" Copyright (c) 2020 The FreeBSD Foundation 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28.\" SUCH DAMAGE. 29.\" 30.\" Note: The date here should be updated whenever a non-trivial 31.\" change is made to the manual page. 32.Dd July 26, 2024 33.Dt SNDSTAT 4 34.Os 35.Sh NAME 36.Nm sndstat 37.Nd "nvlist-based PCM audio device enumeration interface" 38.Sh SYNOPSIS 39To compile the driver into the kernel, 40place the following lines in the 41kernel configuration file: 42.Bd -ragged -offset indent 43.Cd "device sound" 44.Ed 45.Sh DESCRIPTION 46The ioctl interface provided by 47.Pa /dev/sndstat 48device allows callers to enumerate PCM audio devices available for use. 49In other words, it provides means to get the list of all audio devices 50available to the system. 51.Sh IOCTLS 52For ioctl calls that take an argument, the following structure is used: 53.Bd -literal -offset indent 54struct sndstioc_nv_arg { 55 size_t nbytes; 56 void *buf; 57}; 58.Ed 59.Pp 60Here is an example of an nvlist object with explanations of the common fields: 61.Bd -literal -offset indent 62dsps (NVLIST ARRAY): 1 63 from_user (BOOL): FALSE 64 nameunit (STRING): [pcm0] 65 devnode (STRING): [dsp0] 66 desc (STRING): [Generic (0x8086) (Analog Line-out)] 67 pchan (NUMBER): 1 68 rchan (NUMBER): 0 69 info_play (NVLIST): 70 min_rate (NUMBER): 48000 71 max_rate (NUMBER): 48000 72 formats (NUMBER): 16 73 min_chn (NUMBER): 2 74 max_chn (NUMBER): 2 75 provider_info (NVLIST): 76 unit (NUMBER): 0 77 status (STRING): on hdaa0 78 bitperfect (BOOL): FALSE 79 pvchan (NUMBER): 1 80 pvchanrate (NUMBER): 48000 81 pvchanformat (NUMBER): 0x00000010 82 rvchan (NUMBER): 0 83 rvchanrate (NUMBER): 48000 84 rvchanformat (NUMBER): 0x00000010 85 channel_info (NVLIST_ARRAY): 1 86 name (STRING): pcm0:virtual_play:dsp0.vp0 87 parentchan (STRING): pcm0:play:dsp0.p0 88 unit (NUMBER): 1 89 caps (NUMBER): 0x073200 90 latency (NUMBER): 2 91 rate (NUMBER): 48000 92 format (NUMBER): 0x201000 93 pid (NUMBER): 1234 94 comm (STRING): mpv 95 interrupts (NUMBER): 0 96 feedcount (NUMBER): 0 97 xruns (NUMBER): 0 98 left_volume (NUMBER): 45 99 right_volume (NUMBER): 45 100 hwbuf_fmt (NUMBER): 0x200010 101 hwbuf_size (NUMBER): 0 102 hwbuf_blksz (NUMBER): 0 103 hwbuf_blkcnt (NUMBER): 0 104 hwbuf_free (NUMBER): 0 105 hwbuf_ready (NUMBER): 0 106 swbuf_fmt (NUMBER): 0x201000 107 swbuf_size (NUMBER): 16384 108 swbuf_blksz (NUMBER): 2048 109 swbuf_blkcnt (NUMBER): 8 110 swbuf_free (NUMBER): 16384 111 swbuf_ready (NUMBER): 0 112 feederchain (STRING): 113 [userland -> 114 feeder_root(0x00201000) -> 115 feeder_format(0x00201000 -> 0x00200010) -> 116 feeder_volume(0x00200010) -> hardware] 117 provider (STRING): [sound(4)] 118.Ed 119.Bl -tag -width ".Dv provider_info" 120.It Dv from_user 121Whether the PCM audio device node is created by in-kernel audio subsystem or 122userspace providers. 123.It Dv nameunit 124The device identification in the form of subsystem plus a unit number. 125.It Dv devnode 126The PCM audio device node relative path in devfs. 127.It Dv desc 128The description of the PCM audio device. 129.It Dv pchan 130The number of playback channels supported by hardware. 131This can be 0 if this PCM audio device does not support playback at all. 132.It Dv rchan 133The number of recording channels supported by hardware. 134This can be 0 if this PCM audio device does not support recording at all. 135.It Dv info_play 136Supported configurations in playback direction. 137This exists only if this PCM audio device supports playback. 138There are a number of name/value pairs inside this field: 139.Bl -tag -width ".Dv min_rate" 140.It Dv min_rate 141Minimum supported sampling rate. 142.It Dv max_rate 143Maximum supported sampling rate. 144.It Dv formats 145Supported sample formats. 146.It Dv min_chn 147Minimum supported number of channels in channel layout 148.It Dv max_chn 149Maximum supported number of channels in channel layout 150.El 151.It Dv info_rec 152Supported configurations in recording direction. 153This exists only if this PCM audio device supports recording. 154There are a number of name/value pairs inside this field: 155.Bl -tag -width ".Dv min_rate" 156.It Dv min_rate 157Minimum supported sampling rate. 158.It Dv max_rate 159Maximum supported sampling rate. 160.It Dv formats 161Supported sample formats. 162.It Dv min_chn 163Minimum supported number of channels in channel layout 164.It Dv max_chn 165Maximum supported number of channels in channel layout 166.El 167.It Dv provider_info 168Provider-specific fields. 169This field may not exist if the PCM audio device is not provided by in-kernel 170interface. 171This field will not exist if the provider field is an empty string. 172For the 173.Xr sound 4 174provider, there are a number of name/value pairs inside this field: 175.Bl -tag -width ".Dv channel_info" 176.It Dv unit 177Sound card unit. 178.It Dv status 179Status string. 180Usually reports the driver the device is attached on. 181.It Dv bitperfect 182Whether the sound card has bit-perfect mode enabled. 183.It Dv pvchan 184Number of playback virtual channels. 185.It Dv pvchanrate 186Playback virtual channel sample rate. 187.It Dv pvchanformat 188Playback virtual channel format. 189.It Dv rvchan 190Number of recording virtual channels. 191.It Dv rvchanrate 192Recording virtual channel sample rate. 193.It Dv rvchanformat 194Recording virtual channel format. 195.It Dv channel_info 196Channel information. 197There are a number of name/value pairs inside this field: 198.Bl -tag -width ".Dv hwbuf_blkcnt" 199.It Dv name 200Channel name. 201.It Dv parentchan 202Parent channel name (e.g., in the case of virtual channels). 203.It Dv unit 204Channel unit. 205.It Dv caps 206OSS capabilities. 207.It Dv latency 208Latency. 209.It Dv rate 210Sampling rate. 211.It Dv format 212Sampling format. 213.It Dv pid 214PID of the process consuming the channel. 215.It Dv comm 216Name of the process consuming the channel. 217.It Dv interrupts 218Number of interrupts since the channel has been opened. 219.It Dv xruns 220Number of overruns/underruns, depending on channel direction. 221.It Dv feedcount 222Number of read/written bytes since the channel has been opened. 223.It Dv left_volume 224Left volume. 225.It Dv right_volume 226Right volume. 227.It Dv hwbuf_format 228Hardware buffer format. 229.It Dv hwbuf_size 230Hardware buffer size. 231.It Dv hwbuf_blksz 232Hardware buffer block size. 233.It Dv hwbuf_blkcnt 234Hardware buffer block count. 235.It Dv hwbuf_free 236Free space in hardware buffer (in bytes). 237.It Dv hwbuf_ready 238Number of bytes ready to be read/written from hardware buffer. 239.It Dv swbuf_format 240Software buffer format. 241.It Dv swbuf_size 242Software buffer size. 243.It Dv swbuf_blksz 244Software buffer block size. 245.It Dv swbuf_blkcnt 246Software buffer block count. 247.It Dv swbuf_free 248Free space in software buffer (in bytes). 249.It Dv swbuf_ready 250Number of bytes ready to be read/written from software buffer. 251.It Dv feederchain 252Channel feeder chain. 253.El 254.El 255.It Dv provider 256A string specifying the provider of the PCm audio device. 257.El 258.Pp 259The following ioctls are provided for use: 260.Bl -tag -width ".Dv SNDSTIOC_FLUSH_USER_DEVS" 261.It Dv SNDSTIOC_REFRESH_DEVS 262Drop any previously fetched PCM audio devices list snapshots. 263This ioctl takes no arguments. 264.It Dv SNDSTIOC_GET_DEVS 265Generate and/or return PCM audio devices list snapshots to callers. 266This ioctl takes a pointer to 267.Fa struct sndstioc_nv_arg 268as the first and the only argument. 269Callers need to provide a sufficiently large buffer to hold a serialized 270nvlist. 271If there is no existing PCM audio device list snapshot available in the 272internal structure of the opened sndstat. 273.Fa fd , 274a new PCM audio device list snapshot will be automatically generated. 275Callers have to set 276.Fa nbytes 277to either 0 or the size of buffer provided. 278In case 279.Fa nbytes 280is 0, the buffer size required to hold a serialized nvlist 281stream of current snapshot will be returned in 282.Fa nbytes , 283and 284.Fa buf 285will be ignored. 286Otherwise, if the buffer is not sufficiently large, 287the ioctl returns success, and 288.Fa nbytes 289will be set to 0. 290If the buffer provided is sufficiently large, 291.Fa nbytes 292will be set to the size of the serialized nvlist written to the provided buffer. 293Once a PCM audio device list snapshot is returned to user-space successfully, 294the snapshot stored in the subsystem's internal structure of the given 295.Fa fd 296will be freed. 297.It Dv SNDSTIOC_ADD_USER_DEVS 298Add a list of PCM audio devices provided by callers to 299.Pa /dev/sndstat 300device. 301This ioctl takes a pointer to 302.Fa struct sndstioc_nv_arg 303as the first and the only argument. 304Callers have to provide a buffer holding a serialized nvlist. 305.Fa nbytes 306should be set to the length in bytes of the serialized nvlist. 307.Fa buf 308should be pointed to a buffer storing the serialized nvlist. 309Userspace-backed PCM audio device nodes should be listed inside the serialized 310nvlist. 311.It Dv SNDSTIOC_FLUSH_USER_DEVS 312Flush any PCM audio devices previously added by callers. 313This ioctl takes no arguments. 314.El 315.Sh FILES 316.Bl -tag -width ".Pa /dev/sndstat" -compact 317.It Pa /dev/sndstat 318.El 319.Sh EXAMPLES 320The following code enumerates all available PCM audio devices: 321.Bd -literal -offset indent 322#include <sys/types.h> 323#include <err.h> 324#include <fcntl.h> 325#include <stdio.h> 326#include <stdlib.h> 327#include <sys/nv.h> 328#include <sys/sndstat.h> 329#include <sysexits.h> 330#include <unistd.h> 331 332int 333main() 334{ 335 int fd; 336 struct sndstioc_nv_arg arg; 337 const nvlist_t * const *di; 338 size_t i, nitems; 339 nvlist_t *nvl; 340 341 /* Open sndstat node in read-only first */ 342 fd = open("/dev/sndstat", O_RDONLY); 343 344 if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)) 345 err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)"); 346 347 /* Get the size of snapshot, when nbytes = 0 */ 348 arg.nbytes = 0; 349 arg.buf = NULL; 350 if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 351 err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 352 353 /* Get snapshot data */ 354 arg.buf = malloc(arg.nbytes); 355 if (arg.buf == NULL) 356 err(EX_OSERR, "malloc"); 357 if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 358 err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 359 360 /* Deserialize the nvlist stream */ 361 nvl = nvlist_unpack(arg.buf, arg.nbytes, 0); 362 free(arg.buf); 363 364 /* Get DSPs array */ 365 di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems); 366 for (i = 0; i < nitems; i++) { 367 const char *nameunit, *devnode, *desc; 368 369 /* 370 * Examine each device nvlist item 371 */ 372 373 nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT); 374 devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE); 375 desc = nvlist_get_string(di[i], SNDST_DSPS_DESC); 376 printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n", 377 nameunit, devnode, desc); 378 } 379 380 nvlist_destroy(nvl); 381 return (0); 382} 383.Ed 384.Sh SEE ALSO 385.Xr sound 4 , 386.Xr nv 9 387.Sh HISTORY 388The nvlist-based ioctls support for 389.Nm 390device first appeared in 391.Fx 13.0 . 392.Sh AUTHORS 393This manual page was written by 394.An Ka Ho Ng Aq Mt khng@FreeBSD.org . 395