Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src ossaudio: Make SNDCTL_DSP_SETFMT conform with OSSv4.



details:   https://anonhg.NetBSD.org/src/rev/f7d2d40570b6
branches:  trunk
changeset: 1009181:f7d2d40570b6
user:      nia <nia%NetBSD.org@localhost>
date:      Wed Apr 15 15:25:33 2020 +0000

description:
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.

diffstat:

 lib/libossaudio/ossaudio.c     |  52 +++++++++++++++++++++++++++++------------
 sys/compat/ossaudio/ossaudio.c |  21 ++++++++++++----
 2 files changed, 52 insertions(+), 21 deletions(-)

diffs (130 lines):

diff -r 170c912aab5d -r f7d2d40570b6 lib/libossaudio/ossaudio.c
--- a/lib/libossaudio/ossaudio.c        Wed Apr 15 15:22:37 2020 +0000
+++ b/lib/libossaudio/ossaudio.c        Wed Apr 15 15:25:33 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ossaudio.c,v 1.39 2020/04/15 14:54:34 nia Exp $        */
+/*     $NetBSD: ossaudio.c,v 1.40 2020/04/15 15:25:33 nia Exp $        */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: ossaudio.c,v 1.39 2020/04/15 14:54:34 nia Exp $");
+__RCSID("$NetBSD: ossaudio.c,v 1.40 2020/04/15 15:25:33 nia Exp $");
 
 /*
  * This is an OSS (Linux) sound API emulator.
@@ -238,24 +238,19 @@
                        tmpinfo.play.encoding =
                        tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
                        break;
+               /*
+                * XXX: When the kernel supports 24-bit LPCM by default,
+                * the 24-bit formats should be handled properly instead
+                * of falling back to 32 bits.
+                */
                case AFMT_S24_LE:
-                       tmpinfo.play.precision =
-                       tmpinfo.record.precision = 24;
-                       tmpinfo.play.encoding =
-                       tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
-                       break;
-               case AFMT_S24_BE:
-                       tmpinfo.play.precision =
-                       tmpinfo.record.precision = 24;
-                       tmpinfo.play.encoding =
-                       tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
-                       break;
                case AFMT_S32_LE:
                        tmpinfo.play.precision =
                        tmpinfo.record.precision = 32;
                        tmpinfo.play.encoding =
                        tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
                        break;
+               case AFMT_S24_BE:
                case AFMT_S32_BE:
                        tmpinfo.play.precision =
                        tmpinfo.record.precision = 32;
@@ -269,9 +264,36 @@
                        tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
                        break;
                default:
-                       return EINVAL;
+                       /*
+                        * OSSv4 specifies that if an invalid format is chosen
+                        * by an application then a sensible format supported
+                        * by the hardware is returned.
+                        *
+                        * In this case, we pick the current hardware format.
+                        */
+                       retval = ioctl(fd, AUDIO_GETFORMAT, &hwfmt);
+                       if (retval < 0)
+                               return retval;
+                       retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo);
+                       if (retval < 0)
+                               return retval;
+                       tmpinfo.play.encoding =
+                       tmpinfo.record.encoding =
+                           (tmpinfo.mode == AUMODE_RECORD) ?
+                           hwfmt.record.encoding : hwfmt.play.encoding;
+                       tmpinfo.play.precision =
+                       tmpinfo.record.precision =
+                           (tmpinfo.mode == AUMODE_RECORD) ?
+                           hwfmt.record.precision : hwfmt.play.precision ;
+                       break;
                }
-               (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo);
+               /*
+                * In the post-kernel-mixer world, assume that any error means
+                * it's fatal rather than an unsupported format being selected.
+                */
+               retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo);
+               if (retval < 0)
+                       return retval;
                /* FALLTHRU */
        case SOUND_PCM_READ_BITS:
                retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
diff -r 170c912aab5d -r f7d2d40570b6 sys/compat/ossaudio/ossaudio.c
--- a/sys/compat/ossaudio/ossaudio.c    Wed Apr 15 15:22:37 2020 +0000
+++ b/sys/compat/ossaudio/ossaudio.c    Wed Apr 15 15:25:33 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ossaudio.c,v 1.79 2020/04/15 14:54:34 nia Exp $        */
+/*     $NetBSD: ossaudio.c,v 1.80 2020/04/15 15:25:33 nia Exp $        */
 
 /*-
  * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.79 2020/04/15 14:54:34 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.80 2020/04/15 15:25:33 nia Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -395,10 +395,19 @@
                        tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
                        break;
                default:
-                       DPRINTF(("%s: SNDCTL_DSP_SETFMT bad fmt %d\n",
-                            __func__, idat));
-                       error = EINVAL;
-                       goto out;
+                       /*
+                        * OSSv4 specifies that if an invalid format is chosen
+                        * by an application then a sensible format supported
+                        * by the hardware is returned.
+                        *
+                        * In this case, we pick S16LE since it's reasonably
+                        * assumed to be supported by applications.
+                        */
+                       tmpinfo.play.precision =
+                       tmpinfo.record.precision = 16;
+                       tmpinfo.play.encoding =
+                       tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
+                       break;
                }
                DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n",
                    __func__, idat));



Home | Main Index | Thread Index | Old Index