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.\" $FreeBSD$ 31.\" 32.\" Note: The date here should be updated whenever a non-trivial 33.\" change is made to the manual page. 34.Dd April 15, 2021 35.Dt SNDSTAT 4 36.Os 37.Sh NAME 38.Nm sndstat 39.Nd "nvlist-based PCM audio device enumeration interface" 40.Sh SYNOPSIS 41To compile the driver into the kernel, 42place the following lines in the 43kernel configuration file: 44.Bd -ragged -offset indent 45.Cd "device sound" 46.Ed 47.Sh DESCRIPTION 48The ioctl interface provided by 49.Pa /dev/sndstat 50device allows callers to enumerate PCM audio devices available for use. 51In other words, it provides means to get the list of all audio devices 52available to the system. 53.Sh IOCTLS 54For ioctl calls that take an argument, the following structure is used: 55.Bd -literal -offset indent 56struct sndstioc_nv_arg { 57 size_t nbytes; 58 void *buf; 59}; 60.Ed 61.Pp 62Here is an example of an nvlist object with explanations of the common fields: 63.Bd -literal -offset indent 64dsps (NVLIST ARRAY): 1 65 from_user (BOOL): FALSE 66 nameunit (STRING): [pcm0] 67 devnode (STRING): [dsp0] 68 desc (STRING): [Generic (0x8086) (Analog Line-out)] 69 pchan (NUMBER): 1 (1) (0x1) 70 rchan (NUMBER): 0 (0) (0x0) 71 info_play (NVLIST): 72 min_rate (NUMBER): 48000 (48000) (0xbb80) 73 max_rate (NUMBER): 48000 (48000) (0xbb80) 74 formats (NUMBER): 16 (16) (0x10) 75 min_chn (NUMBER): 2 (2) (0x2) 76 max_chn (NUMBER): 2 (2) (0x2) 77 provider_info (NVLIST): 78 unit (NUMBER): 0 (0) (0x0) 79 bitperfect (BOOL): FALSE 80 pvchan (NUMBER): 1 (1) (0x1) 81 rvchan (NUMBER): 0 (0) (0x0) 82 provider (STRING): [sound(4)] 83 , 84.Ed 85.Bl -tag -width ".Dv provider_info" 86.It Dv from_user 87Whether the PCM audio device node is created by in-kernel audio subsystem or 88userspace providers. 89.It Dv nameunit 90The device identification in the form of subsystem plus a unit number. 91.It Dv devnode 92The PCM audio device node relative path in devfs. 93.It Dv desc 94The descripton of the PCM audio device. 95.It Dv pchan 96The number of playback channels supported by hardware. 97This can be 0 if this PCM audio device does not support playback at all. 98.It Dv rchan 99The number of recording channels supported by hardware. 100This can be 0 if this PCM audio device does not support recording at all. 101.It Dv info_play 102Supported configurations in playback direction. 103This exists only if this PCM audio device supports playback. 104There are a number of name/value pairs inside this field: 105.Bl -tag -width ".Dv min_rate" 106.It Dv min_rate 107Minimum supported sampling rate. 108.It Dv max_rate 109Maximum supported sampling rate. 110.It Dv formats 111Supported sample formats. 112.It Dv min_chn 113Minimum supported number of channels in channel layout 114.It Dv max_chn 115Maximum supported number of channels in channel layout 116.El 117.It Dv info_rec 118Supported configurations in recording direction. 119This exists only if this PCM audio device supports recording. 120There are a number of name/value pairs inside this field: 121.Bl -tag -width ".Dv min_rate" 122.It Dv min_rate 123Minimum supported sampling rate. 124.It Dv max_rate 125Maximum supported sampling rate. 126.It Dv formats 127Supported sample formats. 128.It Dv min_chn 129Minimum supported number of channels in channel layout 130.It Dv max_chn 131Maximum supported number of channels in channel layout 132.El 133.It Dv provider_info 134Provider-specific fields. 135This field may not exist if the PCM audio device is not provided by in-kernel 136interface. 137This field will not exist if the provider field is an empty string. 138.It Dv provider 139A string specifying the provider of the PCm audio device. 140.El 141.Pp 142The following ioctls are provided for use: 143.Bl -tag -width ".Dv SNDSTIOC_FLUSH_USER_DEVS" 144.It Dv SNDSTIOC_REFRESH_DEVS 145Drop any previously fetched PCM audio devices list snapshots. 146This ioctl takes no arguments. 147.It Dv SNDSTIOC_GET_DEVS 148Generate and/or return PCM audio devices list snapshots to callers. 149This ioctl takes a pointer to 150.Fa struct sndstioc_nv_arg 151as the first and the only argument. 152Callers need to provide a sufficiently large buffer to hold a serialized 153nvlist. 154If there is no existing PCM audio device list snapshot available in the 155internal structure of the opened sndstat. 156.Fa fd , 157a new PCM audio device list snapshot will be automatically generated. 158Callers have to set 159.Fa nbytes 160to either 0 or the size of buffer provided. 161In case 162.Fa nbytes 163is 0, the buffer size required to hold a serialized nvlist 164stream of current snapshot will be returned in 165.Fa nbytes , 166and 167.Fa buf 168will be ignored. 169Otherwise, if the buffer is not sufficiently large, 170the ioctl returns success, and 171.Fa nbytes 172will be set to 0. 173If the buffer provided is sufficiently large, 174.Fa nbytes 175will be set to the size of the serialized nvlist written to the provided buffer. 176Once a PCM audio device list snapshot is returned to user-space successfully, 177the snapshot stored in the subsystem's internal structure of the given 178.Fa fd 179will be freed. 180.It Dv SNDSTIOC_ADD_USER_DEVS 181Add a list of PCM audio devices provided by callers to 182.Pa /dev/sndstat 183device. 184This ioctl takes a pointer to 185.Fa struct sndstioc_nv_arg 186as the first and the only argument. 187Callers have to provide a buffer holding a serialized nvlist. 188.Fa nbytes 189should be set to the length in bytes of the serialized nvlist. 190.Fa buf 191should be pointed to a buffer storing the serialized nvlist. 192Userspace-backed PCM audio device nodes should be listed inside the serialized 193nvlist. 194.It Dv SNDSTIOC_FLUSH_USER_DEVS 195Flush any PCM audio devices previously added by callers. 196This ioctl takes no arguments. 197.El 198.Sh FILES 199.Bl -tag -width ".Pa /dev/sndstat" -compact 200.It Pa /dev/sndstat 201.El 202.Sh EXAMPLES 203The following code enumerates all available PCM audio devices: 204.Bd -literal -offset indent 205#include <sys/types.h> 206#include <err.h> 207#include <fcntl.h> 208#include <stdio.h> 209#include <stdlib.h> 210#include <sys/nv.h> 211#include <sys/sndstat.h> 212#include <sysexits.h> 213#include <unistd.h> 214 215int 216main() 217{ 218 int fd; 219 struct sndstioc_nv_arg arg; 220 const nvlist_t * const *di; 221 size_t i, nitems; 222 nvlist_t *nvl; 223 224 /* Open sndstat node in read-only first */ 225 fd = open("/dev/sndstat", O_RDONLY); 226 227 if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)) 228 err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)"); 229 230 /* Get the size of snapshot, when nbytes = 0 */ 231 arg.nbytes = 0; 232 arg.buf = NULL; 233 if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 234 err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 235 236 /* Get snapshot data */ 237 arg.buf = malloc(arg.nbytes); 238 if (arg.buf == NULL) 239 err(EX_OSERR, "malloc"); 240 if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 241 err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 242 243 /* Deserialize the nvlist stream */ 244 nvl = nvlist_unpack(arg.buf, arg.nbytes, 0); 245 free(arg.buf); 246 247 /* Get DSPs array */ 248 di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems); 249 for (i = 0; i < nitems; i++) { 250 const char *nameunit, *devnode, *desc; 251 252 /* 253 * Examine each device nvlist item 254 */ 255 256 nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT); 257 devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE); 258 desc = nvlist_get_string(di[i], SNDST_DSPS_DESC); 259 printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n", 260 nameunit, devnode, desc); 261 } 262 263 nvlist_destroy(nvl); 264 return (0); 265} 266.Ed 267.Sh SEE ALSO 268.Xr sound 4 , 269.Xr nv 9 270.Sh HISTORY 271The nvlist-based ioctls support for 272.Nm 273device first appeared in 274.Fx 13.0 . 275.Sh AUTHORS 276This manual page was written by 277.An Ka Ho Ng Aq Mt khng@FreeBSD.org . 278