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