1c96151d3SKa Ho Ng.\" 2c96151d3SKa Ho Ng.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3c96151d3SKa Ho Ng.\" 4c96151d3SKa Ho Ng.\" This software was developed by Ka Ho Ng 5c96151d3SKa Ho Ng.\" under sponsorship from the FreeBSD Foundation. 6c96151d3SKa Ho Ng.\" 7c96151d3SKa Ho Ng.\" Copyright (c) 2020 The FreeBSD Foundation 8c96151d3SKa Ho Ng.\" 9c96151d3SKa Ho Ng.\" Redistribution and use in source and binary forms, with or without 10c96151d3SKa Ho Ng.\" modification, are permitted provided that the following conditions 11c96151d3SKa Ho Ng.\" are met: 12c96151d3SKa Ho Ng.\" 1. Redistributions of source code must retain the above copyright 13c96151d3SKa Ho Ng.\" notice, this list of conditions and the following disclaimer. 14c96151d3SKa Ho Ng.\" 2. Redistributions in binary form must reproduce the above copyright 15c96151d3SKa Ho Ng.\" notice, this list of conditions and the following disclaimer in the 16c96151d3SKa Ho Ng.\" documentation and/or other materials provided with the distribution. 17c96151d3SKa Ho Ng.\" 18c96151d3SKa Ho Ng.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19c96151d3SKa Ho Ng.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20c96151d3SKa Ho Ng.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21c96151d3SKa Ho Ng.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22c96151d3SKa Ho Ng.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23c96151d3SKa Ho Ng.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24c96151d3SKa Ho Ng.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25c96151d3SKa Ho Ng.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26c96151d3SKa Ho Ng.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27c96151d3SKa Ho Ng.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28c96151d3SKa Ho Ng.\" SUCH DAMAGE. 29c96151d3SKa Ho Ng.\" 30c96151d3SKa Ho Ng.\" $FreeBSD$ 31c96151d3SKa Ho Ng.\" 32c96151d3SKa Ho Ng.\" Note: The date here should be updated whenever a non-trivial 33c96151d3SKa Ho Ng.\" change is made to the manual page. 344ce1ba65SKa Ho Ng.Dd April 15, 2021 35c96151d3SKa Ho Ng.Dt SNDSTAT 4 36c96151d3SKa Ho Ng.Os 37c96151d3SKa Ho Ng.Sh NAME 38c96151d3SKa Ho Ng.Nm sndstat 39c96151d3SKa Ho Ng.Nd "nvlist-based PCM audio device enumeration interface" 40c96151d3SKa Ho Ng.Sh SYNOPSIS 41c96151d3SKa Ho NgTo compile the driver into the kernel, 42c96151d3SKa Ho Ngplace the following lines in the 43c96151d3SKa Ho Ngkernel configuration file: 44c96151d3SKa Ho Ng.Bd -ragged -offset indent 45c96151d3SKa Ho Ng.Cd "device sound" 46c96151d3SKa Ho Ng.Ed 47c96151d3SKa Ho Ng.Sh DESCRIPTION 48c96151d3SKa Ho NgThe ioctl interface provided by 49c96151d3SKa Ho Ng.Pa /dev/sndstat 50*c232fd4bSGoran Mekićdevice allows callers to enumerate PCM audio devices available for use. 51*c232fd4bSGoran MekićIn other words, it provides means to get the list of all audio devices 52*c232fd4bSGoran Mekićavailable to the system. 53c96151d3SKa Ho Ng.Sh IOCTLS 54*c232fd4bSGoran MekićFor ioctl calls that take an argument, the following structure is used: 55c96151d3SKa Ho Ng.Bd -literal -offset indent 564ce1ba65SKa Ho Ngstruct sndstioc_nv_arg { 57c96151d3SKa Ho Ng size_t nbytes; 58c96151d3SKa Ho Ng void *buf; 59c96151d3SKa Ho Ng}; 60c96151d3SKa Ho Ng.Ed 61c96151d3SKa Ho Ng.Pp 62*c232fd4bSGoran MekićHere is an example of an nvlist object with explanations of the common fields: 63c96151d3SKa Ho Ng.Bd -literal -offset indent 64c96151d3SKa Ho Ngdsps (NVLIST ARRAY): 1 65c96151d3SKa Ho Ng from_user (BOOL): FALSE 66c96151d3SKa Ho Ng nameunit (STRING): [pcm0] 67c96151d3SKa Ho Ng devnode (STRING): [dsp0] 68c96151d3SKa Ho Ng desc (STRING): [Generic (0x8086) (Analog Line-out)] 69c96151d3SKa Ho Ng pchan (NUMBER): 1 (1) (0x1) 70c96151d3SKa Ho Ng rchan (NUMBER): 0 (0) (0x0) 714ce1ba65SKa Ho Ng info_play (NVLIST): 724ce1ba65SKa Ho Ng min_rate (NUMBER): 48000 (48000) (0xbb80) 734ce1ba65SKa Ho Ng max_rate (NUMBER): 48000 (48000) (0xbb80) 744ce1ba65SKa Ho Ng formats (NUMBER): 16 (16) (0x10) 754ce1ba65SKa Ho Ng min_chn (NUMBER): 2 (2) (0x2) 764ce1ba65SKa Ho Ng max_chn (NUMBER): 2 (2) (0x2) 77c96151d3SKa Ho Ng provider_info (NVLIST): 78c96151d3SKa Ho Ng unit (NUMBER): 0 (0) (0x0) 79c96151d3SKa Ho Ng bitperfect (BOOL): FALSE 80c96151d3SKa Ho Ng pvchan (NUMBER): 1 (1) (0x1) 81c96151d3SKa Ho Ng rvchan (NUMBER): 0 (0) (0x0) 82c96151d3SKa Ho Ng provider (STRING): [sound(4)] 83c96151d3SKa Ho Ng , 84c96151d3SKa Ho Ng.Ed 85c96151d3SKa Ho Ng.Bl -tag -width ".Dv provider_info" 86c96151d3SKa Ho Ng.It Dv from_user 87c96151d3SKa Ho NgWhether the PCM audio device node is created by in-kernel audio subsystem or 88c96151d3SKa Ho Nguserspace providers. 89c96151d3SKa Ho Ng.It Dv nameunit 90c96151d3SKa Ho NgThe device identification in the form of subsystem plus a unit number. 91c96151d3SKa Ho Ng.It Dv devnode 92c96151d3SKa Ho NgThe PCM audio device node relative path in devfs. 93c96151d3SKa Ho Ng.It Dv desc 94c96151d3SKa Ho NgThe descripton of the PCM audio device. 95c96151d3SKa Ho Ng.It Dv pchan 96c96151d3SKa Ho NgThe number of playback channels supported by hardware. 97c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support playback at all. 98c96151d3SKa Ho Ng.It Dv rchan 99c96151d3SKa Ho NgThe number of recording channels supported by hardware. 100c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support recording at all. 1014ce1ba65SKa Ho Ng.It Dv info_play 1024ce1ba65SKa Ho NgSupported configurations in playback direction. 1034ce1ba65SKa Ho NgThis exists only if this PCM audio device supports playback. 1044ce1ba65SKa Ho NgThere are a number of name/value pairs inside this field: 1054ce1ba65SKa Ho Ng.Bl -tag -width ".Dv min_rate" 1064ce1ba65SKa Ho Ng.It Dv min_rate 1074ce1ba65SKa Ho NgMinimum supported sampling rate. 1084ce1ba65SKa Ho Ng.It Dv max_rate 1094ce1ba65SKa Ho NgMaximum supported sampling rate. 1104ce1ba65SKa Ho Ng.It Dv formats 1114ce1ba65SKa Ho NgSupported sample formats. 1124ce1ba65SKa Ho Ng.It Dv min_chn 1134ce1ba65SKa Ho NgMinimum supported number of channels in channel layout 1144ce1ba65SKa Ho Ng.It Dv max_chn 1154ce1ba65SKa Ho NgMaximum supported number of channels in channel layout 1164ce1ba65SKa Ho Ng.El 1174ce1ba65SKa Ho Ng.It Dv info_rec 1184ce1ba65SKa Ho NgSupported configurations in recording direction. 1194ce1ba65SKa Ho NgThis exists only if this PCM audio device supports recording. 1204ce1ba65SKa Ho NgThere are a number of name/value pairs inside this field: 1214ce1ba65SKa Ho Ng.Bl -tag -width ".Dv min_rate" 1224ce1ba65SKa Ho Ng.It Dv min_rate 1234ce1ba65SKa Ho NgMinimum supported sampling rate. 1244ce1ba65SKa Ho Ng.It Dv max_rate 1254ce1ba65SKa Ho NgMaximum supported sampling rate. 1264ce1ba65SKa Ho Ng.It Dv formats 1274ce1ba65SKa Ho NgSupported sample formats. 1284ce1ba65SKa Ho Ng.It Dv min_chn 1294ce1ba65SKa Ho NgMinimum supported number of channels in channel layout 1304ce1ba65SKa Ho Ng.It Dv max_chn 1314ce1ba65SKa Ho NgMaximum supported number of channels in channel layout 1324ce1ba65SKa Ho Ng.El 133c96151d3SKa Ho Ng.It Dv provider_info 134c96151d3SKa Ho NgProvider-specific fields. 135c96151d3SKa Ho NgThis field may not exist if the PCM audio device is not provided by in-kernel 136c96151d3SKa Ho Nginterface. 137c96151d3SKa Ho NgThis field will not exist if the provider field is an empty string. 138c96151d3SKa Ho Ng.It Dv provider 139c96151d3SKa Ho NgA string specifying the provider of the PCm audio device. 140c96151d3SKa Ho Ng.El 141c96151d3SKa Ho Ng.Pp 1424ce1ba65SKa Ho NgThe following ioctls are provided for use: 1434ce1ba65SKa Ho Ng.Bl -tag -width ".Dv SNDSTIOC_FLUSH_USER_DEVS" 1444ce1ba65SKa Ho Ng.It Dv SNDSTIOC_REFRESH_DEVS 145c96151d3SKa Ho NgDrop any previously fetched PCM audio devices list snapshots. 146c96151d3SKa Ho NgThis ioctl takes no arguments. 1474ce1ba65SKa Ho Ng.It Dv SNDSTIOC_GET_DEVS 148c96151d3SKa Ho NgGenerate and/or return PCM audio devices list snapshots to callers. 149c96151d3SKa Ho NgThis ioctl takes a pointer to 1504ce1ba65SKa Ho Ng.Fa struct sndstioc_nv_arg 151c96151d3SKa Ho Ngas the first and the only argument. 152c96151d3SKa Ho NgCallers need to provide a sufficiently large buffer to hold a serialized 153c96151d3SKa Ho Ngnvlist. 154c96151d3SKa Ho NgIf there is no existing PCM audio device list snapshot available in the 155c96151d3SKa Ho Nginternal structure of the opened sndstat. 156c96151d3SKa Ho Ng.Fa fd , 157c96151d3SKa Ho Nga new PCM audio device list snapshot will be automatically generated. 158c96151d3SKa Ho NgCallers have to set 159c96151d3SKa Ho Ng.Fa nbytes 160c96151d3SKa Ho Ngto either 0 or the size of buffer provided. 161c96151d3SKa Ho NgIn case 162c96151d3SKa Ho Ng.Fa nbytes 163c96151d3SKa Ho Ngis 0, the buffer size required to hold a serialized nvlist 164c96151d3SKa Ho Ngstream of current snapshot will be returned in 165c96151d3SKa Ho Ng.Fa nbytes , 166c96151d3SKa Ho Ngand 167c96151d3SKa Ho Ng.Fa buf 168c96151d3SKa Ho Ngwill be ignored. 169c96151d3SKa Ho NgOtherwise, if the buffer is not sufficiently large, 170c96151d3SKa Ho Ngthe ioctl returns success, and 171c96151d3SKa Ho Ng.Fa nbytes 172c96151d3SKa Ho Ngwill be set to 0. 173c96151d3SKa Ho NgIf the buffer provided is sufficiently large, 174c96151d3SKa Ho Ng.Fa nbytes 175c96151d3SKa Ho Ngwill be set to the size of the serialized nvlist written to the provided buffer. 176c96151d3SKa Ho NgOnce a PCM audio device list snapshot is returned to user-space successfully, 177c96151d3SKa Ho Ngthe snapshot stored in the subsystem's internal structure of the given 178c96151d3SKa Ho Ng.Fa fd 179c96151d3SKa Ho Ngwill be freed. 1804ce1ba65SKa Ho Ng.It Dv SNDSTIOC_ADD_USER_DEVS 181c96151d3SKa Ho NgAdd a list of PCM audio devices provided by callers to 182c96151d3SKa Ho Ng.Pa /dev/sndstat 183c96151d3SKa Ho Ngdevice. 184c96151d3SKa Ho NgThis ioctl takes a pointer to 1854ce1ba65SKa Ho Ng.Fa struct sndstioc_nv_arg 186c96151d3SKa Ho Ngas the first and the only argument. 187c96151d3SKa Ho NgCallers have to provide a buffer holding a serialized nvlist. 188c96151d3SKa Ho Ng.Fa nbytes 189c96151d3SKa Ho Ngshould be set to the length in bytes of the serialized nvlist. 190c96151d3SKa Ho Ng.Fa buf 191c96151d3SKa Ho Ngshould be pointed to a buffer storing the serialized nvlist. 192c96151d3SKa Ho NgUserspace-backed PCM audio device nodes should be listed inside the serialized 193c96151d3SKa Ho Ngnvlist. 1944ce1ba65SKa Ho Ng.It Dv SNDSTIOC_FLUSH_USER_DEVS 195c96151d3SKa Ho NgFlush any PCM audio devices previously added by callers. 196c96151d3SKa Ho NgThis ioctl takes no arguments. 197c96151d3SKa Ho Ng.El 198c96151d3SKa Ho Ng.Sh FILES 199c96151d3SKa Ho Ng.Bl -tag -width ".Pa /dev/sndstat" -compact 200c96151d3SKa Ho Ng.It Pa /dev/sndstat 201c96151d3SKa Ho Ng.El 202c96151d3SKa Ho Ng.Sh EXAMPLES 203c96151d3SKa Ho NgThe following code enumerates all available PCM audio devices: 204c96151d3SKa Ho Ng.Bd -literal -offset indent 205c96151d3SKa Ho Ng#include <sys/types.h> 206c96151d3SKa Ho Ng#include <err.h> 207c96151d3SKa Ho Ng#include <fcntl.h> 208c96151d3SKa Ho Ng#include <stdio.h> 209c96151d3SKa Ho Ng#include <stdlib.h> 210c96151d3SKa Ho Ng#include <sys/nv.h> 211c96151d3SKa Ho Ng#include <sys/sndstat.h> 212c96151d3SKa Ho Ng#include <sysexits.h> 213c96151d3SKa Ho Ng#include <unistd.h> 214c96151d3SKa Ho Ng 215c96151d3SKa Ho Ngint 216c96151d3SKa Ho Ngmain() 217c96151d3SKa Ho Ng{ 218c96151d3SKa Ho Ng int fd; 2194ce1ba65SKa Ho Ng struct sndstioc_nv_arg arg; 220c96151d3SKa Ho Ng const nvlist_t * const *di; 221c96151d3SKa Ho Ng size_t i, nitems; 222c96151d3SKa Ho Ng nvlist_t *nvl; 223c96151d3SKa Ho Ng 224c96151d3SKa Ho Ng /* Open sndstat node in read-only first */ 225c96151d3SKa Ho Ng fd = open("/dev/sndstat", O_RDONLY); 226c96151d3SKa Ho Ng 2274ce1ba65SKa Ho Ng if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)) 2284ce1ba65SKa Ho Ng err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)"); 229c96151d3SKa Ho Ng 230c96151d3SKa Ho Ng /* Get the size of snapshot, when nbytes = 0 */ 231c96151d3SKa Ho Ng arg.nbytes = 0; 232c96151d3SKa Ho Ng arg.buf = NULL; 2334ce1ba65SKa Ho Ng if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 2344ce1ba65SKa Ho Ng err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 235c96151d3SKa Ho Ng 236c96151d3SKa Ho Ng /* Get snapshot data */ 237c96151d3SKa Ho Ng arg.buf = malloc(arg.nbytes); 238c96151d3SKa Ho Ng if (arg.buf == NULL) 239c96151d3SKa Ho Ng err(EX_OSERR, "malloc"); 2404ce1ba65SKa Ho Ng if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg)) 2414ce1ba65SKa Ho Ng err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)"); 242c96151d3SKa Ho Ng 243c96151d3SKa Ho Ng /* Deserialize the nvlist stream */ 244c96151d3SKa Ho Ng nvl = nvlist_unpack(arg.buf, arg.nbytes, 0); 245c96151d3SKa Ho Ng free(arg.buf); 246c96151d3SKa Ho Ng 247c96151d3SKa Ho Ng /* Get DSPs array */ 2484ce1ba65SKa Ho Ng di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems); 249c96151d3SKa Ho Ng for (i = 0; i < nitems; i++) { 250c96151d3SKa Ho Ng const char *nameunit, *devnode, *desc; 251c96151d3SKa Ho Ng 252c96151d3SKa Ho Ng /* 253c96151d3SKa Ho Ng * Examine each device nvlist item 254c96151d3SKa Ho Ng */ 255c96151d3SKa Ho Ng 2564ce1ba65SKa Ho Ng nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT); 2574ce1ba65SKa Ho Ng devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE); 2584ce1ba65SKa Ho Ng desc = nvlist_get_string(di[i], SNDST_DSPS_DESC); 259c96151d3SKa Ho Ng printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n", 260c96151d3SKa Ho Ng nameunit, devnode, desc); 261c96151d3SKa Ho Ng } 262c96151d3SKa Ho Ng 263c96151d3SKa Ho Ng nvlist_destroy(nvl); 264c96151d3SKa Ho Ng return (0); 265c96151d3SKa Ho Ng} 266c96151d3SKa Ho Ng.Ed 267c96151d3SKa Ho Ng.Sh SEE ALSO 268c96151d3SKa Ho Ng.Xr sound 4 , 269c96151d3SKa Ho Ng.Xr nv 9 270c96151d3SKa Ho Ng.Sh HISTORY 271c96151d3SKa Ho NgThe nvlist-based ioctls support for 272c96151d3SKa Ho Ng.Nm 273c96151d3SKa Ho Ngdevice first appeared in 274c96151d3SKa Ho Ng.Fx 13.0 . 275c96151d3SKa Ho Ng.Sh AUTHORS 276c96151d3SKa Ho NgThis manual page was written by 277c96151d3SKa Ho Ng.An Ka Ho Ng Aq Mt khng@FreeBSD.org . 278