Wed Apr 15 15:25:33 2020 UTC ()
ossaudio: Make SNDCTL_DSP_SETFMT conform with OSSv4.

The OSSv4 spec says we shouldn't really error if an invalid format is
chosen by an application. Things are especially likely to be confused
if we return MULAW, since in OSSv4 terms that means that's the native
hardware format. Instead, set and return the current hardware format
if an invalid format is chosen.

For the 24-bit sample formats, note that the NetBSD kernel currently
can't handle them in its default configuration, and will return an error
code if you attempt to use them. So, if an applicaton requests 24-bit PCM,
promote it to 32-bit PCM. According to the spec, this is valid and
applications should be checking the return value anyway.

In the Linux compat layer, we just use S16LE as a fallback. The OSSv3
headers that are still being shipped with Linux don't contain definitions
for fancier formats and we can reasonably expect all applications to
support S16LE.


(nia)
diff -r1.39 -r1.40 src/lib/libossaudio/ossaudio.c
diff -r1.79 -r1.80 src/sys/compat/ossaudio/ossaudio.c

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

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

cvs diff -r1.79 -r1.80 src/sys/compat/ossaudio/ossaudio.c (switch to unified diff)

--- src/sys/compat/ossaudio/ossaudio.c 2020/04/15 14:54:34 1.79
+++ src/sys/compat/ossaudio/ossaudio.c 2020/04/15 15:25:33 1.80
@@ -1,1400 +1,1409 @@ @@ -1,1400 +1,1409 @@
1/* $NetBSD: ossaudio.c,v 1.79 2020/04/15 14:54:34 nia Exp $ */ 1/* $NetBSD: ossaudio.c,v 1.80 2020/04/15 15:25:33 nia Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997, 2008 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__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.79 2020/04/15 14:54:34 nia Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.80 2020/04/15 15:25:33 nia Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/proc.h> 33#include <sys/proc.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/file.h> 35#include <sys/file.h>
36#include <sys/vnode.h> 36#include <sys/vnode.h>
37#include <sys/filedesc.h> 37#include <sys/filedesc.h>
38#include <sys/ioctl.h> 38#include <sys/ioctl.h>
39#include <sys/mount.h> 39#include <sys/mount.h>
40#include <sys/kernel.h> 40#include <sys/kernel.h>
41#include <sys/audioio.h> 41#include <sys/audioio.h>
42#include <sys/midiio.h> 42#include <sys/midiio.h>
43#include <sys/kauth.h> 43#include <sys/kauth.h>
44#include <sys/syscallargs.h> 44#include <sys/syscallargs.h>
45#include <sys/module.h> 45#include <sys/module.h>
46 46
47#include <compat/ossaudio/ossaudio.h> 47#include <compat/ossaudio/ossaudio.h>
48#include <compat/ossaudio/ossaudiovar.h> 48#include <compat/ossaudio/ossaudiovar.h>
49 49
50MODULE(MODULE_CLASS_EXEC, compat_ossaudio, NULL); 50MODULE(MODULE_CLASS_EXEC, compat_ossaudio, NULL);
51 51
52#ifdef AUDIO_DEBUG 52#ifdef AUDIO_DEBUG
53#define DPRINTF(x) if (ossdebug) printf x 53#define DPRINTF(x) if (ossdebug) printf x
54int ossdebug = 0; 54int ossdebug = 0;
55#else 55#else
56#define DPRINTF(x) 56#define DPRINTF(x)
57#endif 57#endif
58 58
59#define TO_OSSVOL(x) (((x) * 100 + 127) / 255) 59#define TO_OSSVOL(x) (((x) * 100 + 127) / 255)
60#define FROM_OSSVOL(x) ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100) 60#define FROM_OSSVOL(x) ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100)
61 61
62#define GETPRINFO(info, name) \ 62#define GETPRINFO(info, name) \
63 (((info)->mode == AUMODE_RECORD) \ 63 (((info)->mode == AUMODE_RECORD) \
64 ? (info)->record.name : (info)->play.name) 64 ? (info)->record.name : (info)->play.name)
65 65
66static struct audiodevinfo *getdevinfo(file_t *); 66static struct audiodevinfo *getdevinfo(file_t *);
67static int opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq); 67static int opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq);
68static int enum_to_ord(struct audiodevinfo *di, int enm); 68static int enum_to_ord(struct audiodevinfo *di, int enm);
69static int enum_to_mask(struct audiodevinfo *di, int enm); 69static int enum_to_mask(struct audiodevinfo *di, int enm);
70 70
71static void setblocksize(file_t *, struct audio_info *); 71static void setblocksize(file_t *, struct audio_info *);
72 72
73#ifdef AUDIO_DEBUG 73#ifdef AUDIO_DEBUG
74static const char * 74static const char *
75compat_ossaudio_getcmd(u_long cmd) 75compat_ossaudio_getcmd(u_long cmd)
76{ 76{
77 static char buf[64]; 77 static char buf[64];
78 switch (cmd) { 78 switch (cmd) {
79#define _DO(_a) \ 79#define _DO(_a) \
80 case _a: \ 80 case _a: \
81 return # _a; 81 return # _a;
82_DO(OSS_SNDCTL_DSP_RESET) 82_DO(OSS_SNDCTL_DSP_RESET)
83_DO(OSS_SNDCTL_DSP_SYNC) 83_DO(OSS_SNDCTL_DSP_SYNC)
84_DO(OSS_SNDCTL_DSP_SPEED) 84_DO(OSS_SNDCTL_DSP_SPEED)
85_DO(OSS_SOUND_PCM_READ_RATE) 85_DO(OSS_SOUND_PCM_READ_RATE)
86_DO(OSS_SNDCTL_DSP_STEREO) 86_DO(OSS_SNDCTL_DSP_STEREO)
87_DO(OSS_SNDCTL_DSP_GETBLKSIZE) 87_DO(OSS_SNDCTL_DSP_GETBLKSIZE)
88_DO(OSS_SNDCTL_DSP_SETFMT) 88_DO(OSS_SNDCTL_DSP_SETFMT)
89_DO(OSS_SOUND_PCM_READ_BITS) 89_DO(OSS_SOUND_PCM_READ_BITS)
90_DO(OSS_SNDCTL_DSP_CHANNELS) 90_DO(OSS_SNDCTL_DSP_CHANNELS)
91_DO(OSS_SOUND_PCM_READ_CHANNELS) 91_DO(OSS_SOUND_PCM_READ_CHANNELS)
92_DO(OSS_SOUND_PCM_WRITE_FILTER) 92_DO(OSS_SOUND_PCM_WRITE_FILTER)
93_DO(OSS_SOUND_PCM_READ_FILTER) 93_DO(OSS_SOUND_PCM_READ_FILTER)
94_DO(OSS_SNDCTL_DSP_POST) 94_DO(OSS_SNDCTL_DSP_POST)
95_DO(OSS_SNDCTL_DSP_SUBDIVIDE) 95_DO(OSS_SNDCTL_DSP_SUBDIVIDE)
96_DO(OSS_SNDCTL_DSP_SETFRAGMENT) 96_DO(OSS_SNDCTL_DSP_SETFRAGMENT)
97_DO(OSS_SNDCTL_DSP_GETFMTS) 97_DO(OSS_SNDCTL_DSP_GETFMTS)
98_DO(OSS_SNDCTL_DSP_GETOSPACE) 98_DO(OSS_SNDCTL_DSP_GETOSPACE)
99_DO(OSS_SNDCTL_DSP_GETISPACE) 99_DO(OSS_SNDCTL_DSP_GETISPACE)
100_DO(OSS_SNDCTL_DSP_NONBLOCK) 100_DO(OSS_SNDCTL_DSP_NONBLOCK)
101_DO(OSS_SNDCTL_DSP_GETCAPS) 101_DO(OSS_SNDCTL_DSP_GETCAPS)
102_DO(OSS_SNDCTL_DSP_GETTRIGGER) 102_DO(OSS_SNDCTL_DSP_GETTRIGGER)
103_DO(OSS_SNDCTL_DSP_SETTRIGGER) 103_DO(OSS_SNDCTL_DSP_SETTRIGGER)
104_DO(OSS_SNDCTL_DSP_GETIPTR) 104_DO(OSS_SNDCTL_DSP_GETIPTR)
105_DO(OSS_SNDCTL_DSP_GETOPTR) 105_DO(OSS_SNDCTL_DSP_GETOPTR)
106_DO(OSS_SNDCTL_DSP_MAPINBUF) 106_DO(OSS_SNDCTL_DSP_MAPINBUF)
107_DO(OSS_SNDCTL_DSP_MAPOUTBUF) 107_DO(OSS_SNDCTL_DSP_MAPOUTBUF)
108_DO(OSS_SNDCTL_DSP_SETSYNCRO) 108_DO(OSS_SNDCTL_DSP_SETSYNCRO)
109_DO(OSS_SNDCTL_DSP_SETDUPLEX) 109_DO(OSS_SNDCTL_DSP_SETDUPLEX)
110_DO(OSS_SNDCTL_DSP_GETODELAY) 110_DO(OSS_SNDCTL_DSP_GETODELAY)
111_DO(OSS_SNDCTL_DSP_PROFILE) 111_DO(OSS_SNDCTL_DSP_PROFILE)
112_DO(OSS_SOUND_MIXER_INFO) 112_DO(OSS_SOUND_MIXER_INFO)
113_DO(OSS_SOUND_OLD_MIXER_INFO) 113_DO(OSS_SOUND_OLD_MIXER_INFO)
114_DO(OSS_GET_VERSION) 114_DO(OSS_GET_VERSION)
115_DO(OSS_SEQ_RESET) 115_DO(OSS_SEQ_RESET)
116_DO(OSS_SEQ_SYNC) 116_DO(OSS_SEQ_SYNC)
117_DO(OSS_SYNTH_INFO) 117_DO(OSS_SYNTH_INFO)
118_DO(OSS_SEQ_CTRLRATE) 118_DO(OSS_SEQ_CTRLRATE)
119_DO(OSS_SEQ_GETOUTCOUNT) 119_DO(OSS_SEQ_GETOUTCOUNT)
120_DO(OSS_SEQ_GETINCOUNT) 120_DO(OSS_SEQ_GETINCOUNT)
121_DO(OSS_SEQ_PERCMODE) 121_DO(OSS_SEQ_PERCMODE)
122_DO(OSS_SEQ_TESTMIDI) 122_DO(OSS_SEQ_TESTMIDI)
123_DO(OSS_SEQ_RESETSAMPLES) 123_DO(OSS_SEQ_RESETSAMPLES)
124_DO(OSS_SEQ_NRSYNTHS) 124_DO(OSS_SEQ_NRSYNTHS)
125_DO(OSS_SEQ_NRMIDIS) 125_DO(OSS_SEQ_NRMIDIS)
126#ifdef notyet 126#ifdef notyet
127_DO(OSS_MIDI_INFO) 127_DO(OSS_MIDI_INFO)
128#endif 128#endif
129_DO(OSS_SEQ_THRESHOLD) 129_DO(OSS_SEQ_THRESHOLD)
130_DO(OSS_MEMAVL) 130_DO(OSS_MEMAVL)
131_DO(OSS_FM_4OP_ENABLE) 131_DO(OSS_FM_4OP_ENABLE)
132_DO(OSS_SEQ_PANIC) 132_DO(OSS_SEQ_PANIC)
133_DO(OSS_SEQ_OUTOFBAND) 133_DO(OSS_SEQ_OUTOFBAND)
134_DO(OSS_SEQ_GETTIME) 134_DO(OSS_SEQ_GETTIME)
135_DO(OSS_ID) 135_DO(OSS_ID)
136_DO(OSS_CONTROL) 136_DO(OSS_CONTROL)
137_DO(OSS_REMOVESAMPLE) 137_DO(OSS_REMOVESAMPLE)
138_DO(OSS_TMR_TIMEBASE) 138_DO(OSS_TMR_TIMEBASE)
139_DO(OSS_TMR_START) 139_DO(OSS_TMR_START)
140_DO(OSS_TMR_STOP) 140_DO(OSS_TMR_STOP)
141_DO(OSS_TMR_CONTINUE) 141_DO(OSS_TMR_CONTINUE)
142_DO(OSS_TMR_TEMPO) 142_DO(OSS_TMR_TEMPO)
143_DO(OSS_TMR_SOURCE) 143_DO(OSS_TMR_SOURCE)
144_DO(OSS_TMR_METRONOME) 144_DO(OSS_TMR_METRONOME)
145_DO(OSS_TMR_SELECT) 145_DO(OSS_TMR_SELECT)
146#undef _DO 146#undef _DO
147 default: 147 default:
148 (void)snprintf(buf, sizeof(buf), "*0x%lx*", cmd); 148 (void)snprintf(buf, sizeof(buf), "*0x%lx*", cmd);
149 return buf; 149 return buf;
150 } 150 }
151} 151}
152#endif 152#endif
153 153
154 154
155static int 155static int
156compat_ossaudio_modcmd(modcmd_t cmd, void *arg) 156compat_ossaudio_modcmd(modcmd_t cmd, void *arg)
157{ 157{
158 158
159 switch (cmd) { 159 switch (cmd) {
160 case MODULE_CMD_INIT: 160 case MODULE_CMD_INIT:
161 case MODULE_CMD_FINI: 161 case MODULE_CMD_FINI:
162 return 0; 162 return 0;
163 default: 163 default:
164 return ENOTTY; 164 return ENOTTY;
165 } 165 }
166} 166}
167 167
168int 168int
169oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval) 169oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval)
170{ 170{
171 /* { 171 /* {
172 syscallarg(int) fd; 172 syscallarg(int) fd;
173 syscallarg(u_long) com; 173 syscallarg(u_long) com;
174 syscallarg(void *) data; 174 syscallarg(void *) data;
175 } */ 175 } */
176 file_t *fp; 176 file_t *fp;
177 u_long com; 177 u_long com;
178 struct audio_info tmpinfo, hwfmt; 178 struct audio_info tmpinfo, hwfmt;
179 struct audio_offset tmpoffs; 179 struct audio_offset tmpoffs;
180 struct oss_audio_buf_info bufinfo; 180 struct oss_audio_buf_info bufinfo;
181 struct oss_count_info cntinfo; 181 struct oss_count_info cntinfo;
182 struct audio_encoding tmpenc; 182 struct audio_encoding tmpenc;
183 u_int u; 183 u_int u;
184 u_int encoding; 184 u_int encoding;
185 u_int precision; 185 u_int precision;
186 int idat, idata; 186 int idat, idata;
187 int error = 0; 187 int error = 0;
188 int (*ioctlf)(file_t *, u_long, void *); 188 int (*ioctlf)(file_t *, u_long, void *);
189 189
190 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) 190 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
191 return (EBADF); 191 return (EBADF);
192 192
193 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 193 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
194 error = EBADF; 194 error = EBADF;
195 goto out; 195 goto out;
196 } 196 }
197 197
198 com = SCARG(uap, com); 198 com = SCARG(uap, com);
199 DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com))); 199 DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com)));
200 200
201 retval[0] = 0; 201 retval[0] = 0;
202 202
203 ioctlf = fp->f_ops->fo_ioctl; 203 ioctlf = fp->f_ops->fo_ioctl;
204 switch (com) { 204 switch (com) {
205 case OSS_SNDCTL_DSP_RESET: 205 case OSS_SNDCTL_DSP_RESET:
206 error = ioctlf(fp, AUDIO_FLUSH, NULL); 206 error = ioctlf(fp, AUDIO_FLUSH, NULL);
207 if (error) { 207 if (error) {
208 DPRINTF(("%s: AUDIO_FLUSH %d\n", __func__, error)); 208 DPRINTF(("%s: AUDIO_FLUSH %d\n", __func__, error));
209 goto out; 209 goto out;
210 } 210 }
211 break; 211 break;
212 case OSS_SNDCTL_DSP_SYNC: 212 case OSS_SNDCTL_DSP_SYNC:
213 error = ioctlf(fp, AUDIO_DRAIN, NULL); 213 error = ioctlf(fp, AUDIO_DRAIN, NULL);
214 if (error) { 214 if (error) {
215 DPRINTF(("%s: AUDIO_DRAIN %d\n", __func__, error)); 215 DPRINTF(("%s: AUDIO_DRAIN %d\n", __func__, error));
216 goto out; 216 goto out;
217 } 217 }
218 break; 218 break;
219 case OSS_SNDCTL_DSP_POST: 219 case OSS_SNDCTL_DSP_POST:
220 /* This call is merely advisory, and may be a nop. */ 220 /* This call is merely advisory, and may be a nop. */
221 break; 221 break;
222 case OSS_SNDCTL_DSP_SPEED: 222 case OSS_SNDCTL_DSP_SPEED:
223 AUDIO_INITINFO(&tmpinfo); 223 AUDIO_INITINFO(&tmpinfo);
224 error = copyin(SCARG(uap, data), &idat, sizeof idat); 224 error = copyin(SCARG(uap, data), &idat, sizeof idat);
225 if (error) { 225 if (error) {
226 DPRINTF(("%s: SNDCTL_DSP_SPEED %d\n", 226 DPRINTF(("%s: SNDCTL_DSP_SPEED %d\n",
227 __func__, error)); 227 __func__, error));
228 goto out; 228 goto out;
229 } 229 }
230 tmpinfo.play.sample_rate = 230 tmpinfo.play.sample_rate =
231 tmpinfo.record.sample_rate = idat; 231 tmpinfo.record.sample_rate = idat;
232 DPRINTF(("%s: SNDCTL_DSP_SPEED > %d\n", __func__, idat)); 232 DPRINTF(("%s: SNDCTL_DSP_SPEED > %d\n", __func__, idat));
233 /* 233 /*
234 * The default NetBSD behavior if an unsupported sample rate 234 * The default NetBSD behavior if an unsupported sample rate
235 * is set is to return an error code and keep the rate at the 235 * is set is to return an error code and keep the rate at the
236 * default of 8000 Hz. 236 * default of 8000 Hz.
237 * 237 *
238 * However, the OSS expectation is a sample rate supported by 238 * However, the OSS expectation is a sample rate supported by
239 * the hardware is returned if the exact rate could not be set. 239 * the hardware is returned if the exact rate could not be set.
240 * 240 *
241 * So, if the chosen sample rate is invalid, set and return 241 * So, if the chosen sample rate is invalid, set and return
242 * the current hardware rate. 242 * the current hardware rate.
243 */ 243 */
244 if (ioctlf(fp, AUDIO_SETINFO, &tmpinfo) != 0) { 244 if (ioctlf(fp, AUDIO_SETINFO, &tmpinfo) != 0) {
245 error = ioctlf(fp, AUDIO_GETFORMAT, &hwfmt); 245 error = ioctlf(fp, AUDIO_GETFORMAT, &hwfmt);
246 if (error) { 246 if (error) {
247 DPRINTF(("%s: AUDIO_GETFORMAT %d\n", 247 DPRINTF(("%s: AUDIO_GETFORMAT %d\n",
248 __func__, error)); 248 __func__, error));
249 goto out; 249 goto out;
250 } 250 }
251 error = ioctlf(fp, AUDIO_GETINFO, &tmpinfo); 251 error = ioctlf(fp, AUDIO_GETINFO, &tmpinfo);
252 if (error) { 252 if (error) {
253 DPRINTF(("%s: AUDIO_GETINFO %d\n", 253 DPRINTF(("%s: AUDIO_GETINFO %d\n",
254 __func__, error)); 254 __func__, error));
255 goto out; 255 goto out;
256 } 256 }
257 tmpinfo.play.sample_rate = 257 tmpinfo.play.sample_rate =
258 tmpinfo.record.sample_rate = 258 tmpinfo.record.sample_rate =
259 (tmpinfo.mode == AUMODE_RECORD) ? 259 (tmpinfo.mode == AUMODE_RECORD) ?
260 hwfmt.record.sample_rate : 260 hwfmt.record.sample_rate :
261 hwfmt.play.sample_rate; 261 hwfmt.play.sample_rate;
262 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 262 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
263 if (error) { 263 if (error) {
264 DPRINTF(("%s: SNDCTL_DSP_SPEED %d = %d\n", 264 DPRINTF(("%s: SNDCTL_DSP_SPEED %d = %d\n",
265 __func__, idat, error)); 265 __func__, idat, error));
266 goto out; 266 goto out;
267 } 267 }
268 } 268 }
269 /* FALLTHROUGH */ 269 /* FALLTHROUGH */
270 case OSS_SOUND_PCM_READ_RATE: 270 case OSS_SOUND_PCM_READ_RATE:
271 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 271 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
272 if (error) { 272 if (error) {
273 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 273 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
274 __func__, error)); 274 __func__, error));
275 goto out; 275 goto out;
276 } 276 }
277 idat = GETPRINFO(&tmpinfo, sample_rate); 277 idat = GETPRINFO(&tmpinfo, sample_rate);
278 DPRINTF(("%s: SNDCTL_PCM_READ_RATE < %d\n", __func__, idat)); 278 DPRINTF(("%s: SNDCTL_PCM_READ_RATE < %d\n", __func__, idat));
279 error = copyout(&idat, SCARG(uap, data), sizeof idat); 279 error = copyout(&idat, SCARG(uap, data), sizeof idat);
280 if (error) { 280 if (error) {
281 DPRINTF(("%s: SOUND_PCM_READ_RATE %d = %d\n", 281 DPRINTF(("%s: SOUND_PCM_READ_RATE %d = %d\n",
282 __func__, idat, error)); 282 __func__, idat, error));
283 goto out; 283 goto out;
284 } 284 }
285 break; 285 break;
286 case OSS_SNDCTL_DSP_STEREO: 286 case OSS_SNDCTL_DSP_STEREO:
287 AUDIO_INITINFO(&tmpinfo); 287 AUDIO_INITINFO(&tmpinfo);
288 error = copyin(SCARG(uap, data), &idat, sizeof idat); 288 error = copyin(SCARG(uap, data), &idat, sizeof idat);
289 if (error) { 289 if (error) {
290 DPRINTF(("%s: SNDCTL_DSP_STEREO %d\n", 290 DPRINTF(("%s: SNDCTL_DSP_STEREO %d\n",
291 __func__, error)); 291 __func__, error));
292 goto out; 292 goto out;
293 } 293 }
294 tmpinfo.play.channels = 294 tmpinfo.play.channels =
295 tmpinfo.record.channels = idat ? 2 : 1; 295 tmpinfo.record.channels = idat ? 2 : 1;
296 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 296 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
297 if (error) { 297 if (error) {
298 DPRINTF(("%s: AUDIO_SETINFO %d\n", 298 DPRINTF(("%s: AUDIO_SETINFO %d\n",
299 __func__, error)); 299 __func__, error));
300 goto out; 300 goto out;
301 } 301 }
302 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 302 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
303 if (error) { 303 if (error) {
304 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 304 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
305 __func__, error)); 305 __func__, error));
306 goto out; 306 goto out;
307 } 307 }
308 idat = GETPRINFO(&tmpinfo, channels) - 1; 308 idat = GETPRINFO(&tmpinfo, channels) - 1;
309 error = copyout(&idat, SCARG(uap, data), sizeof idat); 309 error = copyout(&idat, SCARG(uap, data), sizeof idat);
310 if (error) { 310 if (error) {
311 DPRINTF(("%s: SNDCTL_DSP_STEREO %d = %d\n", 311 DPRINTF(("%s: SNDCTL_DSP_STEREO %d = %d\n",
312 __func__, idat, error)); 312 __func__, idat, error));
313 goto out; 313 goto out;
314 } 314 }
315 break; 315 break;
316 case OSS_SNDCTL_DSP_GETBLKSIZE: 316 case OSS_SNDCTL_DSP_GETBLKSIZE:
317 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 317 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
318 if (error) { 318 if (error) {
319 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 319 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
320 __func__, error)); 320 __func__, error));
321 goto out; 321 goto out;
322 } 322 }
323 setblocksize(fp, &tmpinfo); 323 setblocksize(fp, &tmpinfo);
324 idat = tmpinfo.blocksize; 324 idat = tmpinfo.blocksize;
325 DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE < %d\n", 325 DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE < %d\n",
326 __func__, idat)); 326 __func__, idat));
327 error = copyout(&idat, SCARG(uap, data), sizeof idat); 327 error = copyout(&idat, SCARG(uap, data), sizeof idat);
328 if (error) { 328 if (error) {
329 DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE %d = %d\n", 329 DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE %d = %d\n",
330 __func__, idat, error)); 330 __func__, idat, error));
331 goto out; 331 goto out;
332 } 332 }
333 break; 333 break;
334 case OSS_SNDCTL_DSP_SETFMT: 334 case OSS_SNDCTL_DSP_SETFMT:
335 AUDIO_INITINFO(&tmpinfo); 335 AUDIO_INITINFO(&tmpinfo);
336 error = copyin(SCARG(uap, data), &idat, sizeof idat); 336 error = copyin(SCARG(uap, data), &idat, sizeof idat);
337 if (error) { 337 if (error) {
338 DPRINTF(("%s: SNDCTL_DSP_SETFMT %d\n", 338 DPRINTF(("%s: SNDCTL_DSP_SETFMT %d\n",
339 __func__, error)); 339 __func__, error));
340 goto out; 340 goto out;
341 } 341 }
342 switch (idat) { 342 switch (idat) {
343 case OSS_AFMT_MU_LAW: 343 case OSS_AFMT_MU_LAW:
344 tmpinfo.play.precision = 344 tmpinfo.play.precision =
345 tmpinfo.record.precision = 8; 345 tmpinfo.record.precision = 8;
346 tmpinfo.play.encoding = 346 tmpinfo.play.encoding =
347 tmpinfo.record.encoding = AUDIO_ENCODING_ULAW; 347 tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
348 break; 348 break;
349 case OSS_AFMT_A_LAW: 349 case OSS_AFMT_A_LAW:
350 tmpinfo.play.precision = 350 tmpinfo.play.precision =
351 tmpinfo.record.precision = 8; 351 tmpinfo.record.precision = 8;
352 tmpinfo.play.encoding = 352 tmpinfo.play.encoding =
353 tmpinfo.record.encoding = AUDIO_ENCODING_ALAW; 353 tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
354 break; 354 break;
355 case OSS_AFMT_U8: 355 case OSS_AFMT_U8:
356 tmpinfo.play.precision = 356 tmpinfo.play.precision =
357 tmpinfo.record.precision = 8; 357 tmpinfo.record.precision = 8;
358 tmpinfo.play.encoding = 358 tmpinfo.play.encoding =
359 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR; 359 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR;
360 break; 360 break;
361 case OSS_AFMT_S8: 361 case OSS_AFMT_S8:
362 tmpinfo.play.precision = 362 tmpinfo.play.precision =
363 tmpinfo.record.precision = 8; 363 tmpinfo.record.precision = 8;
364 tmpinfo.play.encoding = 364 tmpinfo.play.encoding =
365 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR; 365 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR;
366 break; 366 break;
367 case OSS_AFMT_S16_LE: 367 case OSS_AFMT_S16_LE:
368 tmpinfo.play.precision = 368 tmpinfo.play.precision =
369 tmpinfo.record.precision = 16; 369 tmpinfo.record.precision = 16;
370 tmpinfo.play.encoding = 370 tmpinfo.play.encoding =
371 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 371 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
372 break; 372 break;
373 case OSS_AFMT_S16_BE: 373 case OSS_AFMT_S16_BE:
374 tmpinfo.play.precision = 374 tmpinfo.play.precision =
375 tmpinfo.record.precision = 16; 375 tmpinfo.record.precision = 16;
376 tmpinfo.play.encoding = 376 tmpinfo.play.encoding =
377 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; 377 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
378 break; 378 break;
379 case OSS_AFMT_U16_LE: 379 case OSS_AFMT_U16_LE:
380 tmpinfo.play.precision = 380 tmpinfo.play.precision =
381 tmpinfo.record.precision = 16; 381 tmpinfo.record.precision = 16;
382 tmpinfo.play.encoding = 382 tmpinfo.play.encoding =
383 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE; 383 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE;
384 break; 384 break;
385 case OSS_AFMT_U16_BE: 385 case OSS_AFMT_U16_BE:
386 tmpinfo.play.precision = 386 tmpinfo.play.precision =
387 tmpinfo.record.precision = 16; 387 tmpinfo.record.precision = 16;
388 tmpinfo.play.encoding = 388 tmpinfo.play.encoding =
389 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE; 389 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
390 break; 390 break;
391 case OSS_AFMT_AC3: 391 case OSS_AFMT_AC3:
392 tmpinfo.play.precision = 392 tmpinfo.play.precision =
393 tmpinfo.record.precision = 16; 393 tmpinfo.record.precision = 16;
394 tmpinfo.play.encoding = 394 tmpinfo.play.encoding =
395 tmpinfo.record.encoding = AUDIO_ENCODING_AC3; 395 tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
396 break; 396 break;
397 default: 397 default:
398 DPRINTF(("%s: SNDCTL_DSP_SETFMT bad fmt %d\n", 398 /*
399 __func__, idat)); 399 * OSSv4 specifies that if an invalid format is chosen
400 error = EINVAL; 400 * by an application then a sensible format supported
401 goto out; 401 * by the hardware is returned.
 402 *
 403 * In this case, we pick S16LE since it's reasonably
 404 * assumed to be supported by applications.
 405 */
 406 tmpinfo.play.precision =
 407 tmpinfo.record.precision = 16;
 408 tmpinfo.play.encoding =
 409 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
 410 break;
402 } 411 }
403 DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n", 412 DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n",
404 __func__, idat)); 413 __func__, idat));
405 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 414 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
406 if (error) { 415 if (error) {
407 DPRINTF(("%s: AUDIO_SETINFO %d\n", 416 DPRINTF(("%s: AUDIO_SETINFO %d\n",
408 __func__, error)); 417 __func__, error));
409 goto out; 418 goto out;
410 } 419 }
411 /* FALLTHROUGH */ 420 /* FALLTHROUGH */
412 case OSS_SOUND_PCM_READ_BITS: 421 case OSS_SOUND_PCM_READ_BITS:
413 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 422 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
414 if (error) { 423 if (error) {
415 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 424 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
416 __func__, error)); 425 __func__, error));
417 goto out; 426 goto out;
418 } 427 }
419 encoding = GETPRINFO(&tmpinfo, encoding); 428 encoding = GETPRINFO(&tmpinfo, encoding);
420 precision = GETPRINFO(&tmpinfo, precision); 429 precision = GETPRINFO(&tmpinfo, precision);
421 switch (encoding) { 430 switch (encoding) {
422 case AUDIO_ENCODING_ULAW: 431 case AUDIO_ENCODING_ULAW:
423 idat = OSS_AFMT_MU_LAW; 432 idat = OSS_AFMT_MU_LAW;
424 break; 433 break;
425 case AUDIO_ENCODING_ALAW: 434 case AUDIO_ENCODING_ALAW:
426 idat = OSS_AFMT_A_LAW; 435 idat = OSS_AFMT_A_LAW;
427 break; 436 break;
428 case AUDIO_ENCODING_SLINEAR_LE: 437 case AUDIO_ENCODING_SLINEAR_LE:
429 if (precision == 16) 438 if (precision == 16)
430 idat = OSS_AFMT_S16_LE; 439 idat = OSS_AFMT_S16_LE;
431 else 440 else
432 idat = OSS_AFMT_S8; 441 idat = OSS_AFMT_S8;
433 break; 442 break;
434 case AUDIO_ENCODING_SLINEAR_BE: 443 case AUDIO_ENCODING_SLINEAR_BE:
435 if (precision == 16) 444 if (precision == 16)
436 idat = OSS_AFMT_S16_BE; 445 idat = OSS_AFMT_S16_BE;
437 else 446 else
438 idat = OSS_AFMT_S8; 447 idat = OSS_AFMT_S8;
439 break; 448 break;
440 case AUDIO_ENCODING_ULINEAR_LE: 449 case AUDIO_ENCODING_ULINEAR_LE:
441 if (precision == 16) 450 if (precision == 16)
442 idat = OSS_AFMT_U16_LE; 451 idat = OSS_AFMT_U16_LE;
443 else 452 else
444 idat = OSS_AFMT_U8; 453 idat = OSS_AFMT_U8;
445 break; 454 break;
446 case AUDIO_ENCODING_ULINEAR_BE: 455 case AUDIO_ENCODING_ULINEAR_BE:
447 if (precision == 16) 456 if (precision == 16)
448 idat = OSS_AFMT_U16_BE; 457 idat = OSS_AFMT_U16_BE;
449 else 458 else
450 idat = OSS_AFMT_U8; 459 idat = OSS_AFMT_U8;
451 break; 460 break;
452 case AUDIO_ENCODING_ADPCM: 461 case AUDIO_ENCODING_ADPCM:
453 idat = OSS_AFMT_IMA_ADPCM; 462 idat = OSS_AFMT_IMA_ADPCM;
454 break; 463 break;
455 case AUDIO_ENCODING_AC3: 464 case AUDIO_ENCODING_AC3:
456 idat = OSS_AFMT_AC3; 465 idat = OSS_AFMT_AC3;
457 break; 466 break;
458 default: 467 default:
459 DPRINTF(("%s: SOUND_PCM_READ_BITS bad encoding %d\n", 468 DPRINTF(("%s: SOUND_PCM_READ_BITS bad encoding %d\n",
460 __func__, tmpinfo.play.encoding)); 469 __func__, tmpinfo.play.encoding));
461 error = EINVAL; 470 error = EINVAL;
462 goto out; 471 goto out;
463 } 472 }
464 DPRINTF(("%s: SOUND_PCM_READ_BITS < 0x%x\n", 473 DPRINTF(("%s: SOUND_PCM_READ_BITS < 0x%x\n",
465 __func__, idat)); 474 __func__, idat));
466 error = copyout(&idat, SCARG(uap, data), sizeof idat); 475 error = copyout(&idat, SCARG(uap, data), sizeof idat);
467 if (error) { 476 if (error) {
468 DPRINTF(("%s: SOUND_PCM_READ_BITS %d = %d\n", 477 DPRINTF(("%s: SOUND_PCM_READ_BITS %d = %d\n",
469 __func__, idat, error)); 478 __func__, idat, error));
470 goto out; 479 goto out;
471 } 480 }
472 break; 481 break;
473 case OSS_SNDCTL_DSP_CHANNELS: 482 case OSS_SNDCTL_DSP_CHANNELS:
474 AUDIO_INITINFO(&tmpinfo); 483 AUDIO_INITINFO(&tmpinfo);
475 error = copyin(SCARG(uap, data), &idat, sizeof idat); 484 error = copyin(SCARG(uap, data), &idat, sizeof idat);
476 if (error) { 485 if (error) {
477 DPRINTF(("%s: SNDCTL_DSP_CHANNELS %d\n", 486 DPRINTF(("%s: SNDCTL_DSP_CHANNELS %d\n",
478 __func__, error)); 487 __func__, error));
479 goto out; 488 goto out;
480 } 489 }
481 tmpinfo.play.channels = 490 tmpinfo.play.channels =
482 tmpinfo.record.channels = idat; 491 tmpinfo.record.channels = idat;
483 DPRINTF(("%s: SNDCTL_DSP_CHANNELS > %d\n", __func__, idat)); 492 DPRINTF(("%s: SNDCTL_DSP_CHANNELS > %d\n", __func__, idat));
484 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 493 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
485 if (error) { 494 if (error) {
486 DPRINTF(("%s: AUDIO_SETINFO %d\n", 495 DPRINTF(("%s: AUDIO_SETINFO %d\n",
487 __func__, error)); 496 __func__, error));
488 goto out; 497 goto out;
489 } 498 }
490 /* FALLTHROUGH */ 499 /* FALLTHROUGH */
491 case OSS_SOUND_PCM_READ_CHANNELS: 500 case OSS_SOUND_PCM_READ_CHANNELS:
492 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 501 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
493 if (error) { 502 if (error) {
494 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 503 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
495 __func__, error)); 504 __func__, error));
496 goto out; 505 goto out;
497 } 506 }
498 idat = GETPRINFO(&tmpinfo, channels); 507 idat = GETPRINFO(&tmpinfo, channels);
499 DPRINTF(("%s: SOUND_PCM_READ_CHANNELS < %d\n", __func__, idat)); 508 DPRINTF(("%s: SOUND_PCM_READ_CHANNELS < %d\n", __func__, idat));
500 error = copyout(&idat, SCARG(uap, data), sizeof idat); 509 error = copyout(&idat, SCARG(uap, data), sizeof idat);
501 if (error) { 510 if (error) {
502 DPRINTF(("%s: SOUND_PCM_READ_CHANNELS %d = %d\n", 511 DPRINTF(("%s: SOUND_PCM_READ_CHANNELS %d = %d\n",
503 __func__, idat, error)); 512 __func__, idat, error));
504 goto out; 513 goto out;
505 } 514 }
506 break; 515 break;
507 case OSS_SOUND_PCM_WRITE_FILTER: 516 case OSS_SOUND_PCM_WRITE_FILTER:
508 case OSS_SOUND_PCM_READ_FILTER: 517 case OSS_SOUND_PCM_READ_FILTER:
509 error = EINVAL; /* XXX unimplemented */ 518 error = EINVAL; /* XXX unimplemented */
510 DPRINTF(("%s: SOUND_PCM_{READ,WRITE}_FILTER filter\n", 519 DPRINTF(("%s: SOUND_PCM_{READ,WRITE}_FILTER filter\n",
511 __func__)); 520 __func__));
512 goto out; 521 goto out;
513 case OSS_SNDCTL_DSP_SUBDIVIDE: 522 case OSS_SNDCTL_DSP_SUBDIVIDE:
514 error = copyin(SCARG(uap, data), &idat, sizeof idat); 523 error = copyin(SCARG(uap, data), &idat, sizeof idat);
515 if (error) { 524 if (error) {
516 DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d\n", 525 DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d\n",
517 __func__, error)); 526 __func__, error));
518 goto out; 527 goto out;
519 } 528 }
520 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 529 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
521 if (error) { 530 if (error) {
522 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 531 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
523 __func__, error)); 532 __func__, error));
524 goto out; 533 goto out;
525 } 534 }
526 setblocksize(fp, &tmpinfo); 535 setblocksize(fp, &tmpinfo);
527 if (idat == 0) 536 if (idat == 0)
528 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize; 537 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
529 idat = (tmpinfo.play.buffer_size / idat) & -4; 538 idat = (tmpinfo.play.buffer_size / idat) & -4;
530 AUDIO_INITINFO(&tmpinfo); 539 AUDIO_INITINFO(&tmpinfo);
531 tmpinfo.blocksize = idat; 540 tmpinfo.blocksize = idat;
532 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 541 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
533 if (error) { 542 if (error) {
534 DPRINTF(("%s: AUDIO_SETINFO %d\n", 543 DPRINTF(("%s: AUDIO_SETINFO %d\n",
535 __func__, error)); 544 __func__, error));
536 goto out; 545 goto out;
537 } 546 }
538 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize; 547 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
539 error = copyout(&idat, SCARG(uap, data), sizeof idat); 548 error = copyout(&idat, SCARG(uap, data), sizeof idat);
540 if (error) { 549 if (error) {
541 DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d = %d\n", 550 DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d = %d\n",
542 __func__, idat, error)); 551 __func__, idat, error));
543 goto out; 552 goto out;
544 } 553 }
545 break; 554 break;
546 case OSS_SNDCTL_DSP_SETFRAGMENT: 555 case OSS_SNDCTL_DSP_SETFRAGMENT:
547 AUDIO_INITINFO(&tmpinfo); 556 AUDIO_INITINFO(&tmpinfo);
548 error = copyin(SCARG(uap, data), &idat, sizeof idat); 557 error = copyin(SCARG(uap, data), &idat, sizeof idat);
549 if (error) { 558 if (error) {
550 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT %d\n", 559 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT %d\n",
551 __func__, error)); 560 __func__, error));
552 goto out; 561 goto out;
553 } 562 }
554 if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) { 563 if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) {
555 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT bad ival%d\n", 564 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT bad ival%d\n",
556 __func__, idat)); 565 __func__, idat));
557 error = EINVAL; 566 error = EINVAL;
558 goto out; 567 goto out;
559 } 568 }
560 tmpinfo.blocksize = 1 << (idat & 0xffff); 569 tmpinfo.blocksize = 1 << (idat & 0xffff);
561 tmpinfo.hiwat = (idat >> 16) & 0x7fff; 570 tmpinfo.hiwat = (idat >> 16) & 0x7fff;
562 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT blksize=%d, " 571 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT blksize=%d, "
563 "hiwat=%d\n", __func__, tmpinfo.blocksize, tmpinfo.hiwat)); 572 "hiwat=%d\n", __func__, tmpinfo.blocksize, tmpinfo.hiwat));
564 if (tmpinfo.hiwat == 0) /* 0 means set to max */ 573 if (tmpinfo.hiwat == 0) /* 0 means set to max */
565 tmpinfo.hiwat = 65536; 574 tmpinfo.hiwat = 65536;
566 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 575 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
567 if (error) { 576 if (error) {
568 DPRINTF(("%s: AUDIO_SETINFO %d\n", 577 DPRINTF(("%s: AUDIO_SETINFO %d\n",
569 __func__, error)); 578 __func__, error));
570 goto out; 579 goto out;
571 } 580 }
572 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 581 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
573 if (error) { 582 if (error) {
574 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 583 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
575 __func__, error)); 584 __func__, error));
576 goto out; 585 goto out;
577 } 586 }
578 u = tmpinfo.blocksize; 587 u = tmpinfo.blocksize;
579 for(idat = 0; u > 1; idat++, u >>= 1) 588 for(idat = 0; u > 1; idat++, u >>= 1)
580 ; 589 ;
581 idat |= (tmpinfo.hiwat & 0x7fff) << 16; 590 idat |= (tmpinfo.hiwat & 0x7fff) << 16;
582 error = copyout(&idat, SCARG(uap, data), sizeof idat); 591 error = copyout(&idat, SCARG(uap, data), sizeof idat);
583 if (error) { 592 if (error) {
584 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT %d = %d\n", 593 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT %d = %d\n",
585 __func__, idat, error)); 594 __func__, idat, error));
586 goto out; 595 goto out;
587 } 596 }
588 break; 597 break;
589 case OSS_SNDCTL_DSP_GETFMTS: 598 case OSS_SNDCTL_DSP_GETFMTS:
590 for (idat = 0, tmpenc.index = 0; 599 for (idat = 0, tmpenc.index = 0;
591 ioctlf(fp, AUDIO_GETENC, &tmpenc) == 0; 600 ioctlf(fp, AUDIO_GETENC, &tmpenc) == 0;
592 tmpenc.index++) { 601 tmpenc.index++) {
593 switch(tmpenc.encoding) { 602 switch(tmpenc.encoding) {
594 case AUDIO_ENCODING_ULAW: 603 case AUDIO_ENCODING_ULAW:
595 idat |= OSS_AFMT_MU_LAW; 604 idat |= OSS_AFMT_MU_LAW;
596 break; 605 break;
597 case AUDIO_ENCODING_ALAW: 606 case AUDIO_ENCODING_ALAW:
598 idat |= OSS_AFMT_A_LAW; 607 idat |= OSS_AFMT_A_LAW;
599 break; 608 break;
600 case AUDIO_ENCODING_SLINEAR: 609 case AUDIO_ENCODING_SLINEAR:
601 idat |= OSS_AFMT_S8; 610 idat |= OSS_AFMT_S8;
602 break; 611 break;
603 case AUDIO_ENCODING_SLINEAR_LE: 612 case AUDIO_ENCODING_SLINEAR_LE:
604 if (tmpenc.precision == 16) 613 if (tmpenc.precision == 16)
605 idat |= OSS_AFMT_S16_LE; 614 idat |= OSS_AFMT_S16_LE;
606 else 615 else
607 idat |= OSS_AFMT_S8; 616 idat |= OSS_AFMT_S8;
608 break; 617 break;
609 case AUDIO_ENCODING_SLINEAR_BE: 618 case AUDIO_ENCODING_SLINEAR_BE:
610 if (tmpenc.precision == 16) 619 if (tmpenc.precision == 16)
611 idat |= OSS_AFMT_S16_BE; 620 idat |= OSS_AFMT_S16_BE;
612 else 621 else
613 idat |= OSS_AFMT_S8; 622 idat |= OSS_AFMT_S8;
614 break; 623 break;
615 case AUDIO_ENCODING_ULINEAR: 624 case AUDIO_ENCODING_ULINEAR:
616 idat |= OSS_AFMT_U8; 625 idat |= OSS_AFMT_U8;
617 break; 626 break;
618 case AUDIO_ENCODING_ULINEAR_LE: 627 case AUDIO_ENCODING_ULINEAR_LE:
619 if (tmpenc.precision == 16) 628 if (tmpenc.precision == 16)
620 idat |= OSS_AFMT_U16_LE; 629 idat |= OSS_AFMT_U16_LE;
621 else 630 else
622 idat |= OSS_AFMT_U8; 631 idat |= OSS_AFMT_U8;
623 break; 632 break;
624 case AUDIO_ENCODING_ULINEAR_BE: 633 case AUDIO_ENCODING_ULINEAR_BE:
625 if (tmpenc.precision == 16) 634 if (tmpenc.precision == 16)
626 idat |= OSS_AFMT_U16_BE; 635 idat |= OSS_AFMT_U16_BE;
627 else 636 else
628 idat |= OSS_AFMT_U8; 637 idat |= OSS_AFMT_U8;
629 break; 638 break;
630 case AUDIO_ENCODING_ADPCM: 639 case AUDIO_ENCODING_ADPCM:
631 idat |= OSS_AFMT_IMA_ADPCM; 640 idat |= OSS_AFMT_IMA_ADPCM;
632 break; 641 break;
633 case AUDIO_ENCODING_AC3: 642 case AUDIO_ENCODING_AC3:
634 idat |= OSS_AFMT_AC3; 643 idat |= OSS_AFMT_AC3;
635 break; 644 break;
636 default: 645 default:
637 DPRINTF(("%s: SNDCTL_DSP_GETFMTS unknown %d\n", 646 DPRINTF(("%s: SNDCTL_DSP_GETFMTS unknown %d\n",
638 __func__, tmpenc.encoding)); 647 __func__, tmpenc.encoding));
639 break; 648 break;
640 } 649 }
641 } 650 }
642 DPRINTF(("%s: SNDCTL_DSP_GETFMTS < 0x%x\n", 651 DPRINTF(("%s: SNDCTL_DSP_GETFMTS < 0x%x\n",
643 __func__, idat)); 652 __func__, idat));
644 error = copyout(&idat, SCARG(uap, data), sizeof idat); 653 error = copyout(&idat, SCARG(uap, data), sizeof idat);
645 if (error) { 654 if (error) {
646 DPRINTF(("%s: SNDCTL_DSP_GETFMTS = %x = %d\n", 655 DPRINTF(("%s: SNDCTL_DSP_GETFMTS = %x = %d\n",
647 __func__, idat, error)); 656 __func__, idat, error));
648 goto out; 657 goto out;
649 } 658 }
650 break; 659 break;
651 case OSS_SNDCTL_DSP_GETOSPACE: 660 case OSS_SNDCTL_DSP_GETOSPACE:
652 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 661 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
653 if (error) { 662 if (error) {
654 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 663 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
655 __func__, error)); 664 __func__, error));
656 goto out; 665 goto out;
657 } 666 }
658 setblocksize(fp, &tmpinfo); 667 setblocksize(fp, &tmpinfo);
659 bufinfo.fragsize = tmpinfo.blocksize; 668 bufinfo.fragsize = tmpinfo.blocksize;
660 bufinfo.fragments = tmpinfo.hiwat - 669 bufinfo.fragments = tmpinfo.hiwat -
661 (tmpinfo.play.seek + tmpinfo.blocksize - 1) / 670 (tmpinfo.play.seek + tmpinfo.blocksize - 1) /
662 tmpinfo.blocksize; 671 tmpinfo.blocksize;
663 bufinfo.fragstotal = tmpinfo.hiwat; 672 bufinfo.fragstotal = tmpinfo.hiwat;
664 bufinfo.bytes = 673 bufinfo.bytes =
665 tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek; 674 tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek;
666 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo); 675 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
667 if (error) { 676 if (error) {
668 DPRINTF(("%s: SNDCTL_DSP_GETOSPACE = %d\n", 677 DPRINTF(("%s: SNDCTL_DSP_GETOSPACE = %d\n",
669 __func__, error)); 678 __func__, error));
670 goto out; 679 goto out;
671 } 680 }
672 break; 681 break;
673 case OSS_SNDCTL_DSP_GETISPACE: 682 case OSS_SNDCTL_DSP_GETISPACE:
674 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 683 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
675 if (error) { 684 if (error) {
676 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 685 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
677 __func__, error)); 686 __func__, error));
678 goto out; 687 goto out;
679 } 688 }
680 setblocksize(fp, &tmpinfo); 689 setblocksize(fp, &tmpinfo);
681 bufinfo.fragsize = tmpinfo.blocksize; 690 bufinfo.fragsize = tmpinfo.blocksize;
682 bufinfo.fragments = tmpinfo.record.seek / tmpinfo.blocksize; 691 bufinfo.fragments = tmpinfo.record.seek / tmpinfo.blocksize;
683 bufinfo.fragstotal = 692 bufinfo.fragstotal =
684 tmpinfo.record.buffer_size / tmpinfo.blocksize; 693 tmpinfo.record.buffer_size / tmpinfo.blocksize;
685 bufinfo.bytes = tmpinfo.record.seek; 694 bufinfo.bytes = tmpinfo.record.seek;
686 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo); 695 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
687 if (error) { 696 if (error) {
688 DPRINTF(("%s: SNDCTL_DSP_GETISPACE %d %d %d %d = %d\n", 697 DPRINTF(("%s: SNDCTL_DSP_GETISPACE %d %d %d %d = %d\n",
689 __func__, bufinfo.fragsize, bufinfo.fragments, 698 __func__, bufinfo.fragsize, bufinfo.fragments,
690 bufinfo.fragstotal, bufinfo.bytes, error)); 699 bufinfo.fragstotal, bufinfo.bytes, error));
691 goto out; 700 goto out;
692 } 701 }
693 break; 702 break;
694 case OSS_SNDCTL_DSP_NONBLOCK: 703 case OSS_SNDCTL_DSP_NONBLOCK:
695 idat = 1; 704 idat = 1;
696 error = ioctlf(fp, FIONBIO, &idat); 705 error = ioctlf(fp, FIONBIO, &idat);
697 if (error) { 706 if (error) {
698 DPRINTF(("%s: FIONBIO %d\n", 707 DPRINTF(("%s: FIONBIO %d\n",
699 __func__, error)); 708 __func__, error));
700 goto out; 709 goto out;
701 } 710 }
702 break; 711 break;
703 case OSS_SNDCTL_DSP_GETCAPS: 712 case OSS_SNDCTL_DSP_GETCAPS:
704 error = ioctlf(fp, AUDIO_GETPROPS, &idata); 713 error = ioctlf(fp, AUDIO_GETPROPS, &idata);
705 if (error) { 714 if (error) {
706 DPRINTF(("%s: AUDIO_GETPROPS %d\n", 715 DPRINTF(("%s: AUDIO_GETPROPS %d\n",
707 __func__, error)); 716 __func__, error));
708 goto out; 717 goto out;
709 } 718 }
710 idat = OSS_DSP_CAP_TRIGGER; /* pretend we have trigger */ 719 idat = OSS_DSP_CAP_TRIGGER; /* pretend we have trigger */
711 if (idata & AUDIO_PROP_FULLDUPLEX) 720 if (idata & AUDIO_PROP_FULLDUPLEX)
712 idat |= OSS_DSP_CAP_DUPLEX; 721 idat |= OSS_DSP_CAP_DUPLEX;
713 if (idata & AUDIO_PROP_MMAP) 722 if (idata & AUDIO_PROP_MMAP)
714 idat |= OSS_DSP_CAP_MMAP; 723 idat |= OSS_DSP_CAP_MMAP;
715 DPRINTF(("%s: SNDCL_DSP_GETCAPS %s duplex, %smmap\n", 724 DPRINTF(("%s: SNDCL_DSP_GETCAPS %s duplex, %smmap\n",
716 __func__, (idat & OSS_DSP_CAP_DUPLEX) ? "full" : "half", 725 __func__, (idat & OSS_DSP_CAP_DUPLEX) ? "full" : "half",
717 (idat & OSS_DSP_CAP_MMAP) ? "" : "no ")); 726 (idat & OSS_DSP_CAP_MMAP) ? "" : "no "));
718 error = copyout(&idat, SCARG(uap, data), sizeof idat); 727 error = copyout(&idat, SCARG(uap, data), sizeof idat);
719 if (error) { 728 if (error) {
720 DPRINTF(("%s: SNDCTL_DSP_GETCAPS %x = %d\n", __func__, 729 DPRINTF(("%s: SNDCTL_DSP_GETCAPS %x = %d\n", __func__,
721 idat, error)); 730 idat, error));
722 goto out; 731 goto out;
723 } 732 }
724 break; 733 break;
725#if 0 734#if 0
726 case OSS_SNDCTL_DSP_GETTRIGGER: 735 case OSS_SNDCTL_DSP_GETTRIGGER:
727 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 736 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
728 if (error) { 737 if (error) {
729 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 738 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
730 __func__, error)); 739 __func__, error));
731 goto out; 740 goto out;
732 } 741 }
733 idat = (tmpinfo.play.pause ? 0 : OSS_PCM_ENABLE_OUTPUT) | 742 idat = (tmpinfo.play.pause ? 0 : OSS_PCM_ENABLE_OUTPUT) |
734 (tmpinfo.record.pause ? 0 : OSS_PCM_ENABLE_INPUT); 743 (tmpinfo.record.pause ? 0 : OSS_PCM_ENABLE_INPUT);
735 error = copyout(&idat, SCARG(uap, data), sizeof idat); 744 error = copyout(&idat, SCARG(uap, data), sizeof idat);
736 if (error) { 745 if (error) {
737 DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n", 746 DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n",
738 __func__, idat, error)); 747 __func__, idat, error));
739 goto out; 748 goto out;
740 } 749 }
741 break; 750 break;
742 case OSS_SNDCTL_DSP_SETTRIGGER: 751 case OSS_SNDCTL_DSP_SETTRIGGER:
743 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo, p); 752 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo, p);
744 if (error) { 753 if (error) {
745 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 754 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
746 __func__, error)); 755 __func__, error));
747 goto out; 756 goto out;
748 } 757 }
749 error = copyin(SCARG(uap, data), &idat, sizeof idat); 758 error = copyin(SCARG(uap, data), &idat, sizeof idat);
750 if (error) { 759 if (error) {
751 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 760 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
752 __func__, error)); 761 __func__, error));
753 goto out; 762 goto out;
754 } 763 }
755 tmpinfo.play.pause = (idat & OSS_PCM_ENABLE_OUTPUT) == 0; 764 tmpinfo.play.pause = (idat & OSS_PCM_ENABLE_OUTPUT) == 0;
756 tmpinfo.record.pause = (idat & OSS_PCM_ENABLE_INPUT) == 0; 765 tmpinfo.record.pause = (idat & OSS_PCM_ENABLE_INPUT) == 0;
757 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 766 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
758 if (error) { 767 if (error) {
759 DPRINTF(("%s: AUDIO_SETINFO %d\n", 768 DPRINTF(("%s: AUDIO_SETINFO %d\n",
760 __func__, error)); 769 __func__, error));
761 goto out; 770 goto out;
762 } 771 }
763 error = copyout(&idat, SCARG(uap, data), sizeof idat); 772 error = copyout(&idat, SCARG(uap, data), sizeof idat);
764 if (error) { 773 if (error) {
765 DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n", 774 DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n",
766 __func__, idat, error)); 775 __func__, idat, error));
767 goto out; 776 goto out;
768 } 777 }
769 break; 778 break;
770#else 779#else
771 case OSS_SNDCTL_DSP_GETTRIGGER: 780 case OSS_SNDCTL_DSP_GETTRIGGER:
772 case OSS_SNDCTL_DSP_SETTRIGGER: 781 case OSS_SNDCTL_DSP_SETTRIGGER:
773 /* XXX Do nothing for now. */ 782 /* XXX Do nothing for now. */
774 idat = OSS_PCM_ENABLE_OUTPUT; 783 idat = OSS_PCM_ENABLE_OUTPUT;
775 error = copyout(&idat, SCARG(uap, data), sizeof idat); 784 error = copyout(&idat, SCARG(uap, data), sizeof idat);
776 if (error) { 785 if (error) {
777 DPRINTF(("%s: SNDCTL_DSP_{GET,SET}RIGGER %x = %d\n", 786 DPRINTF(("%s: SNDCTL_DSP_{GET,SET}RIGGER %x = %d\n",
778 __func__, idat, error)); 787 __func__, idat, error));
779 goto out; 788 goto out;
780 } 789 }
781 break; 790 break;
782#endif 791#endif
783 case OSS_SNDCTL_DSP_GETIPTR: 792 case OSS_SNDCTL_DSP_GETIPTR:
784 error = ioctlf(fp, AUDIO_GETIOFFS, &tmpoffs); 793 error = ioctlf(fp, AUDIO_GETIOFFS, &tmpoffs);
785 if (error) { 794 if (error) {
786 DPRINTF(("%s: AUDIO_GETIOFFS %d\n", 795 DPRINTF(("%s: AUDIO_GETIOFFS %d\n",
787 __func__, error)); 796 __func__, error));
788 goto out; 797 goto out;
789 } 798 }
790 cntinfo.bytes = tmpoffs.samples; 799 cntinfo.bytes = tmpoffs.samples;
791 cntinfo.blocks = tmpoffs.deltablks; 800 cntinfo.blocks = tmpoffs.deltablks;
792 cntinfo.ptr = tmpoffs.offset; 801 cntinfo.ptr = tmpoffs.offset;
793 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo); 802 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
794 if (error) { 803 if (error) {
795 DPRINTF(("%s: SNDCTL_DSP_GETIPTR %d\n", 804 DPRINTF(("%s: SNDCTL_DSP_GETIPTR %d\n",
796 __func__, error)); 805 __func__, error));
797 goto out; 806 goto out;
798 } 807 }
799 break; 808 break;
800 case OSS_SNDCTL_DSP_GETOPTR: 809 case OSS_SNDCTL_DSP_GETOPTR:
801 error = ioctlf(fp, AUDIO_GETOOFFS, &tmpoffs); 810 error = ioctlf(fp, AUDIO_GETOOFFS, &tmpoffs);
802 if (error) { 811 if (error) {
803 DPRINTF(("%s: AUDIO_GETOOFFS %d\n", 812 DPRINTF(("%s: AUDIO_GETOOFFS %d\n",
804 __func__, error)); 813 __func__, error));
805 goto out; 814 goto out;
806 } 815 }
807 cntinfo.bytes = tmpoffs.samples; 816 cntinfo.bytes = tmpoffs.samples;
808 cntinfo.blocks = tmpoffs.deltablks; 817 cntinfo.blocks = tmpoffs.deltablks;
809 cntinfo.ptr = tmpoffs.offset; 818 cntinfo.ptr = tmpoffs.offset;
810 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo); 819 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
811 if (error) { 820 if (error) {
812 DPRINTF(("%s: SNDCTL_DSP_GETOPTR %d\n", 821 DPRINTF(("%s: SNDCTL_DSP_GETOPTR %d\n",
813 __func__, error)); 822 __func__, error));
814 goto out; 823 goto out;
815 } 824 }
816 break; 825 break;
817 case OSS_SNDCTL_DSP_SETDUPLEX: 826 case OSS_SNDCTL_DSP_SETDUPLEX:
818 idat = 1; 827 idat = 1;
819 error = ioctlf(fp, AUDIO_SETFD, &idat); 828 error = ioctlf(fp, AUDIO_SETFD, &idat);
820 if (error) { 829 if (error) {
821 DPRINTF(("%s: AUDIO_SETFD %d = %d\n", 830 DPRINTF(("%s: AUDIO_SETFD %d = %d\n",
822 __func__, idat, error)); 831 __func__, idat, error));
823 goto out; 832 goto out;
824 } 833 }
825 break; 834 break;
826 case OSS_SNDCTL_DSP_MAPINBUF: 835 case OSS_SNDCTL_DSP_MAPINBUF:
827 DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPINBUF\n", 836 DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPINBUF\n",
828 __func__)); 837 __func__));
829 error = EINVAL; 838 error = EINVAL;
830 goto out; 839 goto out;
831 case OSS_SNDCTL_DSP_MAPOUTBUF: 840 case OSS_SNDCTL_DSP_MAPOUTBUF:
832 DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPOUTBUF\n", 841 DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPOUTBUF\n",
833 __func__)); 842 __func__));
834 error = EINVAL; 843 error = EINVAL;
835 goto out; 844 goto out;
836 case OSS_SNDCTL_DSP_SETSYNCRO: 845 case OSS_SNDCTL_DSP_SETSYNCRO:
837 DPRINTF(("%s: Unimplemented SNDCTL_DSP_GETSYNCHRO\n", 846 DPRINTF(("%s: Unimplemented SNDCTL_DSP_GETSYNCHRO\n",
838 __func__)); 847 __func__));
839 error = EINVAL; 848 error = EINVAL;
840 goto out; 849 goto out;
841 case OSS_SNDCTL_DSP_GETODELAY: 850 case OSS_SNDCTL_DSP_GETODELAY:
842 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 851 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
843 if (error) { 852 if (error) {
844 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n", 853 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
845 __func__, error)); 854 __func__, error));
846 goto out; 855 goto out;
847 } 856 }
848 idat = tmpinfo.play.seek + tmpinfo.blocksize / 2; 857 idat = tmpinfo.play.seek + tmpinfo.blocksize / 2;
849 error = copyout(&idat, SCARG(uap, data), sizeof idat); 858 error = copyout(&idat, SCARG(uap, data), sizeof idat);
850 if (error) { 859 if (error) {
851 DPRINTF(("%s: SNDCTL_DSP_GETODELAY %d\n", 860 DPRINTF(("%s: SNDCTL_DSP_GETODELAY %d\n",
852 __func__, error)); 861 __func__, error));
853 goto out; 862 goto out;
854 } 863 }
855 break; 864 break;
856 case OSS_SNDCTL_DSP_PROFILE: 865 case OSS_SNDCTL_DSP_PROFILE:
857 /* This gives just a hint to the driver, 866 /* This gives just a hint to the driver,
858 * implementing it as a NOP is ok 867 * implementing it as a NOP is ok
859 */ 868 */
860 DPRINTF(("%s: SNDCTL_DSP_PROFILE\n", __func__)); 869 DPRINTF(("%s: SNDCTL_DSP_PROFILE\n", __func__));
861 break; 870 break;
862 default: 871 default:
863 DPRINTF(("%s: Unimplemented 0x%lx\n", __func__, com)); 872 DPRINTF(("%s: Unimplemented 0x%lx\n", __func__, com));
864 error = EINVAL; 873 error = EINVAL;
865 goto out; 874 goto out;
866 } 875 }
867 876
868 out: 877 out:
869 fd_putfile(SCARG(uap, fd)); 878 fd_putfile(SCARG(uap, fd));
870 return error; 879 return error;
871} 880}
872 881
873/* If the NetBSD mixer device should have more than 32 devices 882/* If the NetBSD mixer device should have more than 32 devices
874 * some will not be available to Linux */ 883 * some will not be available to Linux */
875#define NETBSD_MAXDEVS 64 884#define NETBSD_MAXDEVS 64
876struct audiodevinfo { 885struct audiodevinfo {
877 int done; 886 int done;
878 dev_t dev; 887 dev_t dev;
879 int16_t devmap[OSS_SOUND_MIXER_NRDEVICES], 888 int16_t devmap[OSS_SOUND_MIXER_NRDEVICES],
880 rdevmap[NETBSD_MAXDEVS]; 889 rdevmap[NETBSD_MAXDEVS];
881 char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN]; 890 char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN];
882 int enum2opaque[NETBSD_MAXDEVS]; 891 int enum2opaque[NETBSD_MAXDEVS];
883 u_long devmask, recmask, stereomask; 892 u_long devmask, recmask, stereomask;
884 u_long caps, source; 893 u_long caps, source;
885}; 894};
886 895
887static int 896static int
888opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq) 897opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq)
889{ 898{
890 int i, o; 899 int i, o;
891 900
892 for (i = 0; i < NETBSD_MAXDEVS; i++) { 901 for (i = 0; i < NETBSD_MAXDEVS; i++) {
893 o = di->enum2opaque[i]; 902 o = di->enum2opaque[i];
894 if (o == opq) 903 if (o == opq)
895 break; 904 break;
896 if (o == -1 && label != NULL && 905 if (o == -1 && label != NULL &&
897 !strncmp(di->names[i], label->name, sizeof di->names[i])) { 906 !strncmp(di->names[i], label->name, sizeof di->names[i])) {
898 di->enum2opaque[i] = opq; 907 di->enum2opaque[i] = opq;
899 break; 908 break;
900 } 909 }
901 } 910 }
902 if (i >= NETBSD_MAXDEVS) 911 if (i >= NETBSD_MAXDEVS)
903 i = -1; 912 i = -1;
904 /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/ 913 /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/
905 return (i); 914 return (i);
906} 915}
907 916
908static int 917static int
909enum_to_ord(struct audiodevinfo *di, int enm) 918enum_to_ord(struct audiodevinfo *di, int enm)
910{ 919{
911 if (enm >= NETBSD_MAXDEVS) 920 if (enm >= NETBSD_MAXDEVS)
912 return (-1); 921 return (-1);
913 922
914 /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/ 923 /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/
915 return (di->enum2opaque[enm]); 924 return (di->enum2opaque[enm]);
916} 925}
917 926
918static int 927static int
919enum_to_mask(struct audiodevinfo *di, int enm) 928enum_to_mask(struct audiodevinfo *di, int enm)
920{ 929{
921 int m; 930 int m;
922 if (enm >= NETBSD_MAXDEVS) 931 if (enm >= NETBSD_MAXDEVS)
923 return (0); 932 return (0);
924 933
925 m = di->enum2opaque[enm]; 934 m = di->enum2opaque[enm];
926 if (m == -1) 935 if (m == -1)
927 m = 0; 936 m = 0;
928 /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/ 937 /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/
929 return (m); 938 return (m);
930} 939}
931 940
932/* 941/*
933 * Collect the audio device information to allow faster 942 * Collect the audio device information to allow faster
934 * emulation of the Linux mixer ioctls. Cache the information 943 * emulation of the Linux mixer ioctls. Cache the information
935 * to eliminate the overhead of repeating all the ioctls needed 944 * to eliminate the overhead of repeating all the ioctls needed
936 * to collect the information. 945 * to collect the information.
937 */ 946 */
938static struct audiodevinfo * 947static struct audiodevinfo *
939getdevinfo(file_t *fp) 948getdevinfo(file_t *fp)
940{ 949{
941 mixer_devinfo_t mi; 950 mixer_devinfo_t mi;
942 int i, j, e; 951 int i, j, e;
943 static const struct { 952 static const struct {
944 const char *name; 953 const char *name;
945 int code; 954 int code;
946 } *dp, devs[] = { 955 } *dp, devs[] = {
947 { AudioNmicrophone, OSS_SOUND_MIXER_MIC }, 956 { AudioNmicrophone, OSS_SOUND_MIXER_MIC },
948 { AudioNline, OSS_SOUND_MIXER_LINE }, 957 { AudioNline, OSS_SOUND_MIXER_LINE },
949 { AudioNcd, OSS_SOUND_MIXER_CD }, 958 { AudioNcd, OSS_SOUND_MIXER_CD },
950 { AudioNdac, OSS_SOUND_MIXER_PCM }, 959 { AudioNdac, OSS_SOUND_MIXER_PCM },
951 { AudioNaux, OSS_SOUND_MIXER_LINE1 }, 960 { AudioNaux, OSS_SOUND_MIXER_LINE1 },
952 { AudioNrecord, OSS_SOUND_MIXER_IMIX }, 961 { AudioNrecord, OSS_SOUND_MIXER_IMIX },
953 { AudioNmaster, OSS_SOUND_MIXER_VOLUME }, 962 { AudioNmaster, OSS_SOUND_MIXER_VOLUME },
954 { AudioNtreble, OSS_SOUND_MIXER_TREBLE }, 963 { AudioNtreble, OSS_SOUND_MIXER_TREBLE },
955 { AudioNbass, OSS_SOUND_MIXER_BASS }, 964 { AudioNbass, OSS_SOUND_MIXER_BASS },
956 { AudioNspeaker, OSS_SOUND_MIXER_SPEAKER }, 965 { AudioNspeaker, OSS_SOUND_MIXER_SPEAKER },
957/* { AudioNheadphone, ?? },*/ 966/* { AudioNheadphone, ?? },*/
958 { AudioNoutput, OSS_SOUND_MIXER_OGAIN }, 967 { AudioNoutput, OSS_SOUND_MIXER_OGAIN },
959 { AudioNinput, OSS_SOUND_MIXER_IGAIN }, 968 { AudioNinput, OSS_SOUND_MIXER_IGAIN },
960/* { AudioNmaster, OSS_SOUND_MIXER_SPEAKER },*/ 969/* { AudioNmaster, OSS_SOUND_MIXER_SPEAKER },*/
961/* { AudioNstereo, ?? },*/ 970/* { AudioNstereo, ?? },*/
962/* { AudioNmono, ?? },*/ 971/* { AudioNmono, ?? },*/
963 { AudioNfmsynth, OSS_SOUND_MIXER_SYNTH }, 972 { AudioNfmsynth, OSS_SOUND_MIXER_SYNTH },
964/* { AudioNwave, OSS_SOUND_MIXER_PCM },*/ 973/* { AudioNwave, OSS_SOUND_MIXER_PCM },*/
965 { AudioNmidi, OSS_SOUND_MIXER_SYNTH }, 974 { AudioNmidi, OSS_SOUND_MIXER_SYNTH },
966/* { AudioNmixerout, ?? },*/ 975/* { AudioNmixerout, ?? },*/
967 { 0, -1 } 976 { 0, -1 }
968 }; 977 };
969 int (*ioctlf)(file_t *, u_long, void *) = fp->f_ops->fo_ioctl; 978 int (*ioctlf)(file_t *, u_long, void *) = fp->f_ops->fo_ioctl;
970 struct vnode *vp; 979 struct vnode *vp;
971 struct vattr va; 980 struct vattr va;
972 static struct audiodevinfo devcache; 981 static struct audiodevinfo devcache;
973 struct audiodevinfo *di = &devcache; 982 struct audiodevinfo *di = &devcache;
974 int error, mlen, dlen; 983 int error, mlen, dlen;
975 984
976 /* 985 /*
977 * Figure out what device it is so we can check if the 986 * Figure out what device it is so we can check if the
978 * cached data is valid. 987 * cached data is valid.
979 */ 988 */
980 vp = fp->f_vnode; 989 vp = fp->f_vnode;
981 if (vp->v_type != VCHR) 990 if (vp->v_type != VCHR)
982 return 0; 991 return 0;
983 vn_lock(vp, LK_SHARED | LK_RETRY); 992 vn_lock(vp, LK_SHARED | LK_RETRY);
984 error = VOP_GETATTR(vp, &va, kauth_cred_get()); 993 error = VOP_GETATTR(vp, &va, kauth_cred_get());
985 VOP_UNLOCK(vp); 994 VOP_UNLOCK(vp);
986 if (error) 995 if (error)
987 return 0; 996 return 0;
988 if (di->done && di->dev == va.va_rdev) 997 if (di->done && di->dev == va.va_rdev)
989 return di; 998 return di;
990 999
991 di->done = 1; 1000 di->done = 1;
992 di->dev = va.va_rdev; 1001 di->dev = va.va_rdev;
993 di->devmask = 0; 1002 di->devmask = 0;
994 di->recmask = 0; 1003 di->recmask = 0;
995 di->stereomask = 0; 1004 di->stereomask = 0;
996 di->source = ~0; 1005 di->source = ~0;
997 di->caps = 0; 1006 di->caps = 0;
998 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) 1007 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
999 di->devmap[i] = -1; 1008 di->devmap[i] = -1;
1000 for(i = 0; i < NETBSD_MAXDEVS; i++) { 1009 for(i = 0; i < NETBSD_MAXDEVS; i++) {
1001 di->rdevmap[i] = -1; 1010 di->rdevmap[i] = -1;
1002 di->names[i][0] = '\0'; 1011 di->names[i][0] = '\0';
1003 di->enum2opaque[i] = -1; 1012 di->enum2opaque[i] = -1;
1004 } 1013 }
1005 for(i = 0; i < NETBSD_MAXDEVS; i++) { 1014 for(i = 0; i < NETBSD_MAXDEVS; i++) {
1006 mi.index = i; 1015 mi.index = i;
1007 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, &mi) != 0) 1016 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, &mi) != 0)
1008 break; 1017 break;
1009 switch(mi.type) { 1018 switch(mi.type) {
1010 case AUDIO_MIXER_VALUE: 1019 case AUDIO_MIXER_VALUE:
1011 for(dp = devs; dp->name; dp++) { 1020 for(dp = devs; dp->name; dp++) {
1012 if (strcmp(dp->name, mi.label.name) == 0) 1021 if (strcmp(dp->name, mi.label.name) == 0)
1013 break; 1022 break;
1014 dlen = strlen(dp->name); 1023 dlen = strlen(dp->name);
1015 mlen = strlen(mi.label.name); 1024 mlen = strlen(mi.label.name);
1016 if (dlen < mlen 1025 if (dlen < mlen
1017 && mi.label.name[mlen-dlen-1] == '.' 1026 && mi.label.name[mlen-dlen-1] == '.'
1018 && strcmp(dp->name, mi.label.name + mlen - dlen) == 0) 1027 && strcmp(dp->name, mi.label.name + mlen - dlen) == 0)
1019 break; 1028 break;
1020 } 1029 }
1021 if (dp->code >= 0) { 1030 if (dp->code >= 0) {
1022 di->devmap[dp->code] = i; 1031 di->devmap[dp->code] = i;
1023 di->rdevmap[i] = dp->code; 1032 di->rdevmap[i] = dp->code;
1024 di->devmask |= 1 << dp->code; 1033 di->devmask |= 1 << dp->code;
1025 if (mi.un.v.num_channels == 2) 1034 if (mi.un.v.num_channels == 2)
1026 di->stereomask |= 1 << dp->code; 1035 di->stereomask |= 1 << dp->code;
1027 strncpy(di->names[i], mi.label.name, 1036 strncpy(di->names[i], mi.label.name,
1028 sizeof di->names[i]); 1037 sizeof di->names[i]);
1029 } 1038 }
1030 break; 1039 break;
1031 } 1040 }
1032 } 1041 }
1033 for(i = 0; i < NETBSD_MAXDEVS; i++) { 1042 for(i = 0; i < NETBSD_MAXDEVS; i++) {
1034 mi.index = i; 1043 mi.index = i;
1035 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, &mi) != 0) 1044 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, &mi) != 0)
1036 break; 1045 break;
1037 if (strcmp(mi.label.name, AudioNsource) != 0) 1046 if (strcmp(mi.label.name, AudioNsource) != 0)
1038 continue; 1047 continue;
1039 di->source = i; 1048 di->source = i;
1040 switch(mi.type) { 1049 switch(mi.type) {
1041 case AUDIO_MIXER_ENUM: 1050 case AUDIO_MIXER_ENUM:
1042 for(j = 0; j < mi.un.e.num_mem; j++) { 1051 for(j = 0; j < mi.un.e.num_mem; j++) {
1043 e = opaque_to_enum(di, 1052 e = opaque_to_enum(di,
1044 &mi.un.e.member[j].label, 1053 &mi.un.e.member[j].label,
1045 mi.un.e.member[j].ord); 1054 mi.un.e.member[j].ord);
1046 if (e >= 0) 1055 if (e >= 0)
1047 di->recmask |= 1 << di->rdevmap[e]; 1056 di->recmask |= 1 << di->rdevmap[e];
1048 } 1057 }
1049 di->caps = OSS_SOUND_CAP_EXCL_INPUT; 1058 di->caps = OSS_SOUND_CAP_EXCL_INPUT;
1050 break; 1059 break;
1051 case AUDIO_MIXER_SET: 1060 case AUDIO_MIXER_SET:
1052 for(j = 0; j < mi.un.s.num_mem; j++) { 1061 for(j = 0; j < mi.un.s.num_mem; j++) {
1053 e = opaque_to_enum(di, 1062 e = opaque_to_enum(di,
1054 &mi.un.s.member[j].label, 1063 &mi.un.s.member[j].label,
1055 mi.un.s.member[j].mask); 1064 mi.un.s.member[j].mask);
1056 if (e >= 0) 1065 if (e >= 0)
1057 di->recmask |= 1 << di->rdevmap[e]; 1066 di->recmask |= 1 << di->rdevmap[e];
1058 } 1067 }
1059 break; 1068 break;
1060 } 1069 }
1061 } 1070 }
1062 return di; 1071 return di;
1063} 1072}
1064 1073
1065int 1074int
1066oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_t *retval) 1075oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_t *retval)
1067{ 1076{
1068 /* { 1077 /* {
1069 syscallarg(int) fd; 1078 syscallarg(int) fd;
1070 syscallarg(u_long) com; 1079 syscallarg(u_long) com;
1071 syscallarg(void *) data; 1080 syscallarg(void *) data;
1072 } */ 1081 } */
1073 file_t *fp; 1082 file_t *fp;
1074 u_long com; 1083 u_long com;
1075 struct audiodevinfo *di; 1084 struct audiodevinfo *di;
1076 mixer_ctrl_t mc; 1085 mixer_ctrl_t mc;
1077 struct oss_mixer_info omi; 1086 struct oss_mixer_info omi;
1078 struct audio_device adev; 1087 struct audio_device adev;
1079 int idat; 1088 int idat;
1080 int i; 1089 int i;
1081 int error; 1090 int error;
1082 int l, r, n, e; 1091 int l, r, n, e;
1083 int (*ioctlf)(file_t *, u_long, void *); 1092 int (*ioctlf)(file_t *, u_long, void *);
1084 1093
1085 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) 1094 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
1086 return error; 1095 return error;
1087 1096
1088 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 1097 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
1089 error = EBADF; 1098 error = EBADF;
1090 goto out; 1099 goto out;
1091 } 1100 }
1092 1101
1093 com = SCARG(uap, com); 1102 com = SCARG(uap, com);
1094 DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com))); 1103 DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com)));
1095 1104
1096 retval[0] = 0; 1105 retval[0] = 0;
1097 1106
1098 di = getdevinfo(fp); 1107 di = getdevinfo(fp);
1099 if (di == 0) { 1108 if (di == 0) {
1100 error = EINVAL; 1109 error = EINVAL;
1101 goto out; 1110 goto out;
1102 } 1111 }
1103 1112
1104 ioctlf = fp->f_ops->fo_ioctl; 1113 ioctlf = fp->f_ops->fo_ioctl;
1105 switch (com) { 1114 switch (com) {
1106 case OSS_GET_VERSION: 1115 case OSS_GET_VERSION:
1107 idat = OSS_SOUND_VERSION; 1116 idat = OSS_SOUND_VERSION;
1108 break; 1117 break;
1109 case OSS_SOUND_MIXER_INFO: 1118 case OSS_SOUND_MIXER_INFO:
1110 case OSS_SOUND_OLD_MIXER_INFO: 1119 case OSS_SOUND_OLD_MIXER_INFO:
1111 error = ioctlf(fp, AUDIO_GETDEV, &adev); 1120 error = ioctlf(fp, AUDIO_GETDEV, &adev);
1112 if (error) { 1121 if (error) {
1113 DPRINTF(("%s: AUDIO_GETDEV %d\n", 1122 DPRINTF(("%s: AUDIO_GETDEV %d\n",
1114 __func__, error)); 1123 __func__, error));
1115 goto out; 1124 goto out;
1116 } 1125 }
1117 omi.modify_counter = 1; 1126 omi.modify_counter = 1;
1118 strncpy(omi.id, adev.name, sizeof omi.id); 1127 strncpy(omi.id, adev.name, sizeof omi.id);
1119 strncpy(omi.name, adev.name, sizeof omi.name); 1128 strncpy(omi.name, adev.name, sizeof omi.name);
1120 error = copyout(&omi, SCARG(uap, data), OSS_IOCTL_SIZE(com)); 1129 error = copyout(&omi, SCARG(uap, data), OSS_IOCTL_SIZE(com));
1121 if (error) { 1130 if (error) {
1122 DPRINTF(("%s: OSS_SOUND_MIXER_INFO %d\n", 1131 DPRINTF(("%s: OSS_SOUND_MIXER_INFO %d\n",
1123 __func__, error)); 1132 __func__, error));
1124 goto out; 1133 goto out;
1125 } 1134 }
1126 break; 1135 break;
1127 case OSS_SOUND_MIXER_READ_RECSRC: 1136 case OSS_SOUND_MIXER_READ_RECSRC:
1128 if (di->source == (u_long)-1) { 1137 if (di->source == (u_long)-1) {
1129 DPRINTF(("%s: OSS_SOUND_MIXER_READ_RECSRC bad source\n", 1138 DPRINTF(("%s: OSS_SOUND_MIXER_READ_RECSRC bad source\n",
1130 __func__)); 1139 __func__));
1131 error = EINVAL; 1140 error = EINVAL;
1132 goto out; 1141 goto out;
1133 } 1142 }
1134 mc.dev = di->source; 1143 mc.dev = di->source;
1135 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) { 1144 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
1136 mc.type = AUDIO_MIXER_ENUM; 1145 mc.type = AUDIO_MIXER_ENUM;
1137 error = ioctlf(fp, AUDIO_MIXER_READ, &mc); 1146 error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
1138 if (error) { 1147 if (error) {
1139 DPRINTF(("%s: AUDIO_MIXER_READ %d\n", 1148 DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
1140 __func__, error)); 1149 __func__, error));
1141 goto out; 1150 goto out;
1142 } 1151 }
1143 e = opaque_to_enum(di, NULL, mc.un.ord); 1152 e = opaque_to_enum(di, NULL, mc.un.ord);
1144 if (e >= 0) 1153 if (e >= 0)
1145 idat = 1 << di->rdevmap[e]; 1154 idat = 1 << di->rdevmap[e];
1146 } else { 1155 } else {
1147 mc.type = AUDIO_MIXER_SET; 1156 mc.type = AUDIO_MIXER_SET;
1148 error = ioctlf(fp, AUDIO_MIXER_READ, &mc); 1157 error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
1149 if (error) { 1158 if (error) {
1150 DPRINTF(("%s: AUDIO_MIXER_READ %d\n", 1159 DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
1151 __func__, error)); 1160 __func__, error));
1152 goto out; 1161 goto out;
1153 } 1162 }
1154 e = opaque_to_enum(di, NULL, mc.un.mask); 1163 e = opaque_to_enum(di, NULL, mc.un.mask);
1155 if (e >= 0) 1164 if (e >= 0)
1156 idat = 1 << di->rdevmap[e]; 1165 idat = 1 << di->rdevmap[e];
1157 } 1166 }
1158 break; 1167 break;
1159 case OSS_SOUND_MIXER_READ_DEVMASK: 1168 case OSS_SOUND_MIXER_READ_DEVMASK:
1160 idat = di->devmask; 1169 idat = di->devmask;
1161 break; 1170 break;
1162 case OSS_SOUND_MIXER_READ_RECMASK: 1171 case OSS_SOUND_MIXER_READ_RECMASK:
1163 idat = di->recmask; 1172 idat = di->recmask;
1164 break; 1173 break;
1165 case OSS_SOUND_MIXER_READ_STEREODEVS: 1174 case OSS_SOUND_MIXER_READ_STEREODEVS:
1166 idat = di->stereomask; 1175 idat = di->stereomask;
1167 break; 1176 break;
1168 case OSS_SOUND_MIXER_READ_CAPS: 1177 case OSS_SOUND_MIXER_READ_CAPS:
1169 idat = di->caps; 1178 idat = di->caps;
1170 break; 1179 break;
1171 case OSS_SOUND_MIXER_WRITE_RECSRC: 1180 case OSS_SOUND_MIXER_WRITE_RECSRC:
1172 case OSS_SOUND_MIXER_WRITE_R_RECSRC: 1181 case OSS_SOUND_MIXER_WRITE_R_RECSRC:
1173 if (di->source == (u_long)-1) { 1182 if (di->source == (u_long)-1) {
1174 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC bad " 1183 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC bad "
1175 "source\n", __func__)); 1184 "source\n", __func__));
1176 error = EINVAL; 1185 error = EINVAL;
1177 goto out; 1186 goto out;
1178 } 1187 }
1179 mc.dev = di->source; 1188 mc.dev = di->source;
1180 error = copyin(SCARG(uap, data), &idat, sizeof idat); 1189 error = copyin(SCARG(uap, data), &idat, sizeof idat);
1181 if (error) { 1190 if (error) {
1182 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC %d\n", 1191 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC %d\n",
1183 __func__, error)); 1192 __func__, error));
1184 goto out; 1193 goto out;
1185 } 1194 }
1186 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) { 1195 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
1187 mc.type = AUDIO_MIXER_ENUM; 1196 mc.type = AUDIO_MIXER_ENUM;
1188 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) 1197 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
1189 if (idat & (1 << i)) 1198 if (idat & (1 << i))
1190 break; 1199 break;
1191 if (i >= OSS_SOUND_MIXER_NRDEVICES || 1200 if (i >= OSS_SOUND_MIXER_NRDEVICES ||
1192 di->devmap[i] == -1) { 1201 di->devmap[i] == -1) {
1193 error = EINVAL; 1202 error = EINVAL;
1194 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC " 1203 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC "
1195 "bad index %d\n", __func__, i)); 1204 "bad index %d\n", __func__, i));
1196 goto out; 1205 goto out;
1197 } 1206 }
1198 mc.un.ord = enum_to_ord(di, di->devmap[i]); 1207 mc.un.ord = enum_to_ord(di, di->devmap[i]);
1199 } else { 1208 } else {
1200 mc.type = AUDIO_MIXER_SET; 1209 mc.type = AUDIO_MIXER_SET;
1201 mc.un.mask = 0; 1210 mc.un.mask = 0;
1202 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) { 1211 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) {
1203 if (idat & (1 << i)) { 1212 if (idat & (1 << i)) {
1204 if (di->devmap[i] == -1) { 1213 if (di->devmap[i] == -1) {
1205 DPRINTF(("%s: OSS_SOUND_MIXER_" 1214 DPRINTF(("%s: OSS_SOUND_MIXER_"
1206 "WRITE_RECSRC bad devmap " 1215 "WRITE_RECSRC bad devmap "
1207 "%d\n", __func__, i)); 1216 "%d\n", __func__, i));
1208 error = EINVAL; 1217 error = EINVAL;
1209 goto out; 1218 goto out;
1210 } 1219 }
1211 mc.un.mask |= enum_to_mask(di, 1220 mc.un.mask |= enum_to_mask(di,
1212 di->devmap[i]); 1221 di->devmap[i]);
1213 } 1222 }
1214 } 1223 }
1215 } 1224 }
1216 error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc); 1225 error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc);
1217 if (error) { 1226 if (error) {
1218 DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n", 1227 DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n",
1219 __func__, error)); 1228 __func__, error));
1220 goto out; 1229 goto out;
1221 } 1230 }
1222 goto out; 1231 goto out;
1223 default: 1232 default:
1224 if (OSS_MIXER_READ(OSS_SOUND_MIXER_FIRST) <= com && 1233 if (OSS_MIXER_READ(OSS_SOUND_MIXER_FIRST) <= com &&
1225 com < OSS_MIXER_READ(OSS_SOUND_MIXER_NRDEVICES)) { 1234 com < OSS_MIXER_READ(OSS_SOUND_MIXER_NRDEVICES)) {
1226 n = OSS_GET_DEV(com); 1235 n = OSS_GET_DEV(com);
1227 if (di->devmap[n] == -1) { 1236 if (di->devmap[n] == -1) {
1228 DPRINTF(("%s: 0x%lx bad devmap %d\n", 1237 DPRINTF(("%s: 0x%lx bad devmap %d\n",
1229 __func__, com, n)); 1238 __func__, com, n));
1230 error = EINVAL; 1239 error = EINVAL;
1231 goto out; 1240 goto out;
1232 } 1241 }
1233 doread: 1242 doread:
1234 mc.dev = di->devmap[n]; 1243 mc.dev = di->devmap[n];
1235 mc.type = AUDIO_MIXER_VALUE; 1244 mc.type = AUDIO_MIXER_VALUE;
1236 mc.un.value.num_channels = di->stereomask & 1245 mc.un.value.num_channels = di->stereomask &
1237 (1 << n) ? 2 : 1; 1246 (1 << n) ? 2 : 1;
1238 error = ioctlf(fp, AUDIO_MIXER_READ, &mc); 1247 error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
1239 if (error) { 1248 if (error) {
1240 DPRINTF(("%s: AUDIO_MIXER_READ %d\n", 1249 DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
1241 __func__, error)); 1250 __func__, error));
1242 goto out; 1251 goto out;
1243 } 1252 }
1244 if (mc.un.value.num_channels != 2) { 1253 if (mc.un.value.num_channels != 2) {
1245 l = r = 1254 l = r =
1246 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO]; 1255 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO];
1247 } else { 1256 } else {
1248 l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 1257 l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1249 r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 1258 r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1250 } 1259 }
1251 idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8); 1260 idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8);
1252 DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n", 1261 DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
1253 __func__, n, di->devmap[n], l, r, idat)); 1262 __func__, n, di->devmap[n], l, r, idat));
1254 break; 1263 break;
1255 } else if ((OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_FIRST) <= com && 1264 } else if ((OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_FIRST) <= com &&
1256 com < OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES)) || 1265 com < OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES)) ||
1257 (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com && 1266 (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
1258 com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES))) { 1267 com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES))) {
1259 n = OSS_GET_DEV(com); 1268 n = OSS_GET_DEV(com);
1260 if (di->devmap[n] == -1) { 1269 if (di->devmap[n] == -1) {
1261 DPRINTF(("%s: 0x%lx bad devmap %d\n", 1270 DPRINTF(("%s: 0x%lx bad devmap %d\n",
1262 __func__, com, n)); 1271 __func__, com, n));
1263 error = EINVAL; 1272 error = EINVAL;
1264 goto out; 1273 goto out;
1265 } 1274 }
1266 error = copyin(SCARG(uap, data), &idat, sizeof idat); 1275 error = copyin(SCARG(uap, data), &idat, sizeof idat);
1267 if (error) { 1276 if (error) {
1268 DPRINTF(("%s: 0x%lx error %d\n", 1277 DPRINTF(("%s: 0x%lx error %d\n",
1269 __func__, com, error)); 1278 __func__, com, error));
1270 goto out; 1279 goto out;
1271 } 1280 }
1272 l = FROM_OSSVOL( idat & 0xff); 1281 l = FROM_OSSVOL( idat & 0xff);
1273 r = FROM_OSSVOL((idat >> 8) & 0xff); 1282 r = FROM_OSSVOL((idat >> 8) & 0xff);
1274 mc.dev = di->devmap[n]; 1283 mc.dev = di->devmap[n];
1275 mc.type = AUDIO_MIXER_VALUE; 1284 mc.type = AUDIO_MIXER_VALUE;
1276 if (di->stereomask & (1 << n)) { 1285 if (di->stereomask & (1 << n)) {
1277 mc.un.value.num_channels = 2; 1286 mc.un.value.num_channels = 2;
1278 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l; 1287 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
1279 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r; 1288 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
1280 } else { 1289 } else {
1281 mc.un.value.num_channels = 1; 1290 mc.un.value.num_channels = 1;
1282 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] = 1291 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1283 (l + r) / 2; 1292 (l + r) / 2;
1284 } 1293 }
1285 DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n", 1294 DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
1286 __func__, n, di->devmap[n], l, r, idat)); 1295 __func__, n, di->devmap[n], l, r, idat));
1287 error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc); 1296 error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc);
1288 if (error) { 1297 if (error) {
1289 DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n", 1298 DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n",
1290 __func__, error)); 1299 __func__, error));
1291 goto out; 1300 goto out;
1292 } 1301 }
1293 if (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com && 1302 if (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
1294 com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES)) { 1303 com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES)) {
1295 error = 0; 1304 error = 0;
1296 goto out; 1305 goto out;
1297 } 1306 }
1298 goto doread; 1307 goto doread;
1299 } else { 1308 } else {
1300 DPRINTF(("%s: Unknown mixer ioctl 0x%lx\n", __func__, 1309 DPRINTF(("%s: Unknown mixer ioctl 0x%lx\n", __func__,
1301 com)); 1310 com));
1302 error = EINVAL; 1311 error = EINVAL;
1303 goto out; 1312 goto out;
1304 } 1313 }
1305 } 1314 }
1306 error = copyout(&idat, SCARG(uap, data), sizeof idat); 1315 error = copyout(&idat, SCARG(uap, data), sizeof idat);
1307 out: 1316 out:
1308 fd_putfile(SCARG(uap, fd)); 1317 fd_putfile(SCARG(uap, fd));
1309 return error; 1318 return error;
1310} 1319}
1311 1320
1312/* Sequencer emulation */ 1321/* Sequencer emulation */
1313int 1322int
1314oss_ioctl_sequencer(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval) 1323oss_ioctl_sequencer(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval)
1315{ 1324{
1316 /* { 1325 /* {
1317 syscallarg(int) fd; 1326 syscallarg(int) fd;
1318 syscallarg(u_long) com; 1327 syscallarg(u_long) com;
1319 syscallarg(void *) data; 1328 syscallarg(void *) data;
1320 } */ 1329 } */
1321 file_t *fp; 1330 file_t *fp;
1322 u_long com; 1331 u_long com;
1323 int idat, idat1; 1332 int idat, idat1;
1324 struct synth_info si; 1333 struct synth_info si;
1325 struct oss_synth_info osi; 1334 struct oss_synth_info osi;
1326 struct oss_seq_event_rec oser; 1335 struct oss_seq_event_rec oser;
1327 int error; 1336 int error;
1328 int (*ioctlf)(file_t *, u_long, void *); 1337 int (*ioctlf)(file_t *, u_long, void *);
1329 1338
1330 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) 1339 if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
1331 return (EBADF); 1340 return (EBADF);
1332 1341
1333 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 1342 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
1334 error = EBADF; 1343 error = EBADF;
1335 goto out; 1344 goto out;
1336 } 1345 }
1337 1346
1338 com = SCARG(uap, com); 1347 com = SCARG(uap, com);
1339 DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com))); 1348 DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com)));
1340 1349
1341 retval[0] = 0; 1350 retval[0] = 0;
1342 1351
1343 ioctlf = fp->f_ops->fo_ioctl; 1352 ioctlf = fp->f_ops->fo_ioctl;
1344 switch (com) { 1353 switch (com) {
1345 case OSS_SEQ_RESET: 1354 case OSS_SEQ_RESET:
1346 error = ioctlf(fp, SEQUENCER_RESET, &idat); 1355 error = ioctlf(fp, SEQUENCER_RESET, &idat);
1347 goto out; 1356 goto out;
1348 case OSS_SEQ_SYNC: 1357 case OSS_SEQ_SYNC:
1349 error = ioctlf(fp, SEQUENCER_SYNC, &idat); 1358 error = ioctlf(fp, SEQUENCER_SYNC, &idat);
1350 goto out; 1359 goto out;
1351 case OSS_SYNTH_INFO: 1360 case OSS_SYNTH_INFO:
1352 error = copyin(SCARG(uap, data), &osi, sizeof osi); 1361 error = copyin(SCARG(uap, data), &osi, sizeof osi);
1353 if (error) 1362 if (error)
1354 goto out; 1363 goto out;
1355 si.device = osi.device; 1364 si.device = osi.device;
1356 error = ioctlf(fp, SEQUENCER_INFO, &si); 1365 error = ioctlf(fp, SEQUENCER_INFO, &si);
1357 if (error) 1366 if (error)
1358 goto out; 1367 goto out;
1359 strncpy(osi.name, si.name, sizeof osi.name); 1368 strncpy(osi.name, si.name, sizeof osi.name);
1360 osi.device = si.device; 1369 osi.device = si.device;
1361 switch(si.synth_type) { 1370 switch(si.synth_type) {
1362 case SYNTH_TYPE_FM: 1371 case SYNTH_TYPE_FM:
1363 osi.synth_type = OSS_SYNTH_TYPE_FM; break; 1372 osi.synth_type = OSS_SYNTH_TYPE_FM; break;
1364 case SYNTH_TYPE_SAMPLE: 1373 case SYNTH_TYPE_SAMPLE:
1365 osi.synth_type = OSS_SYNTH_TYPE_SAMPLE; break; 1374 osi.synth_type = OSS_SYNTH_TYPE_SAMPLE; break;
1366 case SYNTH_TYPE_MIDI: 1375 case SYNTH_TYPE_MIDI:
1367 osi.synth_type = OSS_SYNTH_TYPE_MIDI; break; 1376 osi.synth_type = OSS_SYNTH_TYPE_MIDI; break;
1368 default: 1377 default:
1369 osi.synth_type = 0; break; 1378 osi.synth_type = 0; break;
1370 } 1379 }
1371 switch(si.synth_subtype) { 1380 switch(si.synth_subtype) {
1372 case SYNTH_SUB_FM_TYPE_ADLIB: 1381 case SYNTH_SUB_FM_TYPE_ADLIB:
1373 osi.synth_subtype = OSS_FM_TYPE_ADLIB; break; 1382 osi.synth_subtype = OSS_FM_TYPE_ADLIB; break;
1374 case SYNTH_SUB_FM_TYPE_OPL3: 1383 case SYNTH_SUB_FM_TYPE_OPL3:
1375 osi.synth_subtype = OSS_FM_TYPE_OPL3; break; 1384 osi.synth_subtype = OSS_FM_TYPE_OPL3; break;
1376 case SYNTH_SUB_MIDI_TYPE_MPU401: 1385 case SYNTH_SUB_MIDI_TYPE_MPU401:
1377 osi.synth_subtype = OSS_MIDI_TYPE_MPU401; break; 1386 osi.synth_subtype = OSS_MIDI_TYPE_MPU401; break;
1378 case SYNTH_SUB_SAMPLE_TYPE_BASIC: 1387 case SYNTH_SUB_SAMPLE_TYPE_BASIC:
1379 osi.synth_subtype = OSS_SAMPLE_TYPE_BASIC; break; 1388 osi.synth_subtype = OSS_SAMPLE_TYPE_BASIC; break;
1380 default: 1389 default:
1381 osi.synth_subtype = 0; break; 1390 osi.synth_subtype = 0; break;
1382 } 1391 }
1383 osi.perc_mode = 0; 1392 osi.perc_mode = 0;
1384 osi.nr_voices = si.nr_voices; 1393 osi.nr_voices = si.nr_voices;
1385 osi.nr_drums = 0; 1394 osi.nr_drums = 0;
1386 osi.instr_bank_size = si.instr_bank_size; 1395 osi.instr_bank_size = si.instr_bank_size;
1387 osi.capabilities = 0; 1396 osi.capabilities = 0;
1388 if (si.capabilities & SYNTH_CAP_OPL3) 1397 if (si.capabilities & SYNTH_CAP_OPL3)
1389 osi.capabilities |= OSS_SYNTH_CAP_OPL3; 1398 osi.capabilities |= OSS_SYNTH_CAP_OPL3;
1390 if (si.capabilities & SYNTH_CAP_INPUT) 1399 if (si.capabilities & SYNTH_CAP_INPUT)
1391 osi.capabilities |= OSS_SYNTH_CAP_INPUT; 1400 osi.capabilities |= OSS_SYNTH_CAP_INPUT;
1392 error = copyout(&osi, SCARG(uap, data), sizeof osi); 1401 error = copyout(&osi, SCARG(uap, data), sizeof osi);
1393 goto out; 1402 goto out;
1394 case OSS_SEQ_CTRLRATE: 1403 case OSS_SEQ_CTRLRATE:
1395 error = copyin(SCARG(uap, data), &idat, sizeof idat); 1404 error = copyin(SCARG(uap, data), &idat, sizeof idat);
1396 if (error) 1405 if (error)
1397 goto out; 1406 goto out;
1398 error = ioctlf(fp, SEQUENCER_CTRLRATE, &idat); 1407 error = ioctlf(fp, SEQUENCER_CTRLRATE, &idat);
1399 if (error) 1408 if (error)
1400 goto out; 1409 goto out;