Fri Oct 30 21:44:49 2020 UTC ()
ossaudio(3): Simplify setting rate (try to supply the nearest one possible)


(nia)
diff -r1.58 -r1.59 src/lib/libossaudio/ossaudio.c

cvs diff -r1.58 -r1.59 src/lib/libossaudio/Attic/ossaudio.c (switch to unified diff)

--- src/lib/libossaudio/Attic/ossaudio.c 2020/10/24 14:43:53 1.58
+++ src/lib/libossaudio/Attic/ossaudio.c 2020/10/30 21:44:49 1.59
@@ -1,1211 +1,1190 @@ @@ -1,1211 +1,1190 @@
1/* $NetBSD: ossaudio.c,v 1.58 2020/10/24 14:43:53 roy Exp $ */ 1/* $NetBSD: ossaudio.c,v 1.59 2020/10/30 21:44:49 nia Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__RCSID("$NetBSD: ossaudio.c,v 1.58 2020/10/24 14:43:53 roy Exp $"); 30__RCSID("$NetBSD: ossaudio.c,v 1.59 2020/10/30 21:44:49 nia Exp $");
31 31
32/* 32/*
33 * This is an Open Sound System compatibility layer, which provides 33 * This is an Open Sound System compatibility layer, which provides
34 * fairly complete ioctl emulation for OSSv3 and some of OSSv4. 34 * fairly complete ioctl emulation for OSSv3 and some of OSSv4.
35 * 35 *
36 * The canonical OSS specification is available at 36 * The canonical OSS specification is available at
37 * http://manuals.opensound.com/developer/ 37 * http://manuals.opensound.com/developer/
38 *  38 *
39 * This file is similar to sys/compat/ossaudio.c with additional OSSv4 39 * This file is similar to sys/compat/ossaudio.c with additional OSSv4
40 * compatibility. 40 * compatibility.
41 */ 41 */
42 42
43#include <string.h> 43#include <string.h>
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/ioctl.h> 45#include <sys/ioctl.h>
46#include <sys/audioio.h> 46#include <sys/audioio.h>
47#include <sys/stat.h> 47#include <sys/stat.h>
48#include <errno.h> 48#include <errno.h>
49#include <fcntl.h> 49#include <fcntl.h>
50#include <stdio.h> 50#include <stdio.h>
51#include <unistd.h> 51#include <unistd.h>
52#include <limits.h> 52#include <limits.h>
53#include <stdarg.h> 53#include <stdarg.h>
54#include <stdbool.h> 54#include <stdbool.h>
55 55
56#include "soundcard.h" 56#include "soundcard.h"
57#undef ioctl 57#undef ioctl
58 58
59#define GET_DEV(com) ((com) & 0xff) 59#define GET_DEV(com) ((com) & 0xff)
60 60
61#define TO_OSSVOL(x) (((x) * 100 + 127) / 255) 61#define TO_OSSVOL(x) (((x) * 100 + 127) / 255)
62#define FROM_OSSVOL(x) ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100) 62#define FROM_OSSVOL(x) ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100)
63 63
64#define GETPRINFO(info, name) \ 64#define GETPRINFO(info, name) \
65 (((info)->mode == AUMODE_RECORD) \ 65 (((info)->mode == AUMODE_RECORD) \
66 ? (info)->record.name : (info)->play.name) 66 ? (info)->record.name : (info)->play.name)
67 67
68static struct audiodevinfo *getdevinfo(int); 68static struct audiodevinfo *getdevinfo(int);
69 69
70static int getaudiocount(void); 70static int getaudiocount(void);
71static int getmixercount(void); 71static int getmixercount(void);
72static int getmixercontrolcount(int); 72static int getmixercontrolcount(int);
73 73
74static int getvol(u_int, u_char); 74static int getvol(u_int, u_char);
75static void setvol(int, int, bool); 75static void setvol(int, int, bool);
76 76
77static void setchannels(int, int, int); 77static void setchannels(int, int, int);
78static void setblocksize(int, struct audio_info *); 78static void setblocksize(int, struct audio_info *);
79 79
80static int audio_ioctl(int, unsigned long, void *); 80static int audio_ioctl(int, unsigned long, void *);
81static int mixer_oss3_ioctl(int, unsigned long, void *); 81static int mixer_oss3_ioctl(int, unsigned long, void *);
82static int mixer_oss4_ioctl(int, unsigned long, void *); 82static int mixer_oss4_ioctl(int, unsigned long, void *);
83static int global_oss4_ioctl(int, unsigned long, void *); 83static int global_oss4_ioctl(int, unsigned long, void *);
84static int opaque_to_enum(struct audiodevinfo *, audio_mixer_name_t *, int); 84static int opaque_to_enum(struct audiodevinfo *, audio_mixer_name_t *, int);
85static int enum_to_ord(struct audiodevinfo *, int); 85static int enum_to_ord(struct audiodevinfo *, int);
86static int enum_to_mask(struct audiodevinfo *, int); 86static int enum_to_mask(struct audiodevinfo *, int);
87 87
88#define INTARG (*(int*)argp) 88#define INTARG (*(int*)argp)
89 89
90int 90int
91_oss_ioctl(int fd, unsigned long com, ...) 91_oss_ioctl(int fd, unsigned long com, ...)
92{ 92{
93 va_list ap; 93 va_list ap;
94 void *argp; 94 void *argp;
95 95
96 va_start(ap, com); 96 va_start(ap, com);
97 argp = va_arg(ap, void *); 97 argp = va_arg(ap, void *);
98 va_end(ap); 98 va_end(ap);
99 99
100 if (IOCGROUP(com) == 'P') 100 if (IOCGROUP(com) == 'P')
101 return audio_ioctl(fd, com, argp); 101 return audio_ioctl(fd, com, argp);
102 else if (IOCGROUP(com) == 'M') 102 else if (IOCGROUP(com) == 'M')
103 return mixer_oss3_ioctl(fd, com, argp); 103 return mixer_oss3_ioctl(fd, com, argp);
104 else if (IOCGROUP(com) == 'X') 104 else if (IOCGROUP(com) == 'X')
105 return mixer_oss4_ioctl(fd, com, argp); 105 return mixer_oss4_ioctl(fd, com, argp);
106 else if (IOCGROUP(com) == 'Y') 106 else if (IOCGROUP(com) == 'Y')
107 return global_oss4_ioctl(fd, com, argp); 107 return global_oss4_ioctl(fd, com, argp);
108 else 108 else
109 return ioctl(fd, com, argp); 109 return ioctl(fd, com, argp);
110} 110}
111 111
112static int 112static int
113audio_ioctl(int fd, unsigned long com, void *argp) 113audio_ioctl(int fd, unsigned long com, void *argp)
114{ 114{
115 115
116 struct audio_info tmpinfo, hwfmt; 116 struct audio_info tmpinfo, hwfmt;
117 struct audio_offset tmpoffs; 117 struct audio_offset tmpoffs;
118 struct audio_buf_info bufinfo; 118 struct audio_buf_info bufinfo;
119 struct audio_errinfo *tmperrinfo; 119 struct audio_errinfo *tmperrinfo;
120 struct count_info cntinfo; 120 struct count_info cntinfo;
121 struct audio_encoding tmpenc; 121 struct audio_encoding tmpenc;
122 u_int u; 122 u_int u;
123 u_int encoding; 123 u_int encoding;
124 u_int precision; 124 u_int precision;
125 int perrors, rerrors; 125 int perrors, rerrors;
126 static int totalperrors = 0; 126 static int totalperrors = 0;
127 static int totalrerrors = 0; 127 static int totalrerrors = 0;
128 oss_count_t osscount; 128 oss_count_t osscount;
129 int idat, idata; 129 int idat, idata;
130 int retval; 130 int retval;
131 131
132 idat = 0; 132 idat = 0;
133 133
134 switch (com) { 134 switch (com) {
135 case SNDCTL_DSP_RESET: 135 case SNDCTL_DSP_RESET:
136 retval = ioctl(fd, AUDIO_FLUSH, 0); 136 retval = ioctl(fd, AUDIO_FLUSH, 0);
137 if (retval < 0) 137 if (retval < 0)
138 return retval; 138 return retval;
139 break; 139 break;
140 case SNDCTL_DSP_SYNC: 140 case SNDCTL_DSP_SYNC:
141 retval = ioctl(fd, AUDIO_DRAIN, 0); 141 retval = ioctl(fd, AUDIO_DRAIN, 0);
142 if (retval < 0) 142 if (retval < 0)
143 return retval; 143 return retval;
144 break; 144 break;
145 case SNDCTL_DSP_GETERROR: 145 case SNDCTL_DSP_GETERROR:
146 tmperrinfo = (struct audio_errinfo *)argp; 146 tmperrinfo = (struct audio_errinfo *)argp;
147 if (tmperrinfo == NULL) 147 if (tmperrinfo == NULL)
148 return EINVAL; 148 return EINVAL;
149 memset(tmperrinfo, 0, sizeof(struct audio_errinfo)); 149 memset(tmperrinfo, 0, sizeof(struct audio_errinfo));
150 if ((retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo)) < 0) 150 if ((retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo)) < 0)
151 return retval; 151 return retval;
152 /* 152 /*
153 * OSS requires that we return counters that are relative to 153 * OSS requires that we return counters that are relative to
154 * the last call. We must maintain state here... 154 * the last call. We must maintain state here...
155 */ 155 */
156 if (ioctl(fd, AUDIO_PERROR, &perrors) != -1) { 156 if (ioctl(fd, AUDIO_PERROR, &perrors) != -1) {
157 perrors /= ((tmpinfo.play.precision / NBBY) * 157 perrors /= ((tmpinfo.play.precision / NBBY) *
158 tmpinfo.play.channels); 158 tmpinfo.play.channels);
159 tmperrinfo->play_underruns = 159 tmperrinfo->play_underruns =
160 (perrors / tmpinfo.blocksize) - totalperrors; 160 (perrors / tmpinfo.blocksize) - totalperrors;
161 totalperrors += tmperrinfo->play_underruns; 161 totalperrors += tmperrinfo->play_underruns;
162 } 162 }
163 if (ioctl(fd, AUDIO_RERROR, &rerrors) != -1) { 163 if (ioctl(fd, AUDIO_RERROR, &rerrors) != -1) {
164 rerrors /= ((tmpinfo.record.precision / NBBY) * 164 rerrors /= ((tmpinfo.record.precision / NBBY) *
165 tmpinfo.record.channels); 165 tmpinfo.record.channels);
166 tmperrinfo->rec_overruns = 166 tmperrinfo->rec_overruns =
167 (rerrors / tmpinfo.blocksize) - totalrerrors; 167 (rerrors / tmpinfo.blocksize) - totalrerrors;
168 totalrerrors += tmperrinfo->rec_overruns; 168 totalrerrors += tmperrinfo->rec_overruns;
169 } 169 }
170 break; 170 break;
171 case SNDCTL_DSP_COOKEDMODE: 171 case SNDCTL_DSP_COOKEDMODE:
172 /* 172 /*
173 * NetBSD is always running in "cooked mode" - the kernel 173 * NetBSD is always running in "cooked mode" - the kernel
174 * always performs format conversions. 174 * always performs format conversions.
175 */ 175 */
176 INTARG = 1; 176 INTARG = 1;
177 break; 177 break;
178 case SNDCTL_DSP_POST: 178 case SNDCTL_DSP_POST:
179 /* This call is merely advisory, and may be a nop. */ 179 /* This call is merely advisory, and may be a nop. */
180 break; 180 break;
181 case SNDCTL_DSP_SPEED: 181 case SNDCTL_DSP_SPEED:
182 AUDIO_INITINFO(&tmpinfo); 182 AUDIO_INITINFO(&tmpinfo);
 183 /* Conform to kernel limits. */
 184 if (INTARG < 1000)
 185 INTARG = 1000;
 186 if (INTARG > 192000)
 187 INTARG = 192000;
183 tmpinfo.play.sample_rate = 188 tmpinfo.play.sample_rate =
184 tmpinfo.record.sample_rate = INTARG; 189 tmpinfo.record.sample_rate = INTARG;
185 /* 
186 * The default NetBSD behavior if an unsupported sample rate 
187 * is set is to return an error code and keep the rate at the 
188 * default of 8000 Hz. 
189 *  
190 * However, OSS specifies that a sample rate supported by the 
191 * hardware is returned if the exact rate could not be set. 
192 *  
193 * So, if the chosen sample rate is invalid, set and return 
194 * the current hardware rate. 
195 */ 
196 if (ioctl(fd, AUDIO_SETINFO, &tmpinfo) < 0) { 190 if (ioctl(fd, AUDIO_SETINFO, &tmpinfo) < 0) {
197 /* Don't care that SETINFO failed the first time... */ 191 return retval;
198 errno = 0; 
199 retval = ioctl(fd, AUDIO_GETFORMAT, &hwfmt); 
200 if (retval < 0) 
201 return retval; 
202 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); 
203 if (retval < 0) 
204 return retval; 
205 tmpinfo.play.sample_rate = 
206 tmpinfo.record.sample_rate = 
207 (tmpinfo.mode == AUMODE_RECORD) ? 
208 hwfmt.record.sample_rate : 
209 hwfmt.play.sample_rate; 
210 retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); 
211 if (retval < 0) 
212 return retval; 
213 } 192 }
214 /* FALLTHRU */ 193 /* FALLTHRU */
215 case SOUND_PCM_READ_RATE: 194 case SOUND_PCM_READ_RATE:
216 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 195 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
217 if (retval < 0) 196 if (retval < 0)
218 return retval; 197 return retval;
219 INTARG = GETPRINFO(&tmpinfo, sample_rate); 198 INTARG = GETPRINFO(&tmpinfo, sample_rate);
220 break; 199 break;
221 case SNDCTL_DSP_STEREO: 200 case SNDCTL_DSP_STEREO:
222 AUDIO_INITINFO(&tmpinfo); 201 AUDIO_INITINFO(&tmpinfo);
223 tmpinfo.play.channels = 202 tmpinfo.play.channels =
224 tmpinfo.record.channels = INTARG ? 2 : 1; 203 tmpinfo.record.channels = INTARG ? 2 : 1;
225 (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); 204 (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo);
226 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 205 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
227 if (retval < 0) 206 if (retval < 0)
228 return retval; 207 return retval;
229 INTARG = GETPRINFO(&tmpinfo, channels) - 1; 208 INTARG = GETPRINFO(&tmpinfo, channels) - 1;
230 break; 209 break;
231 case SNDCTL_DSP_GETBLKSIZE: 210 case SNDCTL_DSP_GETBLKSIZE:
232 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 211 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
233 if (retval < 0) 212 if (retval < 0)
234 return retval; 213 return retval;
235 setblocksize(fd, &tmpinfo); 214 setblocksize(fd, &tmpinfo);
236 INTARG = tmpinfo.blocksize; 215 INTARG = tmpinfo.blocksize;
237 break; 216 break;
238 case SNDCTL_DSP_SETFMT: 217 case SNDCTL_DSP_SETFMT:
239 AUDIO_INITINFO(&tmpinfo); 218 AUDIO_INITINFO(&tmpinfo);
240 switch (INTARG) { 219 switch (INTARG) {
241 case AFMT_MU_LAW: 220 case AFMT_MU_LAW:
242 tmpinfo.play.precision = 221 tmpinfo.play.precision =
243 tmpinfo.record.precision = 8; 222 tmpinfo.record.precision = 8;
244 tmpinfo.play.encoding = 223 tmpinfo.play.encoding =
245 tmpinfo.record.encoding = AUDIO_ENCODING_ULAW; 224 tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
246 break; 225 break;
247 case AFMT_A_LAW: 226 case AFMT_A_LAW:
248 tmpinfo.play.precision = 227 tmpinfo.play.precision =
249 tmpinfo.record.precision = 8; 228 tmpinfo.record.precision = 8;
250 tmpinfo.play.encoding = 229 tmpinfo.play.encoding =
251 tmpinfo.record.encoding = AUDIO_ENCODING_ALAW; 230 tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
252 break; 231 break;
253 case AFMT_U8: 232 case AFMT_U8:
254 tmpinfo.play.precision = 233 tmpinfo.play.precision =
255 tmpinfo.record.precision = 8; 234 tmpinfo.record.precision = 8;
256 tmpinfo.play.encoding = 235 tmpinfo.play.encoding =
257 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR; 236 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR;
258 break; 237 break;
259 case AFMT_S8: 238 case AFMT_S8:
260 tmpinfo.play.precision = 239 tmpinfo.play.precision =
261 tmpinfo.record.precision = 8; 240 tmpinfo.record.precision = 8;
262 tmpinfo.play.encoding = 241 tmpinfo.play.encoding =
263 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR; 242 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR;
264 break; 243 break;
265 case AFMT_S16_LE: 244 case AFMT_S16_LE:
266 tmpinfo.play.precision = 245 tmpinfo.play.precision =
267 tmpinfo.record.precision = 16; 246 tmpinfo.record.precision = 16;
268 tmpinfo.play.encoding = 247 tmpinfo.play.encoding =
269 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 248 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
270 break; 249 break;
271 case AFMT_S16_BE: 250 case AFMT_S16_BE:
272 tmpinfo.play.precision = 251 tmpinfo.play.precision =
273 tmpinfo.record.precision = 16; 252 tmpinfo.record.precision = 16;
274 tmpinfo.play.encoding = 253 tmpinfo.play.encoding =
275 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; 254 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
276 break; 255 break;
277 case AFMT_U16_LE: 256 case AFMT_U16_LE:
278 tmpinfo.play.precision = 257 tmpinfo.play.precision =
279 tmpinfo.record.precision = 16; 258 tmpinfo.record.precision = 16;
280 tmpinfo.play.encoding = 259 tmpinfo.play.encoding =
281 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE; 260 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE;
282 break; 261 break;
283 case AFMT_U16_BE: 262 case AFMT_U16_BE:
284 tmpinfo.play.precision = 263 tmpinfo.play.precision =
285 tmpinfo.record.precision = 16; 264 tmpinfo.record.precision = 16;
286 tmpinfo.play.encoding = 265 tmpinfo.play.encoding =
287 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE; 266 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
288 break; 267 break;
289 /* 268 /*
290 * XXX: When the kernel supports 24-bit LPCM by default, 269 * XXX: When the kernel supports 24-bit LPCM by default,
291 * the 24-bit formats should be handled properly instead 270 * the 24-bit formats should be handled properly instead
292 * of falling back to 32 bits. 271 * of falling back to 32 bits.
293 */ 272 */
294 case AFMT_S24_LE: 273 case AFMT_S24_LE:
295 case AFMT_S32_LE: 274 case AFMT_S32_LE:
296 tmpinfo.play.precision = 275 tmpinfo.play.precision =
297 tmpinfo.record.precision = 32; 276 tmpinfo.record.precision = 32;
298 tmpinfo.play.encoding = 277 tmpinfo.play.encoding =
299 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 278 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
300 break; 279 break;
301 case AFMT_S24_BE: 280 case AFMT_S24_BE:
302 case AFMT_S32_BE: 281 case AFMT_S32_BE:
303 tmpinfo.play.precision = 282 tmpinfo.play.precision =
304 tmpinfo.record.precision = 32; 283 tmpinfo.record.precision = 32;
305 tmpinfo.play.encoding = 284 tmpinfo.play.encoding =
306 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; 285 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
307 break; 286 break;
308 case AFMT_AC3: 287 case AFMT_AC3:
309 tmpinfo.play.precision = 288 tmpinfo.play.precision =
310 tmpinfo.record.precision = 16; 289 tmpinfo.record.precision = 16;
311 tmpinfo.play.encoding = 290 tmpinfo.play.encoding =
312 tmpinfo.record.encoding = AUDIO_ENCODING_AC3; 291 tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
313 break; 292 break;
314 default: 293 default:
315 /* 294 /*
316 * OSSv4 specifies that if an invalid format is chosen 295 * OSSv4 specifies that if an invalid format is chosen
317 * by an application then a sensible format supported 296 * by an application then a sensible format supported
318 * by the hardware is returned. 297 * by the hardware is returned.
319 * 298 *
320 * In this case, we pick the current hardware format. 299 * In this case, we pick the current hardware format.
321 */ 300 */
322 retval = ioctl(fd, AUDIO_GETFORMAT, &hwfmt); 301 retval = ioctl(fd, AUDIO_GETFORMAT, &hwfmt);
323 if (retval < 0) 302 if (retval < 0)
324 return retval; 303 return retval;
325 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); 304 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo);
326 if (retval < 0) 305 if (retval < 0)
327 return retval; 306 return retval;
328 tmpinfo.play.encoding = 307 tmpinfo.play.encoding =
329 tmpinfo.record.encoding = 308 tmpinfo.record.encoding =
330 (tmpinfo.mode == AUMODE_RECORD) ? 309 (tmpinfo.mode == AUMODE_RECORD) ?
331 hwfmt.record.encoding : hwfmt.play.encoding; 310 hwfmt.record.encoding : hwfmt.play.encoding;
332 tmpinfo.play.precision = 311 tmpinfo.play.precision =
333 tmpinfo.record.precision = 312 tmpinfo.record.precision =
334 (tmpinfo.mode == AUMODE_RECORD) ? 313 (tmpinfo.mode == AUMODE_RECORD) ?
335 hwfmt.record.precision : hwfmt.play.precision ; 314 hwfmt.record.precision : hwfmt.play.precision ;
336 break; 315 break;
337 } 316 }
338 /* 317 /*
339 * In the post-kernel-mixer world, assume that any error means 318 * In the post-kernel-mixer world, assume that any error means
340 * it's fatal rather than an unsupported format being selected. 319 * it's fatal rather than an unsupported format being selected.
341 */ 320 */
342 retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); 321 retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo);
343 if (retval < 0) 322 if (retval < 0)
344 return retval; 323 return retval;
345 /* FALLTHRU */ 324 /* FALLTHRU */
346 case SOUND_PCM_READ_BITS: 325 case SOUND_PCM_READ_BITS:
347 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 326 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
348 if (retval < 0) 327 if (retval < 0)
349 return retval; 328 return retval;
350 encoding = GETPRINFO(&tmpinfo, encoding); 329 encoding = GETPRINFO(&tmpinfo, encoding);
351 precision = GETPRINFO(&tmpinfo, precision); 330 precision = GETPRINFO(&tmpinfo, precision);
352 switch (encoding) { 331 switch (encoding) {
353 case AUDIO_ENCODING_ULAW: 332 case AUDIO_ENCODING_ULAW:
354 idat = AFMT_MU_LAW; 333 idat = AFMT_MU_LAW;
355 break; 334 break;
356 case AUDIO_ENCODING_ALAW: 335 case AUDIO_ENCODING_ALAW:
357 idat = AFMT_A_LAW; 336 idat = AFMT_A_LAW;
358 break; 337 break;
359 case AUDIO_ENCODING_SLINEAR_LE: 338 case AUDIO_ENCODING_SLINEAR_LE:
360 if (precision == 32) 339 if (precision == 32)
361 idat = AFMT_S32_LE; 340 idat = AFMT_S32_LE;
362 else if (precision == 24) 341 else if (precision == 24)
363 idat = AFMT_S24_LE; 342 idat = AFMT_S24_LE;
364 else if (precision == 16) 343 else if (precision == 16)
365 idat = AFMT_S16_LE; 344 idat = AFMT_S16_LE;
366 else 345 else
367 idat = AFMT_S8; 346 idat = AFMT_S8;
368 break; 347 break;
369 case AUDIO_ENCODING_SLINEAR_BE: 348 case AUDIO_ENCODING_SLINEAR_BE:
370 if (precision == 32) 349 if (precision == 32)
371 idat = AFMT_S32_BE; 350 idat = AFMT_S32_BE;
372 else if (precision == 24) 351 else if (precision == 24)
373 idat = AFMT_S24_BE; 352 idat = AFMT_S24_BE;
374 else if (precision == 16) 353 else if (precision == 16)
375 idat = AFMT_S16_BE; 354 idat = AFMT_S16_BE;
376 else 355 else
377 idat = AFMT_S8; 356 idat = AFMT_S8;
378 break; 357 break;
379 case AUDIO_ENCODING_ULINEAR_LE: 358 case AUDIO_ENCODING_ULINEAR_LE:
380 if (precision == 16) 359 if (precision == 16)
381 idat = AFMT_U16_LE; 360 idat = AFMT_U16_LE;
382 else 361 else
383 idat = AFMT_U8; 362 idat = AFMT_U8;
384 break; 363 break;
385 case AUDIO_ENCODING_ULINEAR_BE: 364 case AUDIO_ENCODING_ULINEAR_BE:
386 if (precision == 16) 365 if (precision == 16)
387 idat = AFMT_U16_BE; 366 idat = AFMT_U16_BE;
388 else 367 else
389 idat = AFMT_U8; 368 idat = AFMT_U8;
390 break; 369 break;
391 case AUDIO_ENCODING_ADPCM: 370 case AUDIO_ENCODING_ADPCM:
392 idat = AFMT_IMA_ADPCM; 371 idat = AFMT_IMA_ADPCM;
393 break; 372 break;
394 case AUDIO_ENCODING_AC3: 373 case AUDIO_ENCODING_AC3:
395 idat = AFMT_AC3; 374 idat = AFMT_AC3;
396 break; 375 break;
397 } 376 }
398 INTARG = idat; 377 INTARG = idat;
399 break; 378 break;
400 case SNDCTL_DSP_CHANNELS: 379 case SNDCTL_DSP_CHANNELS:
401 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 380 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
402 if (retval < 0) 381 if (retval < 0)
403 return retval; 382 return retval;
404 setchannels(fd, tmpinfo.mode, INTARG); 383 setchannels(fd, tmpinfo.mode, INTARG);
405 /* FALLTHRU */ 384 /* FALLTHRU */
406 case SOUND_PCM_READ_CHANNELS: 385 case SOUND_PCM_READ_CHANNELS:
407 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 386 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
408 if (retval < 0) 387 if (retval < 0)
409 return retval; 388 return retval;
410 INTARG = GETPRINFO(&tmpinfo, channels); 389 INTARG = GETPRINFO(&tmpinfo, channels);
411 break; 390 break;
412 case SOUND_PCM_WRITE_FILTER: 391 case SOUND_PCM_WRITE_FILTER:
413 case SOUND_PCM_READ_FILTER: 392 case SOUND_PCM_READ_FILTER:
414 errno = EINVAL; 393 errno = EINVAL;
415 return -1; /* XXX unimplemented */ 394 return -1; /* XXX unimplemented */
416 case SNDCTL_DSP_SUBDIVIDE: 395 case SNDCTL_DSP_SUBDIVIDE:
417 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 396 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
418 if (retval < 0) 397 if (retval < 0)
419 return retval; 398 return retval;
420 setblocksize(fd, &tmpinfo); 399 setblocksize(fd, &tmpinfo);
421 idat = INTARG; 400 idat = INTARG;
422 if (idat == 0) 401 if (idat == 0)
423 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize; 402 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
424 idat = (tmpinfo.play.buffer_size / idat) & -4; 403 idat = (tmpinfo.play.buffer_size / idat) & -4;
425 AUDIO_INITINFO(&tmpinfo); 404 AUDIO_INITINFO(&tmpinfo);
426 tmpinfo.blocksize = idat; 405 tmpinfo.blocksize = idat;
427 retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); 406 retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo);
428 if (retval < 0) 407 if (retval < 0)
429 return retval; 408 return retval;
430 INTARG = tmpinfo.play.buffer_size / tmpinfo.blocksize; 409 INTARG = tmpinfo.play.buffer_size / tmpinfo.blocksize;
431 break; 410 break;
432 case SNDCTL_DSP_SETFRAGMENT: 411 case SNDCTL_DSP_SETFRAGMENT:
433 AUDIO_INITINFO(&tmpinfo); 412 AUDIO_INITINFO(&tmpinfo);
434 idat = INTARG; 413 idat = INTARG;
435 if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) 414 if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17)
436 return EINVAL; 415 return EINVAL;
437 tmpinfo.blocksize = 1 << (idat & 0xffff); 416 tmpinfo.blocksize = 1 << (idat & 0xffff);
438 tmpinfo.hiwat = ((unsigned)idat >> 16) & 0x7fff; 417 tmpinfo.hiwat = ((unsigned)idat >> 16) & 0x7fff;
439 if (tmpinfo.hiwat == 0) /* 0 means set to max */ 418 if (tmpinfo.hiwat == 0) /* 0 means set to max */
440 tmpinfo.hiwat = 65536; 419 tmpinfo.hiwat = 65536;
441 (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); 420 (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo);
442 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 421 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
443 if (retval < 0) 422 if (retval < 0)
444 return retval; 423 return retval;
445 u = tmpinfo.blocksize; 424 u = tmpinfo.blocksize;
446 for(idat = 0; u > 1; idat++, u >>= 1) 425 for(idat = 0; u > 1; idat++, u >>= 1)
447 ; 426 ;
448 idat |= (tmpinfo.hiwat & 0x7fff) << 16; 427 idat |= (tmpinfo.hiwat & 0x7fff) << 16;
449 INTARG = idat; 428 INTARG = idat;
450 break; 429 break;
451 case SNDCTL_DSP_GETFMTS: 430 case SNDCTL_DSP_GETFMTS:
452 for(idat = 0, tmpenc.index = 0; 431 for(idat = 0, tmpenc.index = 0;
453 ioctl(fd, AUDIO_GETENC, &tmpenc) == 0; 432 ioctl(fd, AUDIO_GETENC, &tmpenc) == 0;
454 tmpenc.index++) { 433 tmpenc.index++) {
455 switch(tmpenc.encoding) { 434 switch(tmpenc.encoding) {
456 case AUDIO_ENCODING_ULAW: 435 case AUDIO_ENCODING_ULAW:
457 idat |= AFMT_MU_LAW; 436 idat |= AFMT_MU_LAW;
458 break; 437 break;
459 case AUDIO_ENCODING_ALAW: 438 case AUDIO_ENCODING_ALAW:
460 idat |= AFMT_A_LAW; 439 idat |= AFMT_A_LAW;
461 break; 440 break;
462 case AUDIO_ENCODING_SLINEAR: 441 case AUDIO_ENCODING_SLINEAR:
463 idat |= AFMT_S8; 442 idat |= AFMT_S8;
464 break; 443 break;
465 case AUDIO_ENCODING_SLINEAR_LE: 444 case AUDIO_ENCODING_SLINEAR_LE:
466 if (tmpenc.precision == 32) 445 if (tmpenc.precision == 32)
467 idat |= AFMT_S32_LE; 446 idat |= AFMT_S32_LE;
468 else if (tmpenc.precision == 24) 447 else if (tmpenc.precision == 24)
469 idat |= AFMT_S24_LE; 448 idat |= AFMT_S24_LE;
470 else if (tmpenc.precision == 16) 449 else if (tmpenc.precision == 16)
471 idat |= AFMT_S16_LE; 450 idat |= AFMT_S16_LE;
472 else 451 else
473 idat |= AFMT_S8; 452 idat |= AFMT_S8;
474 break; 453 break;
475 case AUDIO_ENCODING_SLINEAR_BE: 454 case AUDIO_ENCODING_SLINEAR_BE:
476 if (tmpenc.precision == 32) 455 if (tmpenc.precision == 32)
477 idat |= AFMT_S32_BE; 456 idat |= AFMT_S32_BE;
478 else if (tmpenc.precision == 24) 457 else if (tmpenc.precision == 24)
479 idat |= AFMT_S24_BE; 458 idat |= AFMT_S24_BE;
480 else if (tmpenc.precision == 16) 459 else if (tmpenc.precision == 16)
481 idat |= AFMT_S16_BE; 460 idat |= AFMT_S16_BE;
482 else 461 else
483 idat |= AFMT_S8; 462 idat |= AFMT_S8;
484 break; 463 break;
485 case AUDIO_ENCODING_ULINEAR: 464 case AUDIO_ENCODING_ULINEAR:
486 idat |= AFMT_U8; 465 idat |= AFMT_U8;
487 break; 466 break;
488 case AUDIO_ENCODING_ULINEAR_LE: 467 case AUDIO_ENCODING_ULINEAR_LE:
489 if (tmpenc.precision == 16) 468 if (tmpenc.precision == 16)
490 idat |= AFMT_U16_LE; 469 idat |= AFMT_U16_LE;
491 else 470 else
492 idat |= AFMT_U8; 471 idat |= AFMT_U8;
493 break; 472 break;
494 case AUDIO_ENCODING_ULINEAR_BE: 473 case AUDIO_ENCODING_ULINEAR_BE:
495 if (tmpenc.precision == 16) 474 if (tmpenc.precision == 16)
496 idat |= AFMT_U16_BE; 475 idat |= AFMT_U16_BE;
497 else 476 else
498 idat |= AFMT_U8; 477 idat |= AFMT_U8;
499 break; 478 break;
500 case AUDIO_ENCODING_ADPCM: 479 case AUDIO_ENCODING_ADPCM:
501 idat |= AFMT_IMA_ADPCM; 480 idat |= AFMT_IMA_ADPCM;
502 break; 481 break;
503 case AUDIO_ENCODING_AC3: 482 case AUDIO_ENCODING_AC3:
504 idat |= AFMT_AC3; 483 idat |= AFMT_AC3;
505 break; 484 break;
506 default: 485 default:
507 break; 486 break;
508 } 487 }
509 } 488 }
510 INTARG = idat; 489 INTARG = idat;
511 break; 490 break;
512 case SNDCTL_DSP_GETOSPACE: 491 case SNDCTL_DSP_GETOSPACE:
513 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 492 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
514 if (retval < 0) 493 if (retval < 0)
515 return retval; 494 return retval;
516 setblocksize(fd, &tmpinfo); 495 setblocksize(fd, &tmpinfo);
517 bufinfo.fragsize = tmpinfo.blocksize; 496 bufinfo.fragsize = tmpinfo.blocksize;
518 bufinfo.fragments = tmpinfo.hiwat - (tmpinfo.play.seek 497 bufinfo.fragments = tmpinfo.hiwat - (tmpinfo.play.seek
519 + tmpinfo.blocksize - 1) / tmpinfo.blocksize; 498 + tmpinfo.blocksize - 1) / tmpinfo.blocksize;
520 bufinfo.fragstotal = tmpinfo.hiwat; 499 bufinfo.fragstotal = tmpinfo.hiwat;
521 bufinfo.bytes = tmpinfo.hiwat * tmpinfo.blocksize 500 bufinfo.bytes = tmpinfo.hiwat * tmpinfo.blocksize
522 - tmpinfo.play.seek; 501 - tmpinfo.play.seek;
523 *(struct audio_buf_info *)argp = bufinfo; 502 *(struct audio_buf_info *)argp = bufinfo;
524 break; 503 break;
525 case SNDCTL_DSP_GETISPACE: 504 case SNDCTL_DSP_GETISPACE:
526 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 505 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
527 if (retval < 0) 506 if (retval < 0)
528 return retval; 507 return retval;
529 setblocksize(fd, &tmpinfo); 508 setblocksize(fd, &tmpinfo);
530 bufinfo.fragsize = tmpinfo.blocksize; 509 bufinfo.fragsize = tmpinfo.blocksize;
531 bufinfo.fragments = tmpinfo.record.seek / tmpinfo.blocksize; 510 bufinfo.fragments = tmpinfo.record.seek / tmpinfo.blocksize;
532 bufinfo.fragstotal = 511 bufinfo.fragstotal =
533 tmpinfo.record.buffer_size / tmpinfo.blocksize; 512 tmpinfo.record.buffer_size / tmpinfo.blocksize;
534 bufinfo.bytes = tmpinfo.record.seek; 513 bufinfo.bytes = tmpinfo.record.seek;
535 *(struct audio_buf_info *)argp = bufinfo; 514 *(struct audio_buf_info *)argp = bufinfo;
536 break; 515 break;
537 case SNDCTL_DSP_NONBLOCK: 516 case SNDCTL_DSP_NONBLOCK:
538 idat = 1; 517 idat = 1;
539 retval = ioctl(fd, FIONBIO, &idat); 518 retval = ioctl(fd, FIONBIO, &idat);
540 if (retval < 0) 519 if (retval < 0)
541 return retval; 520 return retval;
542 break; 521 break;
543 case SNDCTL_DSP_GETCAPS: 522 case SNDCTL_DSP_GETCAPS:
544 retval = ioctl(fd, AUDIO_GETPROPS, &idata); 523 retval = ioctl(fd, AUDIO_GETPROPS, &idata);
545 if (retval < 0) 524 if (retval < 0)
546 return retval; 525 return retval;
547 idat = DSP_CAP_TRIGGER; 526 idat = DSP_CAP_TRIGGER;
548 if (idata & AUDIO_PROP_FULLDUPLEX) 527 if (idata & AUDIO_PROP_FULLDUPLEX)
549 idat |= DSP_CAP_DUPLEX; 528 idat |= DSP_CAP_DUPLEX;
550 if (idata & AUDIO_PROP_MMAP) 529 if (idata & AUDIO_PROP_MMAP)
551 idat |= DSP_CAP_MMAP; 530 idat |= DSP_CAP_MMAP;
552 INTARG = idat; 531 INTARG = idat;
553 break; 532 break;
554 case SNDCTL_DSP_SETTRIGGER: 533 case SNDCTL_DSP_SETTRIGGER:
555 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 534 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
556 if (retval < 0) 535 if (retval < 0)
557 return retval; 536 return retval;
558 AUDIO_INITINFO(&tmpinfo); 537 AUDIO_INITINFO(&tmpinfo);
559 if (tmpinfo.mode & AUMODE_PLAY) 538 if (tmpinfo.mode & AUMODE_PLAY)
560 tmpinfo.play.pause = (INTARG & PCM_ENABLE_OUTPUT) == 0; 539 tmpinfo.play.pause = (INTARG & PCM_ENABLE_OUTPUT) == 0;
561 if (tmpinfo.mode & AUMODE_RECORD) 540 if (tmpinfo.mode & AUMODE_RECORD)
562 tmpinfo.record.pause = (INTARG & PCM_ENABLE_INPUT) == 0; 541 tmpinfo.record.pause = (INTARG & PCM_ENABLE_INPUT) == 0;
563 (void)ioctl(fd, AUDIO_SETINFO, &tmpinfo); 542 (void)ioctl(fd, AUDIO_SETINFO, &tmpinfo);
564 /* FALLTHRU */ 543 /* FALLTHRU */
565 case SNDCTL_DSP_GETTRIGGER: 544 case SNDCTL_DSP_GETTRIGGER:
566 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 545 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
567 if (retval < 0) 546 if (retval < 0)
568 return retval; 547 return retval;
569 idat = 0; 548 idat = 0;
570 if ((tmpinfo.mode & AUMODE_PLAY) && !tmpinfo.play.pause) 549 if ((tmpinfo.mode & AUMODE_PLAY) && !tmpinfo.play.pause)
571 idat |= PCM_ENABLE_OUTPUT; 550 idat |= PCM_ENABLE_OUTPUT;
572 if ((tmpinfo.mode & AUMODE_RECORD) && !tmpinfo.record.pause) 551 if ((tmpinfo.mode & AUMODE_RECORD) && !tmpinfo.record.pause)
573 idat |= PCM_ENABLE_INPUT; 552 idat |= PCM_ENABLE_INPUT;
574 INTARG = idat; 553 INTARG = idat;
575 break; 554 break;
576 case SNDCTL_DSP_GETIPTR: 555 case SNDCTL_DSP_GETIPTR:
577 retval = ioctl(fd, AUDIO_GETIOFFS, &tmpoffs); 556 retval = ioctl(fd, AUDIO_GETIOFFS, &tmpoffs);
578 if (retval < 0) 557 if (retval < 0)
579 return retval; 558 return retval;
580 cntinfo.bytes = tmpoffs.samples; 559 cntinfo.bytes = tmpoffs.samples;
581 cntinfo.blocks = tmpoffs.deltablks; 560 cntinfo.blocks = tmpoffs.deltablks;
582 cntinfo.ptr = tmpoffs.offset; 561 cntinfo.ptr = tmpoffs.offset;
583 *(struct count_info *)argp = cntinfo; 562 *(struct count_info *)argp = cntinfo;
584 break; 563 break;
585 case SNDCTL_DSP_CURRENT_IPTR: 564 case SNDCTL_DSP_CURRENT_IPTR:
586 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 565 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
587 if (retval < 0) 566 if (retval < 0)
588 return retval; 567 return retval;
589 /* XXX: 'samples' may wrap */ 568 /* XXX: 'samples' may wrap */
590 memset(osscount.filler, 0, sizeof(osscount.filler)); 569 memset(osscount.filler, 0, sizeof(osscount.filler));
591 osscount.samples = tmpinfo.record.samples / 570 osscount.samples = tmpinfo.record.samples /
592 ((tmpinfo.record.precision / NBBY) * 571 ((tmpinfo.record.precision / NBBY) *
593 tmpinfo.record.channels); 572 tmpinfo.record.channels);
594 osscount.fifo_samples = tmpinfo.record.seek / 573 osscount.fifo_samples = tmpinfo.record.seek /
595 ((tmpinfo.record.precision / NBBY) * 574 ((tmpinfo.record.precision / NBBY) *
596 tmpinfo.record.channels); 575 tmpinfo.record.channels);
597 *(oss_count_t *)argp = osscount; 576 *(oss_count_t *)argp = osscount;
598 break; 577 break;
599 case SNDCTL_DSP_GETOPTR: 578 case SNDCTL_DSP_GETOPTR:
600 retval = ioctl(fd, AUDIO_GETOOFFS, &tmpoffs); 579 retval = ioctl(fd, AUDIO_GETOOFFS, &tmpoffs);
601 if (retval < 0) 580 if (retval < 0)
602 return retval; 581 return retval;
603 cntinfo.bytes = tmpoffs.samples; 582 cntinfo.bytes = tmpoffs.samples;
604 cntinfo.blocks = tmpoffs.deltablks; 583 cntinfo.blocks = tmpoffs.deltablks;
605 cntinfo.ptr = tmpoffs.offset; 584 cntinfo.ptr = tmpoffs.offset;
606 *(struct count_info *)argp = cntinfo; 585 *(struct count_info *)argp = cntinfo;
607 break; 586 break;
608 case SNDCTL_DSP_CURRENT_OPTR: 587 case SNDCTL_DSP_CURRENT_OPTR:
609 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 588 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
610 if (retval < 0) 589 if (retval < 0)
611 return retval; 590 return retval;
612 /* XXX: 'samples' may wrap */ 591 /* XXX: 'samples' may wrap */
613 memset(osscount.filler, 0, sizeof(osscount.filler)); 592 memset(osscount.filler, 0, sizeof(osscount.filler));
614 osscount.samples = tmpinfo.play.samples / 593 osscount.samples = tmpinfo.play.samples /
615 ((tmpinfo.play.precision / NBBY) * 594 ((tmpinfo.play.precision / NBBY) *
616 tmpinfo.play.channels); 595 tmpinfo.play.channels);
617 osscount.fifo_samples = tmpinfo.play.seek / 596 osscount.fifo_samples = tmpinfo.play.seek /
618 ((tmpinfo.play.precision / NBBY) * 597 ((tmpinfo.play.precision / NBBY) *
619 tmpinfo.play.channels); 598 tmpinfo.play.channels);
620 *(oss_count_t *)argp = osscount; 599 *(oss_count_t *)argp = osscount;
621 break; 600 break;
622 case SNDCTL_DSP_SETPLAYVOL: 601 case SNDCTL_DSP_SETPLAYVOL:
623 setvol(fd, INTARG, false); 602 setvol(fd, INTARG, false);
624 /* FALLTHRU */ 603 /* FALLTHRU */
625 case SNDCTL_DSP_GETPLAYVOL: 604 case SNDCTL_DSP_GETPLAYVOL:
626 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); 605 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo);
627 if (retval < 0) 606 if (retval < 0)
628 return retval; 607 return retval;
629 INTARG = getvol(tmpinfo.play.gain, tmpinfo.play.balance); 608 INTARG = getvol(tmpinfo.play.gain, tmpinfo.play.balance);
630 break; 609 break;
631 case SNDCTL_DSP_SETRECVOL: 610 case SNDCTL_DSP_SETRECVOL:
632 setvol(fd, INTARG, true); 611 setvol(fd, INTARG, true);
633 /* FALLTHRU */ 612 /* FALLTHRU */
634 case SNDCTL_DSP_GETRECVOL: 613 case SNDCTL_DSP_GETRECVOL:
635 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); 614 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo);
636 if (retval < 0) 615 if (retval < 0)
637 return retval; 616 return retval;
638 INTARG = getvol(tmpinfo.record.gain, tmpinfo.record.balance); 617 INTARG = getvol(tmpinfo.record.gain, tmpinfo.record.balance);
639 break; 618 break;
640 case SNDCTL_DSP_SKIP: 619 case SNDCTL_DSP_SKIP:
641 case SNDCTL_DSP_SILENCE: 620 case SNDCTL_DSP_SILENCE:
642 return EINVAL; 621 return EINVAL;
643 case SNDCTL_DSP_SETDUPLEX: 622 case SNDCTL_DSP_SETDUPLEX:
644 idat = 1; 623 idat = 1;
645 retval = ioctl(fd, AUDIO_SETFD, &idat); 624 retval = ioctl(fd, AUDIO_SETFD, &idat);
646 if (retval < 0) 625 if (retval < 0)
647 return retval; 626 return retval;
648 break; 627 break;
649 case SNDCTL_DSP_GETODELAY: 628 case SNDCTL_DSP_GETODELAY:
650 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 629 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
651 if (retval < 0) 630 if (retval < 0)
652 return retval; 631 return retval;
653 idat = tmpinfo.play.seek + tmpinfo.blocksize / 2; 632 idat = tmpinfo.play.seek + tmpinfo.blocksize / 2;
654 INTARG = idat; 633 INTARG = idat;
655 break; 634 break;
656 case SNDCTL_DSP_PROFILE: 635 case SNDCTL_DSP_PROFILE:
657 /* This gives just a hint to the driver, 636 /* This gives just a hint to the driver,
658 * implementing it as a NOP is ok 637 * implementing it as a NOP is ok
659 */  638 */
660 break; 639 break;
661 case SNDCTL_DSP_MAPINBUF: 640 case SNDCTL_DSP_MAPINBUF:
662 case SNDCTL_DSP_MAPOUTBUF: 641 case SNDCTL_DSP_MAPOUTBUF:
663 case SNDCTL_DSP_SETSYNCRO: 642 case SNDCTL_DSP_SETSYNCRO:
664 errno = EINVAL; 643 errno = EINVAL;
665 return -1; /* XXX unimplemented */ 644 return -1; /* XXX unimplemented */
666 default: 645 default:
667 errno = EINVAL; 646 errno = EINVAL;
668 return -1; 647 return -1;
669 } 648 }
670 649
671 return 0; 650 return 0;
672} 651}
673 652
674 653
675/* If the NetBSD mixer device should have more than NETBSD_MAXDEVS devices 654/* If the NetBSD mixer device should have more than NETBSD_MAXDEVS devices
676 * some will not be available to OSS applications */ 655 * some will not be available to OSS applications */
677#define NETBSD_MAXDEVS 64 656#define NETBSD_MAXDEVS 64
678struct audiodevinfo { 657struct audiodevinfo {
679 int done; 658 int done;
680 dev_t dev; 659 dev_t dev;
681 int16_t devmap[SOUND_MIXER_NRDEVICES], 660 int16_t devmap[SOUND_MIXER_NRDEVICES],
682 rdevmap[NETBSD_MAXDEVS]; 661 rdevmap[NETBSD_MAXDEVS];
683 char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN]; 662 char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN];
684 int enum2opaque[NETBSD_MAXDEVS]; 663 int enum2opaque[NETBSD_MAXDEVS];
685 u_long devmask, recmask, stereomask; 664 u_long devmask, recmask, stereomask;
686 u_long caps; 665 u_long caps;
687 int source; 666 int source;
688}; 667};
689 668
690static int 669static int
691opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq) 670opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq)
692{ 671{
693 int i, o; 672 int i, o;
694 673
695 for (i = 0; i < NETBSD_MAXDEVS; i++) { 674 for (i = 0; i < NETBSD_MAXDEVS; i++) {
696 o = di->enum2opaque[i]; 675 o = di->enum2opaque[i];
697 if (o == opq) 676 if (o == opq)
698 break; 677 break;
699 if (o == -1 && label != NULL && 678 if (o == -1 && label != NULL &&
700 !strncmp(di->names[i], label->name, sizeof di->names[i])) { 679 !strncmp(di->names[i], label->name, sizeof di->names[i])) {
701 di->enum2opaque[i] = opq; 680 di->enum2opaque[i] = opq;
702 break; 681 break;
703 } 682 }
704 } 683 }
705 if (i >= NETBSD_MAXDEVS) 684 if (i >= NETBSD_MAXDEVS)
706 i = -1; 685 i = -1;
707 /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/ 686 /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/
708 return (i); 687 return (i);
709} 688}
710 689
711static int 690static int
712enum_to_ord(struct audiodevinfo *di, int enm) 691enum_to_ord(struct audiodevinfo *di, int enm)
713{ 692{
714 if (enm >= NETBSD_MAXDEVS) 693 if (enm >= NETBSD_MAXDEVS)
715 return (-1); 694 return (-1);
716 695
717 /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/ 696 /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/
718 return (di->enum2opaque[enm]); 697 return (di->enum2opaque[enm]);
719} 698}
720 699
721static int 700static int
722enum_to_mask(struct audiodevinfo *di, int enm) 701enum_to_mask(struct audiodevinfo *di, int enm)
723{ 702{
724 int m; 703 int m;
725 if (enm >= NETBSD_MAXDEVS) 704 if (enm >= NETBSD_MAXDEVS)
726 return (0); 705 return (0);
727 706
728 m = di->enum2opaque[enm]; 707 m = di->enum2opaque[enm];
729 if (m == -1) 708 if (m == -1)
730 m = 0; 709 m = 0;
731 /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/ 710 /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/
732 return (m); 711 return (m);
733} 712}
734 713
735/* 714/*
736 * Collect the audio device information to allow faster 715 * Collect the audio device information to allow faster
737 * emulation of the OSSv3 mixer ioctls. Cache the information 716 * emulation of the OSSv3 mixer ioctls. Cache the information
738 * to eliminate the overhead of repeating all the ioctls needed 717 * to eliminate the overhead of repeating all the ioctls needed
739 * to collect the information. 718 * to collect the information.
740 */ 719 */
741static struct audiodevinfo * 720static struct audiodevinfo *
742getdevinfo(int fd) 721getdevinfo(int fd)
743{ 722{
744 mixer_devinfo_t mi; 723 mixer_devinfo_t mi;
745 int i, j, e; 724 int i, j, e;
746 static struct { 725 static struct {
747 const char *name; 726 const char *name;
748 int code; 727 int code;
749 } *dp, devs[] = { 728 } *dp, devs[] = {
750 { AudioNmicrophone, SOUND_MIXER_MIC }, 729 { AudioNmicrophone, SOUND_MIXER_MIC },
751 { AudioNline, SOUND_MIXER_LINE }, 730 { AudioNline, SOUND_MIXER_LINE },
752 { AudioNcd, SOUND_MIXER_CD }, 731 { AudioNcd, SOUND_MIXER_CD },
753 { AudioNdac, SOUND_MIXER_PCM }, 732 { AudioNdac, SOUND_MIXER_PCM },
754 { AudioNaux, SOUND_MIXER_LINE1 }, 733 { AudioNaux, SOUND_MIXER_LINE1 },
755 { AudioNrecord, SOUND_MIXER_IMIX }, 734 { AudioNrecord, SOUND_MIXER_IMIX },
756 { AudioNmaster, SOUND_MIXER_VOLUME }, 735 { AudioNmaster, SOUND_MIXER_VOLUME },
757 { AudioNtreble, SOUND_MIXER_TREBLE }, 736 { AudioNtreble, SOUND_MIXER_TREBLE },
758 { AudioNbass, SOUND_MIXER_BASS }, 737 { AudioNbass, SOUND_MIXER_BASS },
759 { AudioNspeaker, SOUND_MIXER_SPEAKER }, 738 { AudioNspeaker, SOUND_MIXER_SPEAKER },
760/* { AudioNheadphone, ?? },*/ 739/* { AudioNheadphone, ?? },*/
761 { AudioNoutput, SOUND_MIXER_OGAIN }, 740 { AudioNoutput, SOUND_MIXER_OGAIN },
762 { AudioNinput, SOUND_MIXER_IGAIN }, 741 { AudioNinput, SOUND_MIXER_IGAIN },
763/* { AudioNmaster, SOUND_MIXER_SPEAKER },*/ 742/* { AudioNmaster, SOUND_MIXER_SPEAKER },*/
764/* { AudioNstereo, ?? },*/ 743/* { AudioNstereo, ?? },*/
765/* { AudioNmono, ?? },*/ 744/* { AudioNmono, ?? },*/
766 { AudioNfmsynth, SOUND_MIXER_SYNTH }, 745 { AudioNfmsynth, SOUND_MIXER_SYNTH },
767/* { AudioNwave, SOUND_MIXER_PCM },*/ 746/* { AudioNwave, SOUND_MIXER_PCM },*/
768 { AudioNmidi, SOUND_MIXER_SYNTH }, 747 { AudioNmidi, SOUND_MIXER_SYNTH },
769/* { AudioNmixerout, ?? },*/ 748/* { AudioNmixerout, ?? },*/
770 { 0, -1 } 749 { 0, -1 }
771 }; 750 };
772 static struct audiodevinfo devcache = { .done = 0 }; 751 static struct audiodevinfo devcache = { .done = 0 };
773 struct audiodevinfo *di = &devcache; 752 struct audiodevinfo *di = &devcache;
774 struct stat sb; 753 struct stat sb;
775 size_t mlen, dlen; 754 size_t mlen, dlen;
776 755
777 /* Figure out what device it is so we can check if the 756 /* Figure out what device it is so we can check if the
778 * cached data is valid. 757 * cached data is valid.
779 */ 758 */
780 if (fstat(fd, &sb) < 0) 759 if (fstat(fd, &sb) < 0)
781 return 0; 760 return 0;
782 if (di->done && di->dev == sb.st_dev) 761 if (di->done && di->dev == sb.st_dev)
783 return di; 762 return di;
784 763
785 di->done = 1; 764 di->done = 1;
786 di->dev = sb.st_dev; 765 di->dev = sb.st_dev;
787 di->devmask = 0; 766 di->devmask = 0;
788 di->recmask = 0; 767 di->recmask = 0;
789 di->stereomask = 0; 768 di->stereomask = 0;
790 di->source = ~0; 769 di->source = ~0;
791 di->caps = 0; 770 di->caps = 0;
792 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) 771 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++)
793 di->devmap[i] = -1; 772 di->devmap[i] = -1;
794 for(i = 0; i < NETBSD_MAXDEVS; i++) { 773 for(i = 0; i < NETBSD_MAXDEVS; i++) {
795 di->rdevmap[i] = -1; 774 di->rdevmap[i] = -1;
796 di->names[i][0] = '\0'; 775 di->names[i][0] = '\0';
797 di->enum2opaque[i] = -1; 776 di->enum2opaque[i] = -1;
798 } 777 }
799 for(i = 0; i < NETBSD_MAXDEVS; i++) { 778 for(i = 0; i < NETBSD_MAXDEVS; i++) {
800 mi.index = i; 779 mi.index = i;
801 if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0) 780 if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0)
802 break; 781 break;
803 switch(mi.type) { 782 switch(mi.type) {
804 case AUDIO_MIXER_VALUE: 783 case AUDIO_MIXER_VALUE:
805 for(dp = devs; dp->name; dp++) { 784 for(dp = devs; dp->name; dp++) {
806 if (strcmp(dp->name, mi.label.name) == 0) 785 if (strcmp(dp->name, mi.label.name) == 0)
807 break; 786 break;
808 dlen = strlen(dp->name); 787 dlen = strlen(dp->name);
809 mlen = strlen(mi.label.name); 788 mlen = strlen(mi.label.name);
810 if (dlen < mlen 789 if (dlen < mlen
811 && mi.label.name[mlen-dlen-1] == '.' 790 && mi.label.name[mlen-dlen-1] == '.'
812 && strcmp(dp->name, 791 && strcmp(dp->name,
813 mi.label.name + mlen - dlen) == 0) 792 mi.label.name + mlen - dlen) == 0)
814 break; 793 break;
815 } 794 }
816 if (dp->code >= 0) { 795 if (dp->code >= 0) {
817 di->devmap[dp->code] = i; 796 di->devmap[dp->code] = i;
818 di->rdevmap[i] = dp->code; 797 di->rdevmap[i] = dp->code;
819 di->devmask |= 1 << dp->code; 798 di->devmask |= 1 << dp->code;
820 if (mi.un.v.num_channels == 2) 799 if (mi.un.v.num_channels == 2)
821 di->stereomask |= 1 << dp->code; 800 di->stereomask |= 1 << dp->code;
822 strlcpy(di->names[i], mi.label.name, 801 strlcpy(di->names[i], mi.label.name,
823 sizeof di->names[i]); 802 sizeof di->names[i]);
824 } 803 }
825 break; 804 break;
826 } 805 }
827 } 806 }
828 for(i = 0; i < NETBSD_MAXDEVS; i++) { 807 for(i = 0; i < NETBSD_MAXDEVS; i++) {
829 mi.index = i; 808 mi.index = i;
830 if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0) 809 if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0)
831 break; 810 break;
832 if (strcmp(mi.label.name, AudioNsource) != 0) 811 if (strcmp(mi.label.name, AudioNsource) != 0)
833 continue; 812 continue;
834 di->source = i; 813 di->source = i;
835 switch(mi.type) { 814 switch(mi.type) {
836 case AUDIO_MIXER_ENUM: 815 case AUDIO_MIXER_ENUM:
837 for(j = 0; j < mi.un.e.num_mem; j++) { 816 for(j = 0; j < mi.un.e.num_mem; j++) {
838 e = opaque_to_enum(di, 817 e = opaque_to_enum(di,
839 &mi.un.e.member[j].label, 818 &mi.un.e.member[j].label,
840 mi.un.e.member[j].ord); 819 mi.un.e.member[j].ord);
841 if (e >= 0) 820 if (e >= 0)
842 di->recmask |= 1 << di->rdevmap[e]; 821 di->recmask |= 1 << di->rdevmap[e];
843 } 822 }
844 di->caps = SOUND_CAP_EXCL_INPUT; 823 di->caps = SOUND_CAP_EXCL_INPUT;
845 break; 824 break;
846 case AUDIO_MIXER_SET: 825 case AUDIO_MIXER_SET:
847 for(j = 0; j < mi.un.s.num_mem; j++) { 826 for(j = 0; j < mi.un.s.num_mem; j++) {
848 e = opaque_to_enum(di, 827 e = opaque_to_enum(di,
849 &mi.un.s.member[j].label, 828 &mi.un.s.member[j].label,
850 mi.un.s.member[j].mask); 829 mi.un.s.member[j].mask);
851 if (e >= 0) 830 if (e >= 0)
852 di->recmask |= 1 << di->rdevmap[e]; 831 di->recmask |= 1 << di->rdevmap[e];
853 } 832 }
854 break; 833 break;
855 } 834 }
856 } 835 }
857 return di; 836 return di;
858} 837}
859 838
860static int 839static int
861mixer_oss3_ioctl(int fd, unsigned long com, void *argp) 840mixer_oss3_ioctl(int fd, unsigned long com, void *argp)
862{ 841{
863 struct audiodevinfo *di; 842 struct audiodevinfo *di;
864 struct mixer_info *omi; 843 struct mixer_info *omi;
865 struct audio_device adev; 844 struct audio_device adev;
866 mixer_ctrl_t mc; 845 mixer_ctrl_t mc;
867 u_long idat, n; 846 u_long idat, n;
868 int i; 847 int i;
869 int retval; 848 int retval;
870 int l, r, error, e; 849 int l, r, error, e;
871 850
872 idat = 0; 851 idat = 0;
873 di = getdevinfo(fd); 852 di = getdevinfo(fd);
874 if (di == 0) 853 if (di == 0)
875 return -1; 854 return -1;
876 855
877 switch (com) { 856 switch (com) {
878 case OSS_GETVERSION: 857 case OSS_GETVERSION:
879 idat = SOUND_VERSION; 858 idat = SOUND_VERSION;
880 break; 859 break;
881 case SOUND_MIXER_INFO: 860 case SOUND_MIXER_INFO:
882 case SOUND_OLD_MIXER_INFO: 861 case SOUND_OLD_MIXER_INFO:
883 error = ioctl(fd, AUDIO_GETDEV, &adev); 862 error = ioctl(fd, AUDIO_GETDEV, &adev);
884 if (error) 863 if (error)
885 return (error); 864 return (error);
886 omi = argp; 865 omi = argp;
887 if (com == SOUND_MIXER_INFO) 866 if (com == SOUND_MIXER_INFO)
888 omi->modify_counter = 1; 867 omi->modify_counter = 1;
889 strlcpy(omi->id, adev.name, sizeof omi->id); 868 strlcpy(omi->id, adev.name, sizeof omi->id);
890 strlcpy(omi->name, adev.name, sizeof omi->name); 869 strlcpy(omi->name, adev.name, sizeof omi->name);
891 return 0; 870 return 0;
892 case SOUND_MIXER_READ_RECSRC: 871 case SOUND_MIXER_READ_RECSRC:
893 if (di->source == -1) 872 if (di->source == -1)
894 return EINVAL; 873 return EINVAL;
895 mc.dev = di->source; 874 mc.dev = di->source;
896 if (di->caps & SOUND_CAP_EXCL_INPUT) { 875 if (di->caps & SOUND_CAP_EXCL_INPUT) {
897 mc.type = AUDIO_MIXER_ENUM; 876 mc.type = AUDIO_MIXER_ENUM;
898 retval = ioctl(fd, AUDIO_MIXER_READ, &mc); 877 retval = ioctl(fd, AUDIO_MIXER_READ, &mc);
899 if (retval < 0) 878 if (retval < 0)
900 return retval; 879 return retval;
901 e = opaque_to_enum(di, NULL, mc.un.ord); 880 e = opaque_to_enum(di, NULL, mc.un.ord);
902 if (e >= 0) 881 if (e >= 0)
903 idat = 1 << di->rdevmap[e]; 882 idat = 1 << di->rdevmap[e];
904 } else { 883 } else {
905 mc.type = AUDIO_MIXER_SET; 884 mc.type = AUDIO_MIXER_SET;
906 retval = ioctl(fd, AUDIO_MIXER_READ, &mc); 885 retval = ioctl(fd, AUDIO_MIXER_READ, &mc);
907 if (retval < 0) 886 if (retval < 0)
908 return retval; 887 return retval;
909 e = opaque_to_enum(di, NULL, mc.un.mask); 888 e = opaque_to_enum(di, NULL, mc.un.mask);
910 if (e >= 0) 889 if (e >= 0)
911 idat = 1 << di->rdevmap[e]; 890 idat = 1 << di->rdevmap[e];
912 } 891 }
913 break; 892 break;
914 case SOUND_MIXER_READ_DEVMASK: 893 case SOUND_MIXER_READ_DEVMASK:
915 idat = di->devmask; 894 idat = di->devmask;
916 break; 895 break;
917 case SOUND_MIXER_READ_RECMASK: 896 case SOUND_MIXER_READ_RECMASK:
918 idat = di->recmask; 897 idat = di->recmask;
919 break; 898 break;
920 case SOUND_MIXER_READ_STEREODEVS: 899 case SOUND_MIXER_READ_STEREODEVS:
921 idat = di->stereomask; 900 idat = di->stereomask;
922 break; 901 break;
923 case SOUND_MIXER_READ_CAPS: 902 case SOUND_MIXER_READ_CAPS:
924 idat = di->caps; 903 idat = di->caps;
925 break; 904 break;
926 case SOUND_MIXER_WRITE_RECSRC: 905 case SOUND_MIXER_WRITE_RECSRC:
927 case SOUND_MIXER_WRITE_R_RECSRC: 906 case SOUND_MIXER_WRITE_R_RECSRC:
928 if (di->source == -1) 907 if (di->source == -1)
929 return EINVAL; 908 return EINVAL;
930 mc.dev = di->source; 909 mc.dev = di->source;
931 idat = INTARG; 910 idat = INTARG;
932 if (di->caps & SOUND_CAP_EXCL_INPUT) { 911 if (di->caps & SOUND_CAP_EXCL_INPUT) {
933 mc.type = AUDIO_MIXER_ENUM; 912 mc.type = AUDIO_MIXER_ENUM;
934 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) 913 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++)
935 if (idat & (1 << i)) 914 if (idat & (1 << i))
936 break; 915 break;
937 if (i >= SOUND_MIXER_NRDEVICES || 916 if (i >= SOUND_MIXER_NRDEVICES ||
938 di->devmap[i] == -1) 917 di->devmap[i] == -1)
939 return EINVAL; 918 return EINVAL;
940 mc.un.ord = enum_to_ord(di, di->devmap[i]); 919 mc.un.ord = enum_to_ord(di, di->devmap[i]);
941 } else { 920 } else {
942 mc.type = AUDIO_MIXER_SET; 921 mc.type = AUDIO_MIXER_SET;
943 mc.un.mask = 0; 922 mc.un.mask = 0;
944 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) { 923 for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
945 if (idat & (1 << i)) { 924 if (idat & (1 << i)) {
946 if (di->devmap[i] == -1) 925 if (di->devmap[i] == -1)
947 return EINVAL; 926 return EINVAL;
948 mc.un.mask |= 927 mc.un.mask |=
949 enum_to_mask(di, di->devmap[i]); 928 enum_to_mask(di, di->devmap[i]);
950 } 929 }
951 } 930 }
952 } 931 }
953 return ioctl(fd, AUDIO_MIXER_WRITE, &mc); 932 return ioctl(fd, AUDIO_MIXER_WRITE, &mc);
954 default: 933 default:
955 if (MIXER_READ(SOUND_MIXER_FIRST) <= com && 934 if (MIXER_READ(SOUND_MIXER_FIRST) <= com &&
956 com < MIXER_READ(SOUND_MIXER_NRDEVICES)) { 935 com < MIXER_READ(SOUND_MIXER_NRDEVICES)) {
957 n = GET_DEV(com); 936 n = GET_DEV(com);
958 if (di->devmap[n] == -1) 937 if (di->devmap[n] == -1)
959 return EINVAL; 938 return EINVAL;
960 mc.dev = di->devmap[n]; 939 mc.dev = di->devmap[n];
961 mc.type = AUDIO_MIXER_VALUE; 940 mc.type = AUDIO_MIXER_VALUE;
962 doread: 941 doread:
963 mc.un.value.num_channels = 942 mc.un.value.num_channels =
964 di->stereomask & (1 << (u_int)n) ? 2 : 1; 943 di->stereomask & (1 << (u_int)n) ? 2 : 1;
965 retval = ioctl(fd, AUDIO_MIXER_READ, &mc); 944 retval = ioctl(fd, AUDIO_MIXER_READ, &mc);
966 if (retval < 0) 945 if (retval < 0)
967 return retval; 946 return retval;
968 if (mc.type != AUDIO_MIXER_VALUE) 947 if (mc.type != AUDIO_MIXER_VALUE)
969 return EINVAL; 948 return EINVAL;
970 if (mc.un.value.num_channels != 2) { 949 if (mc.un.value.num_channels != 2) {
971 l = r = 950 l = r =
972 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO]; 951 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO];
973 } else { 952 } else {
974 l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 953 l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT];
975 r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 954 r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
976 } 955 }
977 idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8); 956 idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8);
978 break; 957 break;
979 } else if ((MIXER_WRITE_R(SOUND_MIXER_FIRST) <= com && 958 } else if ((MIXER_WRITE_R(SOUND_MIXER_FIRST) <= com &&
980 com < MIXER_WRITE_R(SOUND_MIXER_NRDEVICES)) || 959 com < MIXER_WRITE_R(SOUND_MIXER_NRDEVICES)) ||
981 (MIXER_WRITE(SOUND_MIXER_FIRST) <= com && 960 (MIXER_WRITE(SOUND_MIXER_FIRST) <= com &&
982 com < MIXER_WRITE(SOUND_MIXER_NRDEVICES))) { 961 com < MIXER_WRITE(SOUND_MIXER_NRDEVICES))) {
983 n = GET_DEV(com); 962 n = GET_DEV(com);
984 if (di->devmap[n] == -1) 963 if (di->devmap[n] == -1)
985 return EINVAL; 964 return EINVAL;
986 idat = INTARG; 965 idat = INTARG;
987 l = FROM_OSSVOL((u_int)idat & 0xff); 966 l = FROM_OSSVOL((u_int)idat & 0xff);
988 r = FROM_OSSVOL(((u_int)idat >> 8) & 0xff); 967 r = FROM_OSSVOL(((u_int)idat >> 8) & 0xff);
989 mc.dev = di->devmap[n]; 968 mc.dev = di->devmap[n];
990 mc.type = AUDIO_MIXER_VALUE; 969 mc.type = AUDIO_MIXER_VALUE;
991 if (di->stereomask & (1 << (u_int)n)) { 970 if (di->stereomask & (1 << (u_int)n)) {
992 mc.un.value.num_channels = 2; 971 mc.un.value.num_channels = 2;
993 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 972 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
994 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 973 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
995 } else { 974 } else {
996 mc.un.value.num_channels = 1; 975 mc.un.value.num_channels = 1;
997 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 976 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] =
998 (l + r) / 2; 977 (l + r) / 2;
999 } 978 }
1000 retval = ioctl(fd, AUDIO_MIXER_WRITE, &mc); 979 retval = ioctl(fd, AUDIO_MIXER_WRITE, &mc);
1001 if (retval < 0) 980 if (retval < 0)
1002 return retval; 981 return retval;
1003 if (MIXER_WRITE(SOUND_MIXER_FIRST) <= com && 982 if (MIXER_WRITE(SOUND_MIXER_FIRST) <= com &&
1004 com < MIXER_WRITE(SOUND_MIXER_NRDEVICES)) 983 com < MIXER_WRITE(SOUND_MIXER_NRDEVICES))
1005 return 0; 984 return 0;
1006 goto doread; 985 goto doread;
1007 } else { 986 } else {
1008 errno = EINVAL; 987 errno = EINVAL;
1009 return -1; 988 return -1;
1010 } 989 }
1011 } 990 }
1012 INTARG = (int)idat; 991 INTARG = (int)idat;
1013 return 0; 992 return 0;
1014} 993}
1015 994
1016static int 995static int
1017mixer_oss4_ioctl(int fd, unsigned long com, void *argp) 996mixer_oss4_ioctl(int fd, unsigned long com, void *argp)
1018{ 997{
1019 oss_audioinfo *tmpai; 998 oss_audioinfo *tmpai;
1020 oss_card_info *cardinfo; 999 oss_card_info *cardinfo;
1021 oss_mixext *ext; 1000 oss_mixext *ext;
1022 oss_mixext_root root; 1001 oss_mixext_root root;
1023 oss_mixer_enuminfo *ei; 1002 oss_mixer_enuminfo *ei;
1024 oss_mixer_value *mv; 1003 oss_mixer_value *mv;
1025 oss_mixerinfo *mi; 1004 oss_mixerinfo *mi;
1026 oss_sysinfo sysinfo; 1005 oss_sysinfo sysinfo;
1027 dev_t devno; 1006 dev_t devno;
1028 struct stat tmpstat; 1007 struct stat tmpstat;
1029 struct audio_device dev; 1008 struct audio_device dev;
1030 struct audio_format_query fmtq; 1009 struct audio_format_query fmtq;
1031 struct mixer_devinfo mdi; 1010 struct mixer_devinfo mdi;
1032 struct mixer_ctrl mc; 1011 struct mixer_ctrl mc;
1033 char devname[32]; 1012 char devname[32];
1034 size_t len; 1013 size_t len;
1035 int newfd = -1, tmperrno; 1014 int newfd = -1, tmperrno;
1036 int i, noffs; 1015 int i, noffs;
1037 int retval; 1016 int retval;
1038 int props, caps; 1017 int props, caps;
1039 1018
1040 /* 1019 /*
1041 * Note: it is difficult to translate the NetBSD concept of a "set" 1020 * Note: it is difficult to translate the NetBSD concept of a "set"
1042 * mixer control type to the OSSv4 API, as far as I can tell. 1021 * mixer control type to the OSSv4 API, as far as I can tell.
1043 * 1022 *
1044 * This means they are treated like enums, i.e. only one entry in the 1023 * This means they are treated like enums, i.e. only one entry in the
1045 * set can be selected at a time. 1024 * set can be selected at a time.
1046 */ 1025 */
1047 1026
1048 switch (com) { 1027 switch (com) {
1049 case SNDCTL_AUDIOINFO: 1028 case SNDCTL_AUDIOINFO:
1050 /* 1029 /*
1051 * SNDCTL_AUDIOINFO_EX is intended for underlying hardware devices 1030 * SNDCTL_AUDIOINFO_EX is intended for underlying hardware devices
1052 * that are to be opened in "exclusive mode" (bypassing the normal 1031 * that are to be opened in "exclusive mode" (bypassing the normal
1053 * kernel mixer for exclusive control). NetBSD does not support 1032 * kernel mixer for exclusive control). NetBSD does not support
1054 * bypassing the kernel mixer, so it's an alias of SNDCTL_AUDIOINFO. 1033 * bypassing the kernel mixer, so it's an alias of SNDCTL_AUDIOINFO.
1055 */ 1034 */
1056 case SNDCTL_AUDIOINFO_EX: 1035 case SNDCTL_AUDIOINFO_EX:
1057 case SNDCTL_ENGINEINFO: 1036 case SNDCTL_ENGINEINFO:
1058 devno = 0; 1037 devno = 0;
1059 tmpai = (struct oss_audioinfo*)argp; 1038 tmpai = (struct oss_audioinfo*)argp;
1060 if (tmpai == NULL) { 1039 if (tmpai == NULL) {
1061 errno = EINVAL; 1040 errno = EINVAL;
1062 return -1; 1041 return -1;
1063 } 1042 }
1064 1043
1065 /* 1044 /*
1066 * If the input device is -1, guess the device related to 1045 * If the input device is -1, guess the device related to
1067 * the open mixer device. 1046 * the open mixer device.
1068 */ 1047 */
1069 if (tmpai->dev < 0) { 1048 if (tmpai->dev < 0) {
1070 fstat(fd, &tmpstat); 1049 fstat(fd, &tmpstat);
1071 if ((tmpstat.st_rdev & 0xff00) == 0x2a00) 1050 if ((tmpstat.st_rdev & 0xff00) == 0x2a00)
1072 devno = tmpstat.st_rdev & 0xff; 1051 devno = tmpstat.st_rdev & 0xff;
1073 if (devno >= 0x80) 1052 if (devno >= 0x80)
1074 tmpai->dev = devno & 0x7f; 1053 tmpai->dev = devno & 0x7f;
1075 } 1054 }
1076 if (tmpai->dev < 0) 1055 if (tmpai->dev < 0)
1077 tmpai->dev = 0; 1056 tmpai->dev = 0;
1078 1057
1079 snprintf(tmpai->devnode, sizeof(tmpai->devnode), 1058 snprintf(tmpai->devnode, sizeof(tmpai->devnode),
1080 "/dev/audio%d", tmpai->dev); 1059 "/dev/audio%d", tmpai->dev);
1081 1060
1082 if ((newfd = open(tmpai->devnode, O_WRONLY)) < 0) { 1061 if ((newfd = open(tmpai->devnode, O_WRONLY)) < 0) {
1083 if ((newfd = open(tmpai->devnode, O_RDONLY)) < 0) { 1062 if ((newfd = open(tmpai->devnode, O_RDONLY)) < 0) {
1084 return newfd; 1063 return newfd;
1085 } 1064 }
1086 } 1065 }
1087 1066
1088 retval = ioctl(newfd, AUDIO_GETDEV, &dev); 1067 retval = ioctl(newfd, AUDIO_GETDEV, &dev);
1089 if (retval < 0) { 1068 if (retval < 0) {
1090 tmperrno = errno; 1069 tmperrno = errno;
1091 close(newfd); 1070 close(newfd);
1092 errno = tmperrno; 1071 errno = tmperrno;
1093 return retval; 1072 return retval;
1094 } 1073 }
1095 retval = ioctl(newfd, AUDIO_GETPROPS, &props); 1074 retval = ioctl(newfd, AUDIO_GETPROPS, &props);
1096 if (retval < 0) { 1075 if (retval < 0) {
1097 tmperrno = errno; 1076 tmperrno = errno;
1098 close(newfd); 1077 close(newfd);
1099 errno = tmperrno; 1078 errno = tmperrno;
1100 return retval; 1079 return retval;
1101 } 1080 }
1102 caps = DSP_CAP_TRIGGER; 1081 caps = DSP_CAP_TRIGGER;
1103 if (props & AUDIO_PROP_FULLDUPLEX) 1082 if (props & AUDIO_PROP_FULLDUPLEX)
1104 caps |= DSP_CAP_DUPLEX; 1083 caps |= DSP_CAP_DUPLEX;
1105 if (props & AUDIO_PROP_MMAP) 1084 if (props & AUDIO_PROP_MMAP)
1106 caps |= DSP_CAP_MMAP; 1085 caps |= DSP_CAP_MMAP;
1107 if (props & AUDIO_PROP_CAPTURE) 1086 if (props & AUDIO_PROP_CAPTURE)
1108 caps |= PCM_CAP_INPUT; 1087 caps |= PCM_CAP_INPUT;
1109 if (props & AUDIO_PROP_PLAYBACK) 1088 if (props & AUDIO_PROP_PLAYBACK)
1110 caps |= PCM_CAP_OUTPUT; 1089 caps |= PCM_CAP_OUTPUT;
1111 snprintf(tmpai->name, sizeof(tmpai->name), 1090 snprintf(tmpai->name, sizeof(tmpai->name),
1112 "%s %s", dev.name, dev.version); 1091 "%s %s", dev.name, dev.version);
1113 tmpai->busy = 0; 1092 tmpai->busy = 0;
1114 tmpai->pid = -1; 1093 tmpai->pid = -1;
1115 tmpai->caps = caps; 1094 tmpai->caps = caps;
1116 ioctl(newfd, SNDCTL_DSP_GETFMTS, &tmpai->iformats); 1095 ioctl(newfd, SNDCTL_DSP_GETFMTS, &tmpai->iformats);
1117 tmpai->oformats = tmpai->iformats; 1096 tmpai->oformats = tmpai->iformats;
1118 tmpai->magic = -1; /* reserved for "internal use" */ 1097 tmpai->magic = -1; /* reserved for "internal use" */
1119 memset(tmpai->cmd, 0, sizeof(tmpai->cmd)); 1098 memset(tmpai->cmd, 0, sizeof(tmpai->cmd));
1120 tmpai->card_number = -1; 1099 tmpai->card_number = -1;
1121 memset(tmpai->song_name, 0, 1100 memset(tmpai->song_name, 0,
1122 sizeof(tmpai->song_name)); 1101 sizeof(tmpai->song_name));
1123 memset(tmpai->label, 0, sizeof(tmpai->label)); 1102 memset(tmpai->label, 0, sizeof(tmpai->label));
1124 tmpai->port_number = 0; 1103 tmpai->port_number = 0;
1125 tmpai->mixer_dev = tmpai->dev; 1104 tmpai->mixer_dev = tmpai->dev;
1126 tmpai->legacy_device = tmpai->dev; 1105 tmpai->legacy_device = tmpai->dev;
1127 tmpai->enabled = 1; 1106 tmpai->enabled = 1;
1128 tmpai->flags = -1; /* reserved for "future versions" */ 1107 tmpai->flags = -1; /* reserved for "future versions" */
1129 tmpai->min_rate = 1000; 1108 tmpai->min_rate = 1000;
1130 tmpai->max_rate = 192000; 1109 tmpai->max_rate = 192000;
1131 tmpai->nrates = 0; 1110 tmpai->nrates = 0;
1132 tmpai->min_channels = 1; 1111 tmpai->min_channels = 1;
1133 tmpai->max_channels = 2; 1112 tmpai->max_channels = 2;
1134 for (fmtq.index = 0; 1113 for (fmtq.index = 0;
1135 ioctl(newfd, AUDIO_QUERYFORMAT, &fmtq) != -1; ++fmtq.index) { 1114 ioctl(newfd, AUDIO_QUERYFORMAT, &fmtq) != -1; ++fmtq.index) {
1136 if (fmtq.fmt.channels > (unsigned)tmpai->max_channels) 1115 if (fmtq.fmt.channels > (unsigned)tmpai->max_channels)
1137 tmpai->max_channels = fmtq.fmt.channels; 1116 tmpai->max_channels = fmtq.fmt.channels;
1138 } 1117 }
1139 tmpai->binding = -1; /* reserved for "future versions" */ 1118 tmpai->binding = -1; /* reserved for "future versions" */
1140 tmpai->rate_source = -1; 1119 tmpai->rate_source = -1;
1141 /* 1120 /*
1142 * 'handle' is supposed to be globally unique. The closest 1121 * 'handle' is supposed to be globally unique. The closest
1143 * we have to that is probably device nodes. 1122 * we have to that is probably device nodes.
1144 */ 1123 */
1145 strlcpy(tmpai->handle, tmpai->devnode, 1124 strlcpy(tmpai->handle, tmpai->devnode,
1146 sizeof(tmpai->handle)); 1125 sizeof(tmpai->handle));
1147 tmpai->next_play_engine = 0; 1126 tmpai->next_play_engine = 0;
1148 tmpai->next_rec_engine = 0; 1127 tmpai->next_rec_engine = 0;
1149 argp = tmpai; 1128 argp = tmpai;
1150 close(newfd); 1129 close(newfd);
1151 break; 1130 break;
1152 case SNDCTL_CARDINFO: 1131 case SNDCTL_CARDINFO:
1153 cardinfo = (oss_card_info *)argp; 1132 cardinfo = (oss_card_info *)argp;
1154 if (cardinfo == NULL) 1133 if (cardinfo == NULL)
1155 return EINVAL; 1134 return EINVAL;
1156 if (cardinfo->card != -1) { 1135 if (cardinfo->card != -1) {
1157 snprintf(devname, sizeof(devname), 1136 snprintf(devname, sizeof(devname),
1158 "/dev/audio%d", cardinfo->card); 1137 "/dev/audio%d", cardinfo->card);
1159 newfd = open(devname, O_RDONLY); 1138 newfd = open(devname, O_RDONLY);
1160 if (newfd < 0) 1139 if (newfd < 0)
1161 return newfd; 1140 return newfd;
1162 } else { 1141 } else {
1163 newfd = fd; 1142 newfd = fd;
1164 } 1143 }
1165 retval = ioctl(newfd, AUDIO_GETDEV, &dev); 1144 retval = ioctl(newfd, AUDIO_GETDEV, &dev);
1166 tmperrno = errno; 1145 tmperrno = errno;
1167 if (newfd != fd) 1146 if (newfd != fd)
1168 close(newfd); 1147 close(newfd);
1169 if (retval < 0) { 1148 if (retval < 0) {
1170 errno = tmperrno; 1149 errno = tmperrno;
1171 return retval; 1150 return retval;
1172 } 1151 }
1173 strlcpy(cardinfo->shortname, dev.name, 1152 strlcpy(cardinfo->shortname, dev.name,
1174 sizeof(cardinfo->shortname)); 1153 sizeof(cardinfo->shortname));
1175 snprintf(cardinfo->longname, sizeof(cardinfo->longname), 1154 snprintf(cardinfo->longname, sizeof(cardinfo->longname),
1176 "%s %s %s", dev.name, dev.version, dev.config); 1155 "%s %s %s", dev.name, dev.version, dev.config);
1177 memset(cardinfo->hw_info, 0, sizeof(cardinfo->hw_info)); 1156 memset(cardinfo->hw_info, 0, sizeof(cardinfo->hw_info));
1178 /* 1157 /*
1179 * OSSv4 does not document this ioctl, and claims it should 1158 * OSSv4 does not document this ioctl, and claims it should
1180 * not be used by applications and is provided for "utiltiy 1159 * not be used by applications and is provided for "utiltiy
1181 * programs included in OSS". We follow the Solaris 1160 * programs included in OSS". We follow the Solaris
1182 * implementation (which is documented) and leave these fields 1161 * implementation (which is documented) and leave these fields
1183 * unset. 1162 * unset.
1184 */ 1163 */
1185 cardinfo->flags = 0; 1164 cardinfo->flags = 0;
1186 cardinfo->intr_count = 0; 1165 cardinfo->intr_count = 0;
1187 cardinfo->ack_count = 0; 1166 cardinfo->ack_count = 0;
1188 break; 1167 break;
1189 case SNDCTL_SYSINFO: 1168 case SNDCTL_SYSINFO:
1190 memset(&sysinfo, 0, sizeof(sysinfo)); 1169 memset(&sysinfo, 0, sizeof(sysinfo));
1191 strlcpy(sysinfo.product, 1170 strlcpy(sysinfo.product,
1192 "OSS/NetBSD", sizeof(sysinfo.product)); 1171 "OSS/NetBSD", sizeof(sysinfo.product));
1193 strlcpy(sysinfo.version, 1172 strlcpy(sysinfo.version,
1194 "4.01", sizeof(sysinfo.version)); 1173 "4.01", sizeof(sysinfo.version));
1195 strlcpy(sysinfo.license, 1174 strlcpy(sysinfo.license,
1196 "BSD", sizeof(sysinfo.license)); 1175 "BSD", sizeof(sysinfo.license));
1197 sysinfo.versionnum = SOUND_VERSION; 1176 sysinfo.versionnum = SOUND_VERSION;
1198 sysinfo.numaudios =  1177 sysinfo.numaudios =
1199 sysinfo.numcards = 1178 sysinfo.numcards =
1200 getaudiocount(); 1179 getaudiocount();
1201 sysinfo.numaudioengines = 1; 1180 sysinfo.numaudioengines = 1;
1202 sysinfo.numsynths = 1; 1181 sysinfo.numsynths = 1;
1203 sysinfo.nummidis = -1; 1182 sysinfo.nummidis = -1;
1204 sysinfo.numtimers = -1; 1183 sysinfo.numtimers = -1;
1205 sysinfo.nummixers = getmixercount(); 1184 sysinfo.nummixers = getmixercount();
1206 *(struct oss_sysinfo *)argp = sysinfo; 1185 *(struct oss_sysinfo *)argp = sysinfo;
1207 break; 1186 break;
1208 case SNDCTL_MIXERINFO: 1187 case SNDCTL_MIXERINFO:
1209 mi = (oss_mixerinfo *)argp; 1188 mi = (oss_mixerinfo *)argp;
1210 if (mi == NULL) { 1189 if (mi == NULL) {
1211 errno = EINVAL; 1190 errno = EINVAL;