Mon Apr 20 12:01:44 2020 UTC ()
ossaudio: removed outdated comment


(nia)
diff -r1.43 -r1.44 src/lib/libossaudio/ossaudio.c

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

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