Sun Apr 19 13:44:51 2020 UTC ()
ossaudio: Implement SNDCTL_DSP_(SET|GET)TRIGGER.


(nia)
diff -r1.42 -r1.43 src/lib/libossaudio/ossaudio.c
diff -r1.81 -r1.82 src/sys/compat/ossaudio/ossaudio.c

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

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

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

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