1*c96151d3SKa Ho Ng.\" 2*c96151d3SKa Ho Ng.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*c96151d3SKa Ho Ng.\" 4*c96151d3SKa Ho Ng.\" This software was developed by Ka Ho Ng 5*c96151d3SKa Ho Ng.\" under sponsorship from the FreeBSD Foundation. 6*c96151d3SKa Ho Ng.\" 7*c96151d3SKa Ho Ng.\" Copyright (c) 2020 The FreeBSD Foundation 8*c96151d3SKa Ho Ng.\" 9*c96151d3SKa Ho Ng.\" Redistribution and use in source and binary forms, with or without 10*c96151d3SKa Ho Ng.\" modification, are permitted provided that the following conditions 11*c96151d3SKa Ho Ng.\" are met: 12*c96151d3SKa Ho Ng.\" 1. Redistributions of source code must retain the above copyright 13*c96151d3SKa Ho Ng.\" notice, this list of conditions and the following disclaimer. 14*c96151d3SKa Ho Ng.\" 2. Redistributions in binary form must reproduce the above copyright 15*c96151d3SKa Ho Ng.\" notice, this list of conditions and the following disclaimer in the 16*c96151d3SKa Ho Ng.\" documentation and/or other materials provided with the distribution. 17*c96151d3SKa Ho Ng.\" 18*c96151d3SKa Ho Ng.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19*c96151d3SKa Ho Ng.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*c96151d3SKa Ho Ng.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*c96151d3SKa Ho Ng.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22*c96151d3SKa Ho Ng.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*c96151d3SKa Ho Ng.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*c96151d3SKa Ho Ng.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*c96151d3SKa Ho Ng.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26*c96151d3SKa Ho Ng.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*c96151d3SKa Ho Ng.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*c96151d3SKa Ho Ng.\" SUCH DAMAGE. 29*c96151d3SKa Ho Ng.\" 30*c96151d3SKa Ho Ng.\" $FreeBSD$ 31*c96151d3SKa Ho Ng.\" 32*c96151d3SKa Ho Ng.\" Note: The date here should be updated whenever a non-trivial 33*c96151d3SKa Ho Ng.\" change is made to the manual page. 34*c96151d3SKa Ho Ng.Dd December 7, 2020 35*c96151d3SKa Ho Ng.Dt SNDSTAT 4 36*c96151d3SKa Ho Ng.Os 37*c96151d3SKa Ho Ng.Sh NAME 38*c96151d3SKa Ho Ng.Nm sndstat 39*c96151d3SKa Ho Ng.Nd "nvlist-based PCM audio device enumeration interface" 40*c96151d3SKa Ho Ng.Sh SYNOPSIS 41*c96151d3SKa Ho NgTo compile the driver into the kernel, 42*c96151d3SKa Ho Ngplace the following lines in the 43*c96151d3SKa Ho Ngkernel configuration file: 44*c96151d3SKa Ho Ng.Bd -ragged -offset indent 45*c96151d3SKa Ho Ng.Cd "device sound" 46*c96151d3SKa Ho Ng.Ed 47*c96151d3SKa Ho Ng.Sh DESCRIPTION 48*c96151d3SKa Ho NgThe ioctl interface provided by 49*c96151d3SKa Ho Ng.Pa /dev/sndstat 50*c96151d3SKa Ho Ngdevice allows callers to enumeration PCM audio devices available for use. 51*c96151d3SKa Ho Ng.Sh IOCTLS 52*c96151d3SKa Ho NgFor all ioctls requiring data exchange between the subsystem and callers, 53*c96151d3SKa Ho Ngthe following structures are used to describe a serialized nvlist: 54*c96151d3SKa Ho Ng.Bd -literal -offset indent 55*c96151d3SKa Ho Ngstruct sndstat_nvlbuf_arg { 56*c96151d3SKa Ho Ng size_t nbytes; 57*c96151d3SKa Ho Ng void *buf; 58*c96151d3SKa Ho Ng}; 59*c96151d3SKa Ho Ng.Ed 60*c96151d3SKa Ho Ng.Pp 61*c96151d3SKa Ho NgHere is an example of an nvlist, with explanations of the common fields: 62*c96151d3SKa Ho Ng.Bd -literal -offset indent 63*c96151d3SKa Ho Ngdsps (NVLIST ARRAY): 1 64*c96151d3SKa Ho Ng from_user (BOOL): FALSE 65*c96151d3SKa Ho Ng nameunit (STRING): [pcm0] 66*c96151d3SKa Ho Ng devnode (STRING): [dsp0] 67*c96151d3SKa Ho Ng desc (STRING): [Generic (0x8086) (Analog Line-out)] 68*c96151d3SKa Ho Ng pchan (NUMBER): 1 (1) (0x1) 69*c96151d3SKa Ho Ng rchan (NUMBER): 0 (0) (0x0) 70*c96151d3SKa Ho Ng pminrate (NUMBER): 48000 (48000) (0xbb80) 71*c96151d3SKa Ho Ng pmaxrate (NUMBER): 48000 (48000) (0xbb80) 72*c96151d3SKa Ho Ng pfmts (NUMBER): 2097168 (2097168) (0x200010) 73*c96151d3SKa Ho Ng provider_info (NVLIST): 74*c96151d3SKa Ho Ng unit (NUMBER): 0 (0) (0x0) 75*c96151d3SKa Ho Ng bitperfect (BOOL): FALSE 76*c96151d3SKa Ho Ng pvchan (NUMBER): 1 (1) (0x1) 77*c96151d3SKa Ho Ng rvchan (NUMBER): 0 (0) (0x0) 78*c96151d3SKa Ho Ng provider (STRING): [sound(4)] 79*c96151d3SKa Ho Ng , 80*c96151d3SKa Ho Ng.Ed 81*c96151d3SKa Ho Ng.Bl -tag -width ".Dv provider_info" 82*c96151d3SKa Ho Ng.It Dv from_user 83*c96151d3SKa Ho NgWhether the PCM audio device node is created by in-kernel audio subsystem or 84*c96151d3SKa Ho Nguserspace providers. 85*c96151d3SKa Ho Ng.It Dv nameunit 86*c96151d3SKa Ho NgThe device identification in the form of subsystem plus a unit number. 87*c96151d3SKa Ho Ng.It Dv devnode 88*c96151d3SKa Ho NgThe PCM audio device node relative path in devfs. 89*c96151d3SKa Ho Ng.It Dv desc 90*c96151d3SKa Ho NgThe descripton of the PCM audio device. 91*c96151d3SKa Ho Ng.It Dv pchan 92*c96151d3SKa Ho NgThe number of playback channels supported by hardware. 93*c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support playback at all. 94*c96151d3SKa Ho Ng.It Dv rchan 95*c96151d3SKa Ho NgThe number of recording channels supported by hardware. 96*c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support recording at all. 97*c96151d3SKa Ho Ng.It Dv pminrate 98*c96151d3SKa Ho NgThe minimum supported playback direction sampling rate. 99*c96151d3SKa Ho NgOnly exists if pchan is greater than 0. 100*c96151d3SKa Ho Ng.It Dv pmaxrate 101*c96151d3SKa Ho NgThe maximum supported playback direction sampling rate. 102*c96151d3SKa Ho NgOnly exists if pchan is greater than 0. 103*c96151d3SKa Ho Ng.It Dv pfmts 104*c96151d3SKa Ho NgThe supported playback direction sample format. 105*c96151d3SKa Ho NgOnly exists if pchan is greater than 0. 106*c96151d3SKa Ho Ng.It Dv rminrate 107*c96151d3SKa Ho NgThe minimum supported recording direction sampling rate. 108*c96151d3SKa Ho NgOnly exists if rchan is greater than 0. 109*c96151d3SKa Ho Ng.It Dv rmaxrate 110*c96151d3SKa Ho NgThe maximum supported recording direction sampling rate. 111*c96151d3SKa Ho NgOnly exists if rchan is greater than 0. 112*c96151d3SKa Ho Ng.It Dv rfmts 113*c96151d3SKa Ho NgThe supported playback recording sample format. 114*c96151d3SKa Ho NgOnly exists if rchan is greater than 0. 115*c96151d3SKa Ho Ng.It Dv provider_info 116*c96151d3SKa Ho NgProvider-specific fields. 117*c96151d3SKa Ho NgThis field may not exist if the PCM audio device is not provided by in-kernel 118*c96151d3SKa Ho Nginterface. 119*c96151d3SKa Ho NgThis field will not exist if the provider field is an empty string. 120*c96151d3SKa Ho Ng.It Dv provider 121*c96151d3SKa Ho NgA string specifying the provider of the PCm audio device. 122*c96151d3SKa Ho Ng.El 123*c96151d3SKa Ho Ng.Pp 124*c96151d3SKa Ho NgThe following ioctls are providede for use: 125*c96151d3SKa Ho Ng.Bl -tag -width ".Dv SNDSTAT_FLUSH_USER_DEVS" 126*c96151d3SKa Ho Ng.It Dv SNDSTAT_REFRESH_DEVS 127*c96151d3SKa Ho NgDrop any previously fetched PCM audio devices list snapshots. 128*c96151d3SKa Ho NgThis ioctl takes no arguments. 129*c96151d3SKa Ho Ng.It Dv SNDSTAT_GET_DEVS 130*c96151d3SKa Ho NgGenerate and/or return PCM audio devices list snapshots to callers. 131*c96151d3SKa Ho NgThis ioctl takes a pointer to 132*c96151d3SKa Ho Ng.Fa struct sndstat_nvlbuf_arg 133*c96151d3SKa Ho Ngas the first and the only argument. 134*c96151d3SKa Ho NgCallers need to provide a sufficiently large buffer to hold a serialized 135*c96151d3SKa Ho Ngnvlist. 136*c96151d3SKa Ho NgIf there is no existing PCM audio device list snapshot available in the 137*c96151d3SKa Ho Nginternal structure of the opened sndstat. 138*c96151d3SKa Ho Ng.Fa fd , 139*c96151d3SKa Ho Nga new PCM audio device list snapshot will be automatically generated. 140*c96151d3SKa Ho NgCallers have to set 141*c96151d3SKa Ho Ng.Fa nbytes 142*c96151d3SKa Ho Ngto either 0 or the size of buffer provided. 143*c96151d3SKa Ho NgIn case 144*c96151d3SKa Ho Ng.Fa nbytes 145*c96151d3SKa Ho Ngis 0, the buffer size required to hold a serialized nvlist 146*c96151d3SKa Ho Ngstream of current snapshot will be returned in 147*c96151d3SKa Ho Ng.Fa nbytes , 148*c96151d3SKa Ho Ngand 149*c96151d3SKa Ho Ng.Fa buf 150*c96151d3SKa Ho Ngwill be ignored. 151*c96151d3SKa Ho NgOtherwise, if the buffer is not sufficiently large, 152*c96151d3SKa Ho Ngthe ioctl returns success, and 153*c96151d3SKa Ho Ng.Fa nbytes 154*c96151d3SKa Ho Ngwill be set to 0. 155*c96151d3SKa Ho NgIf the buffer provided is sufficiently large, 156*c96151d3SKa Ho Ng.Fa nbytes 157*c96151d3SKa Ho Ngwill be set to the size of the serialized nvlist written to the provided buffer. 158*c96151d3SKa Ho NgOnce a PCM audio device list snapshot is returned to user-space successfully, 159*c96151d3SKa Ho Ngthe snapshot stored in the subsystem's internal structure of the given 160*c96151d3SKa Ho Ng.Fa fd 161*c96151d3SKa Ho Ngwill be freed. 162*c96151d3SKa Ho Ng.It Dv SNDSTAT_ADD_USER_DEVS 163*c96151d3SKa Ho NgAdd a list of PCM audio devices provided by callers to 164*c96151d3SKa Ho Ng.Pa /dev/sndstat 165*c96151d3SKa Ho Ngdevice. 166*c96151d3SKa Ho NgThis ioctl takes a pointer to 167*c96151d3SKa Ho Ng.Fa struct sndstat_nvlbuf_arg 168*c96151d3SKa Ho Ngas the first and the only argument. 169*c96151d3SKa Ho NgCallers have to provide a buffer holding a serialized nvlist. 170*c96151d3SKa Ho Ng.Fa nbytes 171*c96151d3SKa Ho Ngshould be set to the length in bytes of the serialized nvlist. 172*c96151d3SKa Ho Ng.Fa buf 173*c96151d3SKa Ho Ngshould be pointed to a buffer storing the serialized nvlist. 174*c96151d3SKa Ho NgUserspace-backed PCM audio device nodes should be listed inside the serialized 175*c96151d3SKa Ho Ngnvlist. 176*c96151d3SKa Ho Ng.It Dv SNDSTAT_FLUSH_USER_DEVS 177*c96151d3SKa Ho NgFlush any PCM audio devices previously added by callers. 178*c96151d3SKa Ho NgThis ioctl takes no arguments. 179*c96151d3SKa Ho Ng.El 180*c96151d3SKa Ho Ng.Sh FILES 181*c96151d3SKa Ho Ng.Bl -tag -width ".Pa /dev/sndstat" -compact 182*c96151d3SKa Ho Ng.It Pa /dev/sndstat 183*c96151d3SKa Ho Ng.El 184*c96151d3SKa Ho Ng.Sh EXAMPLES 185*c96151d3SKa Ho NgThe following code enumerates all available PCM audio devices: 186*c96151d3SKa Ho Ng.Bd -literal -offset indent 187*c96151d3SKa Ho Ng#include <sys/types.h> 188*c96151d3SKa Ho Ng#include <err.h> 189*c96151d3SKa Ho Ng#include <fcntl.h> 190*c96151d3SKa Ho Ng#include <stdio.h> 191*c96151d3SKa Ho Ng#include <stdlib.h> 192*c96151d3SKa Ho Ng#include <sys/nv.h> 193*c96151d3SKa Ho Ng#include <sys/sndstat.h> 194*c96151d3SKa Ho Ng#include <sysexits.h> 195*c96151d3SKa Ho Ng#include <unistd.h> 196*c96151d3SKa Ho Ng 197*c96151d3SKa Ho Ngint 198*c96151d3SKa Ho Ngmain() 199*c96151d3SKa Ho Ng{ 200*c96151d3SKa Ho Ng int fd; 201*c96151d3SKa Ho Ng struct sndstat_nvlbuf_arg arg; 202*c96151d3SKa Ho Ng const nvlist_t * const *di; 203*c96151d3SKa Ho Ng size_t i, nitems; 204*c96151d3SKa Ho Ng nvlist_t *nvl; 205*c96151d3SKa Ho Ng 206*c96151d3SKa Ho Ng /* Open sndstat node in read-only first */ 207*c96151d3SKa Ho Ng fd = open("/dev/sndstat", O_RDONLY); 208*c96151d3SKa Ho Ng 209*c96151d3SKa Ho Ng if (ioctl(fd, SNDSTAT_REFRESH_DEVS, NULL)) 210*c96151d3SKa Ho Ng err(1, "ioctl(fd, SNDSTAT_REFRESH_DEVS, NULL)"); 211*c96151d3SKa Ho Ng 212*c96151d3SKa Ho Ng /* Get the size of snapshot, when nbytes = 0 */ 213*c96151d3SKa Ho Ng arg.nbytes = 0; 214*c96151d3SKa Ho Ng arg.buf = NULL; 215*c96151d3SKa Ho Ng if (ioctl(fd, SNDSTAT_GET_DEVS, &arg)) 216*c96151d3SKa Ho Ng err(1, "ioctl(fd, SNDSTAT_GET_DEVS, &arg)"); 217*c96151d3SKa Ho Ng 218*c96151d3SKa Ho Ng /* Get snapshot data */ 219*c96151d3SKa Ho Ng arg.buf = malloc(arg.nbytes); 220*c96151d3SKa Ho Ng if (arg.buf == NULL) 221*c96151d3SKa Ho Ng err(EX_OSERR, "malloc"); 222*c96151d3SKa Ho Ng if (ioctl(fd, SNDSTAT_GET_DEVS, &arg)) 223*c96151d3SKa Ho Ng err(1, "ioctl(fd, SNDSTAT_GET_DEVS, &arg)"); 224*c96151d3SKa Ho Ng 225*c96151d3SKa Ho Ng /* Deserialize the nvlist stream */ 226*c96151d3SKa Ho Ng nvl = nvlist_unpack(arg.buf, arg.nbytes, 0); 227*c96151d3SKa Ho Ng free(arg.buf); 228*c96151d3SKa Ho Ng 229*c96151d3SKa Ho Ng /* Get DSPs array */ 230*c96151d3SKa Ho Ng di = nvlist_get_nvlist_array(nvl, SNDSTAT_LABEL_DSPS, &nitems); 231*c96151d3SKa Ho Ng for (i = 0; i < nitems; i++) { 232*c96151d3SKa Ho Ng const char *nameunit, *devnode, *desc; 233*c96151d3SKa Ho Ng 234*c96151d3SKa Ho Ng /* 235*c96151d3SKa Ho Ng * Examine each device nvlist item 236*c96151d3SKa Ho Ng */ 237*c96151d3SKa Ho Ng 238*c96151d3SKa Ho Ng nameunit = nvlist_get_string(di[i], SNDSTAT_LABEL_NAMEUNIT); 239*c96151d3SKa Ho Ng devnode = nvlist_get_string(di[i], SNDSTAT_LABEL_DEVNODE); 240*c96151d3SKa Ho Ng desc = nvlist_get_string(di[i], SNDSTAT_LABEL_DESC); 241*c96151d3SKa Ho Ng printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n", 242*c96151d3SKa Ho Ng nameunit, devnode, desc); 243*c96151d3SKa Ho Ng } 244*c96151d3SKa Ho Ng 245*c96151d3SKa Ho Ng nvlist_destroy(nvl); 246*c96151d3SKa Ho Ng return (0); 247*c96151d3SKa Ho Ng} 248*c96151d3SKa Ho Ng.Ed 249*c96151d3SKa Ho Ng.Sh SEE ALSO 250*c96151d3SKa Ho Ng.Xr sound 4 , 251*c96151d3SKa Ho Ng.Xr nv 9 252*c96151d3SKa Ho Ng.Sh HISTORY 253*c96151d3SKa Ho NgThe nvlist-based ioctls support for 254*c96151d3SKa Ho Ng.Nm 255*c96151d3SKa Ho Ngdevice first appeared in 256*c96151d3SKa Ho Ng.Fx 13.0 . 257*c96151d3SKa Ho Ng.Sh AUTHORS 258*c96151d3SKa Ho NgThis manual page was written by 259*c96151d3SKa Ho Ng.An Ka Ho Ng Aq Mt khng@FreeBSD.org . 260