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

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

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

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


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

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

--- src/lib/libossaudio/Attic/ossaudio.c 2020/04/15 14:54:34 1.39
+++ src/lib/libossaudio/Attic/ossaudio.c 2020/04/15 15:25:33 1.40
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ossaudio.c,v 1.39 2020/04/15 14:54:34 nia Exp $ */ 1/* $NetBSD: ossaudio.c,v 1.40 2020/04/15 15:25:33 nia Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__RCSID("$NetBSD: ossaudio.c,v 1.39 2020/04/15 14:54:34 nia Exp $"); 30__RCSID("$NetBSD: ossaudio.c,v 1.40 2020/04/15 15:25:33 nia Exp $");
31 31
32/* 32/*
33 * This is an OSS (Linux) sound API emulator. 33 * This is an OSS (Linux) sound API emulator.
34 * It provides the essentials of the API. 34 * It provides the essentials of the API.
35 */ 35 */
36 36
37/* XXX This file is essentially the same as sys/compat/ossaudio.c. 37/* XXX This file is essentially the same as sys/compat/ossaudio.c.
38 * With some preprocessor magic it could be the same file. 38 * With some preprocessor magic it could be the same file.
39 */ 39 */
40 40
41#include <string.h> 41#include <string.h>
42#include <sys/types.h> 42#include <sys/types.h>
43#include <sys/ioctl.h> 43#include <sys/ioctl.h>
@@ -228,60 +228,82 @@ audio_ioctl(int fd, unsigned long com, v @@ -228,60 +228,82 @@ audio_ioctl(int fd, unsigned long com, v
228 break; 228 break;
229 case AFMT_U16_LE: 229 case AFMT_U16_LE:
230 tmpinfo.play.precision = 230 tmpinfo.play.precision =
231 tmpinfo.record.precision = 16; 231 tmpinfo.record.precision = 16;
232 tmpinfo.play.encoding = 232 tmpinfo.play.encoding =
233 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE; 233 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE;
234 break; 234 break;
235 case AFMT_U16_BE: 235 case AFMT_U16_BE:
236 tmpinfo.play.precision = 236 tmpinfo.play.precision =
237 tmpinfo.record.precision = 16; 237 tmpinfo.record.precision = 16;
238 tmpinfo.play.encoding = 238 tmpinfo.play.encoding =
239 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE; 239 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
240 break; 240 break;
 241 /*
 242 * XXX: When the kernel supports 24-bit LPCM by default,
 243 * the 24-bit formats should be handled properly instead
 244 * of falling back to 32 bits.
 245 */
241 case AFMT_S24_LE: 246 case AFMT_S24_LE:
242 tmpinfo.play.precision = 
243 tmpinfo.record.precision = 24; 
244 tmpinfo.play.encoding = 
245 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 
246 break; 
247 case AFMT_S24_BE: 
248 tmpinfo.play.precision = 
249 tmpinfo.record.precision = 24; 
250 tmpinfo.play.encoding = 
251 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; 
252 break; 
253 case AFMT_S32_LE: 247 case AFMT_S32_LE:
254 tmpinfo.play.precision = 248 tmpinfo.play.precision =
255 tmpinfo.record.precision = 32; 249 tmpinfo.record.precision = 32;
256 tmpinfo.play.encoding = 250 tmpinfo.play.encoding =
257 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 251 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
258 break; 252 break;
 253 case AFMT_S24_BE:
259 case AFMT_S32_BE: 254 case AFMT_S32_BE:
260 tmpinfo.play.precision = 255 tmpinfo.play.precision =
261 tmpinfo.record.precision = 32; 256 tmpinfo.record.precision = 32;
262 tmpinfo.play.encoding = 257 tmpinfo.play.encoding =
263 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; 258 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
264 break; 259 break;
265 case AFMT_AC3: 260 case AFMT_AC3:
266 tmpinfo.play.precision = 261 tmpinfo.play.precision =
267 tmpinfo.record.precision = 16; 262 tmpinfo.record.precision = 16;
268 tmpinfo.play.encoding = 263 tmpinfo.play.encoding =
269 tmpinfo.record.encoding = AUDIO_ENCODING_AC3; 264 tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
270 break; 265 break;
271 default: 266 default:
272 return EINVAL; 267 /*
 268 * OSSv4 specifies that if an invalid format is chosen
 269 * by an application then a sensible format supported
 270 * by the hardware is returned.
 271 *
 272 * In this case, we pick the current hardware format.
 273 */
 274 retval = ioctl(fd, AUDIO_GETFORMAT, &hwfmt);
 275 if (retval < 0)
 276 return retval;
 277 retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo);
 278 if (retval < 0)
 279 return retval;
 280 tmpinfo.play.encoding =
 281 tmpinfo.record.encoding =
 282 (tmpinfo.mode == AUMODE_RECORD) ?
 283 hwfmt.record.encoding : hwfmt.play.encoding;
 284 tmpinfo.play.precision =
 285 tmpinfo.record.precision =
 286 (tmpinfo.mode == AUMODE_RECORD) ?
 287 hwfmt.record.precision : hwfmt.play.precision ;
 288 break;
273 } 289 }
274 (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); 290 /*
 291 * In the post-kernel-mixer world, assume that any error means
 292 * it's fatal rather than an unsupported format being selected.
 293 */
 294 retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo);
 295 if (retval < 0)
 296 return retval;
