xref: /freebsd/share/man/man4/sndstat.4 (revision bbca3a75bb412f7106a569b82c616404103be084)
1c96151d3SKa Ho Ng.\"
24d846d26SWarner Losh.\" SPDX-License-Identifier: BSD-2-Clause
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.\" Note: The date here should be updated whenever a non-trivial
31c96151d3SKa Ho Ng.\" change is made to the manual page.
32*bbca3a75SChristos Margiolis.Dd June 5, 2024
33c96151d3SKa Ho Ng.Dt SNDSTAT 4
34c96151d3SKa Ho Ng.Os
35c96151d3SKa Ho Ng.Sh NAME
36c96151d3SKa Ho Ng.Nm sndstat
37c96151d3SKa Ho Ng.Nd "nvlist-based PCM audio device enumeration interface"
38c96151d3SKa Ho Ng.Sh SYNOPSIS
39c96151d3SKa Ho NgTo compile the driver into the kernel,
40c96151d3SKa Ho Ngplace the following lines in the
41c96151d3SKa Ho Ngkernel configuration file:
42c96151d3SKa Ho Ng.Bd -ragged -offset indent
43c96151d3SKa Ho Ng.Cd "device sound"
44c96151d3SKa Ho Ng.Ed
45c96151d3SKa Ho Ng.Sh DESCRIPTION
46c96151d3SKa Ho NgThe ioctl interface provided by
47c96151d3SKa Ho Ng.Pa /dev/sndstat
48c232fd4bSGoran Mekićdevice allows callers to enumerate PCM audio devices available for use.
49c232fd4bSGoran MekićIn other words, it provides means to get the list of all audio devices
50c232fd4bSGoran Mekićavailable to the system.
51c96151d3SKa Ho Ng.Sh IOCTLS
52c232fd4bSGoran MekićFor ioctl calls that take an argument, the following structure is used:
53c96151d3SKa Ho Ng.Bd -literal -offset indent
544ce1ba65SKa Ho Ngstruct sndstioc_nv_arg {
55c96151d3SKa Ho Ng	size_t nbytes;
56c96151d3SKa Ho Ng	void *buf;
57c96151d3SKa Ho Ng};
58c96151d3SKa Ho Ng.Ed
59c96151d3SKa Ho Ng.Pp
60c232fd4bSGoran MekićHere is an example of an nvlist object with explanations of the common fields:
61c96151d3SKa Ho Ng.Bd -literal -offset indent
62c96151d3SKa Ho Ngdsps (NVLIST ARRAY): 1
63c96151d3SKa Ho Ng	from_user (BOOL): FALSE
64c96151d3SKa Ho Ng	nameunit (STRING): [pcm0]
65c96151d3SKa Ho Ng	devnode (STRING): [dsp0]
66c96151d3SKa Ho Ng	desc (STRING): [Generic (0x8086) (Analog Line-out)]
67*bbca3a75SChristos Margiolis	pchan (NUMBER): 1
68*bbca3a75SChristos Margiolis	rchan (NUMBER): 0
694ce1ba65SKa Ho Ng	info_play (NVLIST):
70*bbca3a75SChristos Margiolis		min_rate (NUMBER): 48000
71*bbca3a75SChristos Margiolis		max_rate (NUMBER): 48000
72*bbca3a75SChristos Margiolis		formats (NUMBER): 16
73*bbca3a75SChristos Margiolis		min_chn (NUMBER): 2
74*bbca3a75SChristos Margiolis		max_chn (NUMBER): 2
75c96151d3SKa Ho Ng	provider_info (NVLIST):
76*bbca3a75SChristos Margiolis		unit (NUMBER): 0
77c96151d3SKa Ho Ng		bitperfect (BOOL): FALSE
78*bbca3a75SChristos Margiolis		pvchan (NUMBER): 1
79*bbca3a75SChristos Margiolis		rvchan (NUMBER): 0
80*bbca3a75SChristos Margiolis		channel_info (NVLIST_ARRAY): 1
81*bbca3a75SChristos Margiolis			name (STRING): pcm0:virtual_play:dsp0.vp0
82*bbca3a75SChristos Margiolis			parentchan (STRING): pcm0:play:dsp0.p0
83*bbca3a75SChristos Margiolis			unit (NUMBER): 1
84*bbca3a75SChristos Margiolis			latency (NUMBER): 2
85*bbca3a75SChristos Margiolis			rate (NUMBER): 48000
86*bbca3a75SChristos Margiolis			format (NUMBER): 0x201000
87*bbca3a75SChristos Margiolis			pid (NUMBER): 1234
88*bbca3a75SChristos Margiolis			comm (STRING): mpv
89*bbca3a75SChristos Margiolis			interrupts (NUMBER): 0
90*bbca3a75SChristos Margiolis			feedcount (NUMBER): 0
91*bbca3a75SChristos Margiolis			xruns (NUMBER): 0
92*bbca3a75SChristos Margiolis			left_volume (NUMBER): 45
93*bbca3a75SChristos Margiolis			right_volume (NUMBER): 45
94*bbca3a75SChristos Margiolis			hwbuf_fmt (NUMBER): 0x200010
95*bbca3a75SChristos Margiolis			hwbuf_size (NUMBER): 0
96*bbca3a75SChristos Margiolis			hwbuf_blksz (NUMBER): 0
97*bbca3a75SChristos Margiolis			hwbuf_blkcnt (NUMBER): 0
98*bbca3a75SChristos Margiolis			hwbuf_free (NUMBER): 0
99*bbca3a75SChristos Margiolis			hwbuf_ready (NUMBER): 0
100*bbca3a75SChristos Margiolis			swbuf_fmt (NUMBER): 0x201000
101*bbca3a75SChristos Margiolis			swbuf_size (NUMBER): 16384
102*bbca3a75SChristos Margiolis			swbuf_blksz (NUMBER): 2048
103*bbca3a75SChristos Margiolis			swbuf_blkcnt (NUMBER): 8
104*bbca3a75SChristos Margiolis			swbuf_free (NUMBER): 16384
105*bbca3a75SChristos Margiolis			swbuf_ready (NUMBER): 0
106*bbca3a75SChristos Margiolis			feederchain (STRING):
107*bbca3a75SChristos Margiolis				[userland ->
108*bbca3a75SChristos Margiolis				feeder_root(0x00201000) ->
109*bbca3a75SChristos Margiolis				feeder_format(0x00201000 -> 0x00200010) ->
110*bbca3a75SChristos Margiolis				feeder_volume(0x00200010) -> hardware]
111c96151d3SKa Ho Ng	provider (STRING): [sound(4)]
112c96151d3SKa Ho Ng.Ed
113c96151d3SKa Ho Ng.Bl -tag -width ".Dv provider_info"
114c96151d3SKa Ho Ng.It Dv from_user
115c96151d3SKa Ho NgWhether the PCM audio device node is created by in-kernel audio subsystem or
116c96151d3SKa Ho Nguserspace providers.
117c96151d3SKa Ho Ng.It Dv nameunit
118c96151d3SKa Ho NgThe device identification in the form of subsystem plus a unit number.
119c96151d3SKa Ho Ng.It Dv devnode
120c96151d3SKa Ho NgThe PCM audio device node relative path in devfs.
121c96151d3SKa Ho Ng.It Dv desc
122ffc4f93eSBenedict ReuschlingThe description of the PCM audio device.
123c96151d3SKa Ho Ng.It Dv pchan
124c96151d3SKa Ho NgThe number of playback channels supported by hardware.
125c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support playback at all.
126c96151d3SKa Ho Ng.It Dv rchan
127c96151d3SKa Ho NgThe number of recording channels supported by hardware.
128c96151d3SKa Ho NgThis can be 0 if this PCM audio device does not support recording at all.
1294ce1ba65SKa Ho Ng.It Dv info_play
1304ce1ba65SKa Ho NgSupported configurations in playback direction.
1314ce1ba65SKa Ho NgThis exists only if this PCM audio device supports playback.
1324ce1ba65SKa Ho NgThere are a number of name/value pairs inside this field:
1334ce1ba65SKa Ho Ng.Bl -tag -width ".Dv min_rate"
1344ce1ba65SKa Ho Ng.It Dv min_rate
1354ce1ba65SKa Ho NgMinimum supported sampling rate.
1364ce1ba65SKa Ho Ng.It Dv max_rate
1374ce1ba65SKa Ho NgMaximum supported sampling rate.
1384ce1ba65SKa Ho Ng.It Dv formats
1394ce1ba65SKa Ho NgSupported sample formats.
1404ce1ba65SKa Ho Ng.It Dv min_chn
1414ce1ba65SKa Ho NgMinimum supported number of channels in channel layout
1424ce1ba65SKa Ho Ng.It Dv max_chn
1434ce1ba65SKa Ho NgMaximum supported number of channels in channel layout
1444ce1ba65SKa Ho Ng.El
1454ce1ba65SKa Ho Ng.It Dv info_rec
1464ce1ba65SKa Ho NgSupported configurations in recording direction.
1474ce1ba65SKa Ho NgThis exists only if this PCM audio device supports recording.
1484ce1ba65SKa Ho NgThere are a number of name/value pairs inside this field:
1494ce1ba65SKa Ho Ng.Bl -tag -width ".Dv min_rate"
1504ce1ba65SKa Ho Ng.It Dv min_rate
1514ce1ba65SKa Ho NgMinimum supported sampling rate.
1524ce1ba65SKa Ho Ng.It Dv max_rate
1534ce1ba65SKa Ho NgMaximum supported sampling rate.
1544ce1ba65SKa Ho Ng.It Dv formats
1554ce1ba65SKa Ho NgSupported sample formats.
1564ce1ba65SKa Ho Ng.It Dv min_chn
1574ce1ba65SKa Ho NgMinimum supported number of channels in channel layout
1584ce1ba65SKa Ho Ng.It Dv max_chn
1594ce1ba65SKa Ho NgMaximum supported number of channels in channel layout
1604ce1ba65SKa Ho Ng.El
161c96151d3SKa Ho Ng.It Dv provider_info
162c96151d3SKa Ho NgProvider-specific fields.
163c96151d3SKa Ho NgThis field may not exist if the PCM audio device is not provided by in-kernel
164c96151d3SKa Ho Nginterface.
165c96151d3SKa Ho NgThis field will not exist if the provider field is an empty string.
166*bbca3a75SChristos MargiolisFor the
167*bbca3a75SChristos Margiolis.Xr sound 4
168*bbca3a75SChristos Margiolisprovider, there are a number of name/value pairs inside this field:
169*bbca3a75SChristos Margiolis.Bl -tag -width ".Dv channel_info"
170*bbca3a75SChristos Margiolis.It Dv unit
171*bbca3a75SChristos MargiolisSound card unit.
172*bbca3a75SChristos Margiolis.It Dv bitperfect
173*bbca3a75SChristos MargiolisWhether the sound card has bit-perfect mode enabled.
174*bbca3a75SChristos Margiolis.It Dv pvchan
175*bbca3a75SChristos MargiolisNumber of playback virtual channels.
176*bbca3a75SChristos Margiolis.It Dv rvchan
177*bbca3a75SChristos MargiolisNumber of recording virtual channels.
178*bbca3a75SChristos Margiolis.It Dv channel_info
179*bbca3a75SChristos MargiolisChannel information.
180*bbca3a75SChristos MargiolisThere are a number of name/value pairs inside this field:
181*bbca3a75SChristos Margiolis.Bl -tag -width ".Dv hwbuf_blkcnt"
182*bbca3a75SChristos Margiolis.It Dv name
183*bbca3a75SChristos MargiolisChannel name.
184*bbca3a75SChristos Margiolis.It Dv parenchan
185*bbca3a75SChristos MargiolisParent channel name (e.g., in the case of virtual channels).
186*bbca3a75SChristos Margiolis.It Dv unit
187*bbca3a75SChristos MargiolisChannel unit.
188*bbca3a75SChristos Margiolis.It Dv latency
189*bbca3a75SChristos MargiolisLatency.
190*bbca3a75SChristos Margiolis.It Dv rate
191*bbca3a75SChristos MargiolisSampling rate.
192*bbca3a75SChristos Margiolis.It Dv format
193*bbca3a75SChristos MargiolisSampling format.
194*bbca3a75SChristos Margiolis.It Dv pid
195*bbca3a75SChristos MargiolisPID of the process consuming the channel.
196*bbca3a75SChristos Margiolis.It Dv comm
197*bbca3a75SChristos MargiolisName of the process consuming the channel.
198*bbca3a75SChristos Margiolis.It Dv interrupts
199*bbca3a75SChristos MargiolisNumber of interrupts since the channel has been opened.
200*bbca3a75SChristos Margiolis.It Dv xruns
201*bbca3a75SChristos MargiolisNumber of overruns/underruns, depending on channel direction.
202*bbca3a75SChristos Margiolis.It Dv feedcount
203*bbca3a75SChristos MargiolisNumber of read/written bytes since the channel has been opened.
204*bbca3a75SChristos Margiolis.It Dv left_volume
205*bbca3a75SChristos MargiolisLeft volume.
206*bbca3a75SChristos Margiolis.It Dv right_volume
207*bbca3a75SChristos MargiolisRight volume.
208*bbca3a75SChristos Margiolis.It Dv hwbuf_format
209*bbca3a75SChristos MargiolisHardware buffer format.
210*bbca3a75SChristos Margiolis.It Dv hwbuf_size
211*bbca3a75SChristos MargiolisHardware buffer size.
212*bbca3a75SChristos Margiolis.It Dv hwbuf_blksz
213*bbca3a75SChristos MargiolisHardware buffer block size.
214*bbca3a75SChristos Margiolis.It Dv hwbuf_blkcnt
215*bbca3a75SChristos MargiolisHardware buffer block count.
216*bbca3a75SChristos Margiolis.It Dv hwbuf_free
217*bbca3a75SChristos MargiolisFree space in hardware buffer (in bytes).
218*bbca3a75SChristos Margiolis.It Dv hwbuf_ready
219*bbca3a75SChristos MargiolisNumber of bytes ready to be read/written from hardware buffer.
220*bbca3a75SChristos Margiolis.It Dv swbuf_format
221*bbca3a75SChristos MargiolisSoftware buffer format.
222*bbca3a75SChristos Margiolis.It Dv swbuf_size
223*bbca3a75SChristos MargiolisSoftware buffer size.
224*bbca3a75SChristos Margiolis.It Dv swbuf_blksz
225*bbca3a75SChristos MargiolisSoftware buffer block size.
226*bbca3a75SChristos Margiolis.It Dv swbuf_blkcnt
227*bbca3a75SChristos MargiolisSoftware buffer block count.
228*bbca3a75SChristos Margiolis.It Dv swbuf_free
229*bbca3a75SChristos MargiolisFree space in software buffer (in bytes).
230*bbca3a75SChristos Margiolis.It Dv swbuf_ready
231*bbca3a75SChristos MargiolisNumber of bytes ready to be read/written from software buffer.
232*bbca3a75SChristos Margiolis.It Dv feederchain
233*bbca3a75SChristos MargiolisChannel feeder chain.
234*bbca3a75SChristos Margiolis.El
235*bbca3a75SChristos Margiolis.El
236c96151d3SKa Ho Ng.It Dv provider
237c96151d3SKa Ho NgA string specifying the provider of the PCm audio device.
238c96151d3SKa Ho Ng.El
239c96151d3SKa Ho Ng.Pp
2404ce1ba65SKa Ho NgThe following ioctls are provided for use:
2414ce1ba65SKa Ho Ng.Bl -tag -width ".Dv SNDSTIOC_FLUSH_USER_DEVS"
2424ce1ba65SKa Ho Ng.It Dv SNDSTIOC_REFRESH_DEVS
243c96151d3SKa Ho NgDrop any previously fetched PCM audio devices list snapshots.
244c96151d3SKa Ho NgThis ioctl takes no arguments.
2454ce1ba65SKa Ho Ng.It Dv SNDSTIOC_GET_DEVS
246c96151d3SKa Ho NgGenerate and/or return PCM audio devices list snapshots to callers.
247c96151d3SKa Ho NgThis ioctl takes a pointer to
2484ce1ba65SKa Ho Ng.Fa struct sndstioc_nv_arg
249c96151d3SKa Ho Ngas the first and the only argument.
250c96151d3SKa Ho NgCallers need to provide a sufficiently large buffer to hold a serialized
251c96151d3SKa Ho Ngnvlist.
252c96151d3SKa Ho NgIf there is no existing PCM audio device list snapshot available in the
253c96151d3SKa Ho Nginternal structure of the opened sndstat.
254c96151d3SKa Ho Ng.Fa fd ,
255c96151d3SKa Ho Nga new PCM audio device list snapshot will be automatically generated.
256c96151d3SKa Ho NgCallers have to set
257c96151d3SKa Ho Ng.Fa nbytes
258c96151d3SKa Ho Ngto either 0 or the size of buffer provided.
259c96151d3SKa Ho NgIn case
260c96151d3SKa Ho Ng.Fa nbytes
261c96151d3SKa Ho Ngis 0, the buffer size required to hold a serialized nvlist
262c96151d3SKa Ho Ngstream of current snapshot will be returned in
263c96151d3SKa Ho Ng.Fa nbytes ,
264c96151d3SKa Ho Ngand
265c96151d3SKa Ho Ng.Fa buf
266c96151d3SKa Ho Ngwill be ignored.
267c96151d3SKa Ho NgOtherwise, if the buffer is not sufficiently large,
268c96151d3SKa Ho Ngthe ioctl returns success, and
269c96151d3SKa Ho Ng.Fa nbytes
270c96151d3SKa Ho Ngwill be set to 0.
271c96151d3SKa Ho NgIf the buffer provided is sufficiently large,
272c96151d3SKa Ho Ng.Fa nbytes
273c96151d3SKa Ho Ngwill be set to the size of the serialized nvlist written to the provided buffer.
274c96151d3SKa Ho NgOnce a PCM audio device list snapshot is returned to user-space successfully,
275c96151d3SKa Ho Ngthe snapshot stored in the subsystem's internal structure of the given
276c96151d3SKa Ho Ng.Fa fd
277c96151d3SKa Ho Ngwill be freed.
2784ce1ba65SKa Ho Ng.It Dv SNDSTIOC_ADD_USER_DEVS
279c96151d3SKa Ho NgAdd a list of PCM audio devices provided by callers to
280c96151d3SKa Ho Ng.Pa /dev/sndstat
281c96151d3SKa Ho Ngdevice.
282c96151d3SKa Ho NgThis ioctl takes a pointer to
2834ce1ba65SKa Ho Ng.Fa struct sndstioc_nv_arg
284c96151d3SKa Ho Ngas the first and the only argument.
285c96151d3SKa Ho NgCallers have to provide a buffer holding a serialized nvlist.
286c96151d3SKa Ho Ng.Fa nbytes
287c96151d3SKa Ho Ngshould be set to the length in bytes of the serialized nvlist.
288c96151d3SKa Ho Ng.Fa buf
289c96151d3SKa Ho Ngshould be pointed to a buffer storing the serialized nvlist.
290c96151d3SKa Ho NgUserspace-backed PCM audio device nodes should be listed inside the serialized
291c96151d3SKa Ho Ngnvlist.
2924ce1ba65SKa Ho Ng.It Dv SNDSTIOC_FLUSH_USER_DEVS
293c96151d3SKa Ho NgFlush any PCM audio devices previously added by callers.
294c96151d3SKa Ho NgThis ioctl takes no arguments.
295c96151d3SKa Ho Ng.El
296c96151d3SKa Ho Ng.Sh FILES
297c96151d3SKa Ho Ng.Bl -tag -width ".Pa /dev/sndstat" -compact
298c96151d3SKa Ho Ng.It Pa /dev/sndstat
299c96151d3SKa Ho Ng.El
300c96151d3SKa Ho Ng.Sh EXAMPLES
301c96151d3SKa Ho NgThe following code enumerates all available PCM audio devices:
302c96151d3SKa Ho Ng.Bd -literal -offset indent
303c96151d3SKa Ho Ng#include <sys/types.h>
304c96151d3SKa Ho Ng#include <err.h>
305c96151d3SKa Ho Ng#include <fcntl.h>
306c96151d3SKa Ho Ng#include <stdio.h>
307c96151d3SKa Ho Ng#include <stdlib.h>
308c96151d3SKa Ho Ng#include <sys/nv.h>
309c96151d3SKa Ho Ng#include <sys/sndstat.h>
310c96151d3SKa Ho Ng#include <sysexits.h>
311c96151d3SKa Ho Ng#include <unistd.h>
312c96151d3SKa Ho Ng
313c96151d3SKa Ho Ngint
314c96151d3SKa Ho Ngmain()
315c96151d3SKa Ho Ng{
316c96151d3SKa Ho Ng	int fd;
3174ce1ba65SKa Ho Ng	struct sndstioc_nv_arg arg;
318c96151d3SKa Ho Ng	const nvlist_t * const *di;
319c96151d3SKa Ho Ng	size_t i, nitems;
320c96151d3SKa Ho Ng	nvlist_t *nvl;
321c96151d3SKa Ho Ng
322c96151d3SKa Ho Ng	/* Open sndstat node in read-only first */
323c96151d3SKa Ho Ng	fd = open("/dev/sndstat", O_RDONLY);
324c96151d3SKa Ho Ng
3254ce1ba65SKa Ho Ng	if (ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL))
3264ce1ba65SKa Ho Ng		err(1, "ioctl(fd, SNDSTIOC_REFRESH_DEVS, NULL)");
327c96151d3SKa Ho Ng
328c96151d3SKa Ho Ng	/* Get the size of snapshot, when nbytes = 0 */
329c96151d3SKa Ho Ng	arg.nbytes = 0;
330c96151d3SKa Ho Ng	arg.buf = NULL;
3314ce1ba65SKa Ho Ng	if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg))
3324ce1ba65SKa Ho Ng		err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)");
333c96151d3SKa Ho Ng
334c96151d3SKa Ho Ng	/* Get snapshot data */
335c96151d3SKa Ho Ng	arg.buf = malloc(arg.nbytes);
336c96151d3SKa Ho Ng	if (arg.buf == NULL)
337c96151d3SKa Ho Ng		err(EX_OSERR, "malloc");
3384ce1ba65SKa Ho Ng	if (ioctl(fd, SNDSTIOC_GET_DEVS, &arg))
3394ce1ba65SKa Ho Ng		err(1, "ioctl(fd, SNDSTIOC_GET_DEVS, &arg)");
340c96151d3SKa Ho Ng
341c96151d3SKa Ho Ng	/* Deserialize the nvlist stream */
342c96151d3SKa Ho Ng	nvl = nvlist_unpack(arg.buf, arg.nbytes, 0);
343c96151d3SKa Ho Ng	free(arg.buf);
344c96151d3SKa Ho Ng
345c96151d3SKa Ho Ng	/* Get DSPs array */
3464ce1ba65SKa Ho Ng	di = nvlist_get_nvlist_array(nvl, SNDST_DSPS, &nitems);
347c96151d3SKa Ho Ng	for (i = 0; i < nitems; i++) {
348c96151d3SKa Ho Ng		const char *nameunit, *devnode, *desc;
349c96151d3SKa Ho Ng
350c96151d3SKa Ho Ng		/*
351c96151d3SKa Ho Ng		 * Examine each device nvlist item
352c96151d3SKa Ho Ng		 */
353c96151d3SKa Ho Ng
3544ce1ba65SKa Ho Ng		nameunit = nvlist_get_string(di[i], SNDST_DSPS_NAMEUNIT);
3554ce1ba65SKa Ho Ng		devnode = nvlist_get_string(di[i], SNDST_DSPS_DEVNODE);
3564ce1ba65SKa Ho Ng		desc = nvlist_get_string(di[i], SNDST_DSPS_DESC);
357c96151d3SKa Ho Ng		printf("Name unit: `%s`, Device node: `%s`, Description: `%s`\n",
358c96151d3SKa Ho Ng		    nameunit, devnode, desc);
359c96151d3SKa Ho Ng	}
360c96151d3SKa Ho Ng
361c96151d3SKa Ho Ng	nvlist_destroy(nvl);
362c96151d3SKa Ho Ng	return (0);
363c96151d3SKa Ho Ng}
364c96151d3SKa Ho Ng.Ed
365c96151d3SKa Ho Ng.Sh SEE ALSO
366c96151d3SKa Ho Ng.Xr sound 4 ,
367c96151d3SKa Ho Ng.Xr nv 9
368c96151d3SKa Ho Ng.Sh HISTORY
369c96151d3SKa Ho NgThe nvlist-based ioctls support for
370c96151d3SKa Ho Ng.Nm
371c96151d3SKa Ho Ngdevice first appeared in
372c96151d3SKa Ho Ng.Fx 13.0 .
373c96151d3SKa Ho Ng.Sh AUTHORS
374c96151d3SKa Ho NgThis manual page was written by
375c96151d3SKa Ho Ng.An Ka Ho Ng Aq Mt khng@FreeBSD.org .
376