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 (BOOL): TRUE 80 pvchanrate (NUMBER): 48000 81 pvchanformat (NUMBER): 0x00000010 82 rvchan (BOOL): TRUE 83 rvchanrate (NUMBER): 48000 84 rvchanformat (NUMBER): 0x00000010 85 channel_info (NVLIST_ARRAY): 1 86 name (STRING): dsp0.virtual_play.0 87 parentchan (STRING): dsp0.play.0 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_rate (NUMBER): 48000 102 hwbuf_size (NUMBER): 0 103 hwbuf_blksz (NUMBER): 0 104 hwbuf_blkcnt (NUMBER): 0 105 hwbuf_free (NUMBER): 0 106 hwbuf_ready (NUMBER): 0 107 swbuf_fmt (NUMBER): 0x201000 108 swbuf_rate (NUMBER): 48000 109 swbuf_size (NUMBER): 16384 110 swbuf_blksz (NUMBER): 2048 111 swbuf_blkcnt (NUMBER): 8 112 swbuf_free (NUMBER): 16384 113 swbuf_ready (NUMBER): 0 114 feederchain (STRING): 115 [userland -> 116 feeder_root(0x00201000) -> 117 feeder_format(0x00201000 -> 0x00200010) -> 118 feeder_volume(0x00200010) -> hardware] 119 provider (STRING): [sound(4)] 120.Ed 121.Bl -tag -width ".Dv provider_info" 122.It Dv from_user 123Whether the PCM audio device node is created by in-kernel audio subsystem or 124userspace providers. 125.It Dv nameunit 126The device identification in the form of subsystem plus a unit number. 127.It Dv devnode 128The PCM audio device node relative path in devfs. 129.It Dv desc 130The description of the PCM audio device. 131.It Dv pchan 132The number of playback channels supported by hardware. 133This can be 0 if this PCM audio device does not support playback at all. 134.It Dv rchan 135The number of recording channels supported by hardware. 136This can be 0 if this PCM audio device does not support recording at all. 137.It Dv info_play 138Supported configurations in playback direction. 139This exists only if this PCM audio device supports playback. 140There are a number of name/value pairs inside this field: 141.Bl -tag -width ".Dv min_rate" 142.It Dv min_rate 143Minimum supported sampling rate. 144.It Dv max_rate 145Maximum supported sampling rate. 146.It Dv formats 147Supported sample formats. 148.It Dv min_chn 149Minimum supported number of channels in channel layout 150.It Dv max_chn 151Maximum supported number of channels in channel layout 152.El 153.It Dv info_rec 154Supported configurations in recording direction. 155This exists only if this PCM audio device supports recording. 156There are a number of name/value pairs inside this field: 157.Bl -tag -width ".Dv min_rate" 158.It Dv min_rate 159Minimum supported sampling rate. 160.It Dv max_rate 161Maximum supported sampling rate. 162.It Dv formats 163Supported sample formats. 164.It Dv min_chn 165Minimum supported number of channels in channel layout 166.It Dv max_chn 167Maximum supported number of channels in channel layout 168.El 169.It Dv provider_info 170Provider-specific fields. 171This field may not exist if the PCM audio device is not provided by in-kernel 172interface. 173This field will not exist if the provider field is an empty string. 174For the 175.Xr sound 4 176provider, there are a number of name/value pairs inside this field: 177.Bl -tag -width ".Dv channel_info" 178.It Dv unit 179Sound card unit. 180.It Dv status 181Status string. 182Usually reports the driver the device is attached on. 183.It Dv bitperfect 184Whether the sound card has bit-perfect mode enabled. 185.It Dv pvchan 186Playback virtual channels enabled. 187.It Dv pvchanrate 188Playback virtual channel sample rate. 189.It Dv pvchanformat 190Playback virtual channel format. 191.It Dv rvchan 192Recording virtual channels enabled. 193.It Dv rvchanrate 194Recording virtual channel sample rate. 195.It Dv rvchanformat 196Recording virtual channel format. 197.It Dv channel_info 198Channel information. 199There are a number of name/value pairs inside this field: 200.Bl -tag -width ".Dv hwbuf_blkcnt" 201.It Dv name 202Channel name. 203.It Dv parentchan 204Parent channel name (e.g., in the case of virtual channels). 205.It Dv unit 206Channel unit. 207.It Dv caps 208OSS capabilities. 209.It Dv latency 210Latency. 211.It Dv rate 212Sampling rate. 213.It Dv format 214Sampling format. 215.It Dv pid 216PID of the process consuming the channel. 217.It Dv comm 218Name of the process consuming the channel. 219.It Dv interrupts 220Number of interrupts since the channel has been opened. 221.It Dv xruns 222Number of overruns/underruns, depending on channel direction. 223.It Dv feedcount 224Number of read/written bytes since the channel has been opened. 225.It Dv left_volume 226Left volume. 227.It Dv right_volume 228Right volume. 229.It Dv hwbuf_format 230Hardware buffer format. 231.It Dv hwbuf_rate 232Hardware buffer sample rate; 233.It Dv hwbuf_size 234Hardware buffer size. 235.It Dv hwbuf_blksz 236Hardware buffer block size. 237.It Dv hwbuf_blkcnt 238Hardware buffer block count. 239.It Dv hwbuf_free 240Free space in hardware buffer (in bytes). 241.It Dv hwbuf_ready 242Number of bytes ready to be read/written from hardware buffer. 243.It Dv swbuf_format 244Software buffer format. 245.It Dv swbuf_rate 246Software buffer sample rate; 247.It Dv swbuf_size 248Software buffer size. 249.It Dv swbuf_blksz 250Software buffer block size. 251.It Dv swbuf_blkcnt 252Software buffer block count. 253.It Dv swbuf_free 254Free space in software buffer (in bytes). 255.It Dv swbuf_ready 256Number of bytes ready to be read/written from software buffer. 257.It Dv feederchain 258Channel feeder chain. 259.El 260.El 261.It Dv provider 262A string specifying the provider of the PCm audio device. 263.El 264.Pp 265The following ioctls are provided for use: 266.Bl -tag -width ".Dv SNDSTIOC_FLUSH_USER_DEVS" 267.It Dv SNDSTIOC_REFRESH_DEVS 268Drop any previously fetched PCM audio devices list snapshots. 269This ioctl takes no arguments. 270.It Dv SNDSTIOC_GET_DEVS 271Generate and/or return PCM audio devices list snapshots to callers. 272This ioctl takes a pointer to 273.Fa struct sndstioc_nv_arg 274as the first and the only argument. 275Callers need to provide a sufficiently large buffer to hold a serialized 276nvlist. 277If there is no existing PCM audio device list snapshot available in the 278internal structure of the opened sndstat. 279.Fa fd , 280a new PCM audio device list snapshot will be automatically generated. 281Callers have to set 282.Fa nbytes 283to either 0 or the size of buffer provided. 284In case 285.Fa nbytes 286is 0, the buffer size required to hold a serialized nvlist 287stream of current snapshot will be returned in 288.Fa nbytes , 289and 290.Fa buf 291will be ignored. 292Otherwise, if the buffer is not sufficiently large, 293the ioctl returns success, and 294.Fa nbytes 295will be set to 0. 296If the buffer provided is sufficiently large, 297.Fa nbytes 298will be set to the size of the serialized nvlist written to the provided buffer. 299Once a PCM audio device list snapshot is returned to user-space successfully, 300the snapshot stored in the subsystem's internal structure of the given 301.Fa fd 302will be freed. 303.It Dv SNDSTIOC_ADD_USER_DEVS 304Add a list of PCM audio devices provided by callers to 305.Pa /dev/sndstat 306device. 307This ioctl takes a pointer to 308.Fa struct sndstioc_nv_arg 309as the first and the only argument. 310Callers have to provide a buffer holding a serialized nvlist. 311.Fa nbytes 312should be set to the length in bytes of the serialized nvlist. 313.Fa buf 314should be pointed to a buffer storing the serialized nvlist. 315Userspace-backed PCM audio device nodes should be listed inside the serialized 316nvlist. 317.It Dv SNDSTIOC_FLUSH_USER_DEVS 318Flush any PCM audio devices previously added by callers. 319This ioctl takes no arguments. 320.El 321.Sh FILES 322.Bl -tag -width ".Pa /dev/sndstat" -compact 323.It Pa /dev/sndstat 324.El 325.Sh EXAMPLES 326The following code enumerates all available PCM audio devices: 327.Bd -literal -offset indent 328#include <sys/types.h> 329#include <err.h> 330#include <fcntl.h> 331#include <stdio.h> 332#include <stdlib.h> 333#include <sys/nv.h> 334#include <sys/sndstat.h> 335#include <sysexits.h> 336#include <unistd.h> 337 338int 339main() 340{ 341 int fd; 342 struct sndstioc_nv_arg arg; 343 const nvlist_t * const *di; 344 size_t i, nitems; 345 nvlist_t *nvl; 346 347 /* Open sndstat node in read-only first */ 348 fd = open("/dev/sndstat", O_RDONLY); 349 350 if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)) 351 err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)"); 352 353 /* Get the size of snapshot, when nbytes = 0 */ 354 arg.nbytes = 0; 355 arg.buf = NULL; 356 if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 357 err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 358 359 /* Get snapshot data */ 360 arg.buf = malloc(arg.nbytes); 361 if (arg.buf == NULL) 362 err(EX_OSERR, "malloc"); 363 if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 364 err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 365 366 /* Deserialize the nvlist stream */ 367 nvl = nvlist_unpack(arg.buf, arg.nbytes, 0); 368 free(arg.buf); 369 370 /* Get DSPs array */ 371 di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems); 372 for (i = 0; i < nitems; i++) { 373 const char *nameunit, *devnode, *desc; 374 375 /* 376 * Examine each device nvlist item 377 */ 378 379 nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT); 380 devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE); 381 desc = nvlist_get_string(di[i], SNDST_DSPS_DESC); 382 printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n", 383 nameunit, devnode, desc); 384 } 385 386 nvlist_destroy(nvl); 387 return (0); 388} 389.Ed 390.Sh SEE ALSO 391.Xr sound 4 , 392.Xr nv 9 393.Sh HISTORY 394The nvlist-based ioctls support for 395.Nm 396device first appeared in 397.Fx 13.0 . 398.Sh AUTHORS 399This manual page was written by 400.An Ka Ho Ng Aq Mt khng@FreeBSD.org . 401