275 /* FALLTHRU */ 297 /* FALLTHRU */
276 case SOUND_PCM_READ_BITS: 298 case SOUND_PCM_READ_BITS:
277 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo); 299 retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
278 if (retval < 0) 300 if (retval < 0)
279 return retval; 301 return retval;
280 encoding = GETPRINFO(&tmpinfo, encoding); 302 encoding = GETPRINFO(&tmpinfo, encoding);
281 precision = GETPRINFO(&tmpinfo, precision); 303 precision = GETPRINFO(&tmpinfo, precision);
282 switch (encoding) { 304 switch (encoding) {
283 case AUDIO_ENCODING_ULAW: 305 case AUDIO_ENCODING_ULAW:
284 idat = AFMT_MU_LAW; 306 idat = AFMT_MU_LAW;
285 break; 307 break;
286 case AUDIO_ENCODING_ALAW: 308 case AUDIO_ENCODING_ALAW:
287 idat = AFMT_A_LAW; 309 idat = AFMT_A_LAW;

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

--- src/sys/compat/ossaudio/ossaudio.c 2020/04/15 14:54:34 1.79
+++ src/sys/compat/ossaudio/ossaudio.c 2020/04/15 15:25:33 1.80
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ossaudio.c,v 1.79 2020/04/15 14:54:34 nia Exp $ */ 1/* $NetBSD: ossaudio.c,v 1.80 2020/04/15 15:25:33 nia Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.79 2020/04/15 14:54:34 nia Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.80 2020/04/15 15:25:33 nia Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/proc.h> 33#include <sys/proc.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/file.h> 35#include <sys/file.h>
36#include <sys/vnode.h> 36#include <sys/vnode.h>
37#include <sys/filedesc.h> 37#include <sys/filedesc.h>
38#include <sys/ioctl.h> 38#include <sys/ioctl.h>
39#include <sys/mount.h> 39#include <sys/mount.h>
40#include <sys/kernel.h> 40#include <sys/kernel.h>
41#include <sys/audioio.h> 41#include <sys/audioio.h>
42#include <sys/midiio.h> 42#include <sys/midiio.h>
43#include <sys/kauth.h> 43#include <sys/kauth.h>
@@ -385,30 +385,39 @@ oss_ioctl_audio(struct lwp *l, const str @@ -385,30 +385,39 @@ oss_ioctl_audio(struct lwp *l, const str
385 case OSS_AFMT_U16_BE: 385 case OSS_AFMT_U16_BE:
386 tmpinfo.play.precision = 386 tmpinfo.play.precision =
387 tmpinfo.record.precision = 16; 387 tmpinfo.record.precision = 16;
388 tmpinfo.play.encoding = 388 tmpinfo.play.encoding =
389 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE; 389 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
390 break; 390 break;
391 case OSS_AFMT_AC3: 391 case OSS_AFMT_AC3:
392 tmpinfo.play.precision = 392 tmpinfo.play.precision =
393 tmpinfo.record.precision = 16; 393 tmpinfo.record.precision = 16;
394 tmpinfo.play.encoding = 394 tmpinfo.play.encoding =
395 tmpinfo.record.encoding = AUDIO_ENCODING_AC3; 395 tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
396 break; 396 break;
397 default: 397 default:
398 DPRINTF(("%s: SNDCTL_DSP_SETFMT bad fmt %d\n", 398 /*
399 __func__, idat)); 399 * OSSv4 specifies that if an invalid format is chosen
400 error = EINVAL; 400 * by an application then a sensible format supported
401 goto out; 401 * by the hardware is returned.
 402 *
 403 * In this case, we pick S16LE since it's reasonably
 404 * assumed to be supported by applications.
 405 */
 406 tmpinfo.play.precision =
 407 tmpinfo.record.precision = 16;
 408 tmpinfo.play.encoding =
 409 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
 410 break;
402 } 411 }
403 DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n", 412 DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n",
404 __func__, idat)); 413 __func__, idat));
405 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); 414 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
406 if (error) { 415 if (error) {
407 DPRINTF(("%s: AUDIO_SETINFO %d\n", 416 DPRINTF(("%s: AUDIO_SETINFO %d\n",
408 __func__, error)); 417 __func__, error));
409 goto out; 418 goto out;
410 } 419 }
411 /* FALLTHROUGH */ 420 /* FALLTHROUGH */
412 case OSS_SOUND_PCM_READ_BITS: 421 case OSS_SOUND_PCM_READ_BITS:
413 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); 422 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
414 if (error) { 423 if (error) {