Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/audio Improve error handling around audio_hw_probe().



details:   https://anonhg.NetBSD.org/src/rev/3c665a71be95
branches:  trunk
changeset: 745117:3c665a71be95
user:      isaki <isaki%NetBSD.org@localhost>
date:      Sun Feb 23 04:24:56 2020 +0000

description:
Improve error handling around audio_hw_probe().
It was difficult to return multiple errors.

diffstat:

 sys/dev/audio/audio.c |  122 ++++++++++++++++++-------------------------------
 1 files changed, 45 insertions(+), 77 deletions(-)

diffs (179 lines):

diff -r fd1ff549e1c5 -r 3c665a71be95 sys/dev/audio/audio.c
--- a/sys/dev/audio/audio.c     Sun Feb 23 04:02:45 2020 +0000
+++ b/sys/dev/audio/audio.c     Sun Feb 23 04:24:56 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.54 2020/02/23 04:02:46 isaki Exp $ */
+/*     $NetBSD: audio.c,v 1.55 2020/02/23 04:24:56 isaki Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -142,7 +142,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.54 2020/02/23 04:02:46 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.55 2020/02/23 04:24:56 isaki Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -558,9 +558,7 @@
        const audio_format2_t *, const audio_format2_t *,
        const audio_filter_reg_t *, const audio_filter_reg_t *);
 static int audio_select_freq(const struct audio_format *);
-static int audio_hw_probe(struct audio_softc *, int, int *,
-       audio_format2_t *, audio_format2_t *);
-static int audio_hw_probe_fmt(struct audio_softc *, audio_format2_t *, int);
+static int audio_hw_probe(struct audio_softc *, audio_format2_t *, int);
 static int audio_hw_validate_format(struct audio_softc *, int,
        const audio_format2_t *);
 static int audio_mixers_set_format(struct audio_softc *,
@@ -940,21 +938,46 @@
        memset(&rhwfmt, 0, sizeof(rhwfmt));
        memset(&pfil, 0, sizeof(pfil));
        memset(&rfil, 0, sizeof(rfil));
-       mutex_enter(sc->sc_lock);
-       error = audio_hw_probe(sc, has_indep, &mode, &phwfmt, &rhwfmt);
-       if (error) {
-               mutex_exit(sc->sc_lock);
-               aprint_error_dev(self, "audio_hw_probe failed, "
-                   "error = %d\n", error);
-               goto bad;
-       }
-       if (mode == 0) {
-               mutex_exit(sc->sc_lock);
-               aprint_error_dev(self, "audio_hw_probe failed, no mode\n");
-               goto bad;
-       }
+       if (has_indep) {
+               int perror, rerror;
+
+               /* On independent devices, probe separately. */
+               perror = audio_hw_probe(sc, &phwfmt, AUMODE_PLAY);
+               rerror = audio_hw_probe(sc, &rhwfmt, AUMODE_RECORD);
+               if (perror && rerror) {
+                       aprint_error_dev(self, "audio_hw_probe failed, "
+                           "perror = %d, rerror = %d\n", perror, rerror);
+                       goto bad;
+               }
+               if (perror) {
+                       mode &= ~AUMODE_PLAY;
+                       aprint_error_dev(self, "audio_hw_probe failed with "
+                           "%d, playback disabled\n", perror);
+               }
+               if (rerror) {
+                       mode &= ~AUMODE_RECORD;
+                       aprint_error_dev(self, "audio_hw_probe failed with "
+                           "%d, capture disabled\n", rerror);
+               }
+       } else {
+               /*
+                * On non independent devices or uni-directional devices,
+                * probe once (simultaneously).
+                */
+               audio_format2_t *fmt = has_playback ? &phwfmt : &rhwfmt;
+               error = audio_hw_probe(sc, fmt, mode);
+               if (error) {
+                       aprint_error_dev(self, "audio_hw_probe failed, "
+                           "error = %d\n", error);
+                       goto bad;
+               }
+               if (has_playback && has_capture)
+                       rhwfmt = phwfmt;
+       }
+
        /* Init hardware. */
        /* hw_probe() also validates [pr]hwfmt.  */
+       mutex_enter(sc->sc_lock);
        error = audio_hw_set_format(sc, mode, &phwfmt, &rhwfmt, &pfil, &rfil);
        if (error) {
                mutex_exit(sc->sc_lock);
@@ -6045,68 +6068,13 @@
 }
 
 /*
- * Probe playback and/or recording format (depending on *modep).
- * *modep is an in-out parameter.  It indicates the direction to configure
- * as an argument, and the direction configured is written back as out
- * parameter.
- * If successful, probed hardware format is stored into *phwfmt, *rhwfmt
- * depending on *modep, and return 0.  Otherwise it returns errno.
- * Must be called with sc_lock held.
- */
-static int
-audio_hw_probe(struct audio_softc *sc, int is_indep, int *modep,
-       audio_format2_t *phwfmt, audio_format2_t *rhwfmt)
-{
-       audio_format2_t fmt;
-       int mode;
-       int error = 0;
-
-       KASSERT(mutex_owned(sc->sc_lock));
-
-       mode = *modep;
-       KASSERTMSG((mode & (AUMODE_PLAY | AUMODE_RECORD)) != 0, "mode=0x%x", mode);
-
-       if (is_indep) {
-               int errorp = 0, errorr = 0;
-
-               /* On independent devices, probe separately. */
-               if ((mode & AUMODE_PLAY) != 0) {
-                       errorp = audio_hw_probe_fmt(sc, phwfmt, AUMODE_PLAY);
-                       if (errorp)
-                               mode &= ~AUMODE_PLAY;
-               }
-               if ((mode & AUMODE_RECORD) != 0) {
-                       errorr = audio_hw_probe_fmt(sc, rhwfmt, AUMODE_RECORD);
-                       if (errorr)
-                               mode &= ~AUMODE_RECORD;
-               }
-
-               /* Return error if both play and record probes failed. */
-               if (errorp && errorr)
-                       error = errorp;
-       } else {
-               /* On non independent devices, probe simultaneously. */
-               error = audio_hw_probe_fmt(sc, &fmt, mode);
-               if (error) {
-                       mode = 0;
-               } else {
-                       *phwfmt = fmt;
-                       *rhwfmt = fmt;
-               }
-       }
-
-       *modep = mode;
-       return error;
-}
-
-/*
  * Choose the most preferred hardware format.
  * If successful, it will store the chosen format into *cand and return 0.
  * Otherwise, return errno.
- * Must be called with sc_lock held.
+ * Must be called without sc_lock held.
  */
 static int
-audio_hw_probe_fmt(struct audio_softc *sc, audio_format2_t *cand, int mode)
+audio_hw_probe(struct audio_softc *sc, audio_format2_t *cand, int mode)
 {
        audio_format_query_t query;
        int cand_score;
@@ -6114,8 +6082,6 @@
        int i;
        int error;
 
-       KASSERT(mutex_owned(sc->sc_lock));
-
        /*
         * Score each formats and choose the highest one.
         *
@@ -6130,7 +6096,9 @@
                memset(&query, 0, sizeof(query));
                query.index = i;
 
+               mutex_enter(sc->sc_lock);
                error = sc->hw_if->query_format(sc->hw_hdl, &query);
+               mutex_exit(sc->sc_lock);
                if (error == EINVAL)
                        break;
                if (error)



Home | Main Index | Thread Index | Old Index