Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/tests/dev/audio Add AUDIO_SETINFO_gain_balance test.
details: https://anonhg.NetBSD.org/src/rev/6a39e14f2949
branches: trunk
changeset: 1022470:6a39e14f2949
user: isaki <isaki%NetBSD.org@localhost>
date: Wed Jul 21 06:18:32 2021 +0000
description:
Add AUDIO_SETINFO_gain_balance test.
The test checks whether AUDIO_SETINFO can change the gain and the balance
at the same time (if MD driver has the capability). See PR kern/56308.
diffstat:
tests/dev/audio/audiotest.c | 293 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 291 insertions(+), 2 deletions(-)
diffs (truncated from 321 to 300 lines):
diff -r 2c1cd2c7b896 -r 6a39e14f2949 tests/dev/audio/audiotest.c
--- a/tests/dev/audio/audiotest.c Wed Jul 21 06:14:58 2021 +0000
+++ b/tests/dev/audio/audiotest.c Wed Jul 21 06:18:32 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: audiotest.c,v 1.13 2020/10/13 09:00:17 rin Exp $ */
+/* $NetBSD: audiotest.c,v 1.14 2021/07/21 06:18:32 isaki Exp $ */
/*
* Copyright (C) 2019 Tetsuya Isaki. All rights reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: audiotest.c,v 1.13 2020/10/13 09:00:17 rin Exp $");
+__RCSID("$NetBSD: audiotest.c,v 1.14 2021/07/21 06:18:32 isaki Exp $");
#include <errno.h>
#include <fcntl.h>
@@ -5573,6 +5573,294 @@
XP_SYS_EQ(0, r);
}
+/*
+ * Look if there are any (non-zero) gain values that can be changed.
+ * If any gain can be set, it is set to gain[0].
+ * If another gain can be set, it is set to gain[1], otherwise gain[1] = -1.
+ * This is for AUDIO_SETINFO_gain_balance.
+ */
+static void
+get_changeable_gain(int fd, int *gain, const char *dir, int offset)
+{
+ struct audio_info ai;
+ int *ai_gain;
+ int hi;
+ int lo;
+ int r;
+
+ /* A hack to handle ai.{play,record}.gain in the same code.. */
+ ai_gain = (int *)(((char *)&ai) + offset);
+
+ /* Try to set the maximum gain */
+ AUDIO_INITINFO(&ai);
+ *ai_gain = AUDIO_MAX_GAIN;
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.gain=%d", dir, *ai_gain);
+ XP_SYS_EQ(0, r);
+ /* Get again. The value you set is not always used as is. */
+ AUDIO_INITINFO(&ai);
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
+ XP_SYS_EQ(0, r);
+ hi = *ai_gain;
+
+ /* Look for next configurable value. */
+ for (lo = hi - 1; lo >= 0; lo--) {
+ AUDIO_INITINFO(&ai);
+ *ai_gain = lo;
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.gain=%d", dir, *ai_gain);
+ XP_SYS_EQ(0, r);
+ /* Get again */
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
+ XP_SYS_EQ(0, r);
+ if (*ai_gain != hi) {
+ lo = *ai_gain;
+ break;
+ }
+ }
+
+ /* Now gain is lo(=gain[0]). */
+
+ /*
+ * hi lo
+ * --- ---
+ * <0 <0 : not available.
+ * >=0 <0 : available but not changeable.
+ * >=0 >=0 (hi!=lo) : available and changeable.
+ */
+ if (hi < 0) {
+ gain[0] = -1;
+ gain[1] = -1;
+ DPRINTF(" > %s.gain cannot be set\n", dir);
+ } else if (lo < 0) {
+ gain[0] = hi;
+ gain[1] = -1;
+ DPRINTF(" > %s.gain can only be set %d\n", dir, gain[0]);
+ } else {
+ gain[0] = lo;
+ gain[1] = hi;
+ DPRINTF(" > %s.gain can be set %d, %d\n",
+ dir, gain[0], gain[1]);
+ }
+}
+
+/*
+ * Look if there are any balance values that can be changed.
+ * If any balance value can be set, it is set to balance[0].
+ * If another balance value can be set, it is set to balance[1],
+ * otherwise balance[1] = -1.
+ * This is for AUDIO_SETINFO_gain_balance.
+ */
+static void
+get_changeable_balance(int fd, int *balance, const char *dir, int offset)
+{
+ struct audio_info ai;
+ u_char *ai_balance;
+ u_char left;
+ u_char right;
+ int r;
+
+ /* A hack to handle ai.{play,record}.balance in the same code.. */
+ ai_balance = ((u_char *)&ai) + offset;
+
+ /* Look for the right side configurable value. */
+ AUDIO_INITINFO(&ai);
+ *ai_balance = AUDIO_RIGHT_BALANCE;
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.balance=%d", dir, *ai_balance);
+ XP_SYS_EQ(0, r);
+ /* Get again. The value you set is not always used as is. */
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
+ XP_SYS_EQ(0, r);
+ right = *ai_balance;
+
+ /* Look for the left side configurable value. */
+ AUDIO_INITINFO(&ai);
+ *ai_balance = AUDIO_LEFT_BALANCE;
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "%s.balance=%d", dir, *ai_balance);
+ XP_SYS_EQ(0, r);
+ /* Get again */
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
+ XP_SYS_EQ(0, r);
+ left = *ai_balance;
+
+ /* Now balance is the left(=balance[0]). */
+
+ if (left == right) {
+ /* The driver has no balance feature. */
+ balance[0] = left;
+ balance[1] = -1;
+ DPRINTF(" > %s.balance can only be set %d\n",
+ dir, balance[0]);
+ } else {
+ balance[0] = left;
+ balance[1] = right;
+ DPRINTF(" > %s.balance can be set %d, %d\n",
+ dir, balance[0], balance[1]);
+ }
+}
+
+/*
+ * Check whether gain and balance can be set at the same time.
+ * PR kern/56308
+ */
+DEF(AUDIO_SETINFO_gain_balance)
+{
+ struct audio_info oai;
+ struct audio_info ai;
+ int i;
+ int mode;
+ int fd;
+ int r;
+ int pgain[2];
+ int pbalance[2];
+ int rgain[2];
+ int rbalance[2];
+ bool ptest;
+ bool rtest;
+
+ TEST("AUDIO_SETINFO_gain_balance");
+
+ mode = openable_mode();
+ fd = OPEN(devaudio, mode);
+ REQUIRED_SYS_OK(fd);
+
+ /* Backup current gain and balance */
+ r = IOCTL(fd, AUDIO_GETINFO, &oai, "&oai");
+ XP_SYS_EQ(0, r);
+
+ if (debug) {
+ printf(" > old play.gain = %d\n", oai.play.gain);
+ printf(" > old play.balance = %d\n", oai.play.balance);
+ printf(" > old record.gain = %d\n", oai.record.gain);
+ printf(" > old record.balance = %d\n", oai.record.balance);
+ }
+
+ for (i = 0; i < 2; i++) {
+ pgain[i] = -1;
+ pbalance[i] = -1;
+ rgain[i] = -1;
+ rbalance[i] = -1;
+ }
+
+ /*
+ * First, check each one separately can be changed.
+ *
+ * The simplest two different gain values are zero and non-zero.
+ * But some device drivers seem to process balance differently
+ * when the gain is high enough and when the gain is zero or near.
+ * So I needed to select two different "non-zero (and high if
+ * possible)" gains.
+ */
+ if (hw_canplay()) {
+ get_changeable_gain(fd, pgain, "play",
+ offsetof(struct audio_info, play.gain));
+ get_changeable_balance(fd, pbalance, "play",
+ offsetof(struct audio_info, play.balance));
+ }
+ if (hw_canrec()) {
+ get_changeable_gain(fd, rgain, "record",
+ offsetof(struct audio_info, record.gain));
+ get_changeable_balance(fd, rbalance, "record",
+ offsetof(struct audio_info, record.balance));
+ }
+
+ /*
+ * [0] [1]
+ * --- ---
+ * -1 * : not available.
+ * >=0 -1 : available but not changeable.
+ * >=0 >=0 : available and changeable. It can be tested.
+ */
+ ptest = (pgain[0] >= 0 && pgain[1] >= 0 &&
+ pbalance[0] >= 0 && pbalance[1] >= 0);
+ rtest = (rgain[0] >= 0 && rgain[1] >= 0 &&
+ rbalance[0] >= 0 && rbalance[1] >= 0);
+
+ if (ptest == false && rtest == false) {
+ XP_SKIP(
+ "The test requires changeable gain and changeable balance");
+
+ /* Restore as possible */
+ AUDIO_INITINFO(&ai);
+ ai.play.gain = oai.play.gain;
+ ai.play.balance = oai.play.balance;
+ ai.record.gain = oai.record.gain;
+ ai.record.balance = oai.record.balance;
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "restore all");
+ XP_SYS_EQ(0, r);
+
+ r = CLOSE(fd);
+ XP_SYS_EQ(0, r);
+ return;
+ }
+
+ /*
+ * If both play.gain and play.balance are changeable,
+ * it should be able to set both at the same time.
+ */
+ if (ptest) {
+ AUDIO_INITINFO(&ai);
+ ai.play.gain = pgain[1];
+ ai.play.balance = pbalance[1];
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "play.gain=%d/balance=%d",
+ ai.play.gain, ai.play.balance);
+ XP_SYS_EQ(0, r);
+
+ AUDIO_INITINFO(&ai);
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
+ XP_SYS_EQ(0, r);
+
+ DPRINTF(" > setting play.gain=%d/balance=%d: "
+ "result gain=%d/balance=%d\n",
+ pgain[1], pbalance[1], ai.play.gain, ai.play.balance);
+ XP_EQ(ai.play.gain, pgain[1]);
+ XP_EQ(ai.play.balance, pbalance[1]);
+ }
+ /*
+ * If both record.gain and record.balance are changeable,
+ * it should be able to set both at the same time.
+ */
+ if (rtest) {
+ AUDIO_INITINFO(&ai);
+ ai.record.gain = rgain[1];
+ ai.record.balance = rbalance[1];
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "record.gain=%d/balance=%d",
+ ai.record.gain, ai.record.balance);
+ XP_SYS_EQ(0, r);
+
+ AUDIO_INITINFO(&ai);
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
+ XP_SYS_EQ(0, r);
+
+ DPRINTF(" > setting record.gain=%d/balance=%d: "
+ "result gain=%d/balance=%d\n",
+ rgain[1], rbalance[1], ai.record.gain, ai.record.balance);
+ XP_EQ(ai.record.gain, rgain[1]);
+ XP_EQ(ai.record.balance, rbalance[1]);
+ }
+
+ /*
+ * Restore all values as possible at the same time.
+ * This restore is also a test.
+ */
+ AUDIO_INITINFO(&ai);
+ ai.play.gain = oai.play.gain;
+ ai.play.balance = oai.play.balance;
+ ai.record.gain = oai.record.gain;
+ ai.record.balance = oai.record.balance;
+ r = IOCTL(fd, AUDIO_SETINFO, &ai, "restore all");
+ XP_SYS_EQ(0, r);
+
+ AUDIO_INITINFO(&ai);
+ r = IOCTL(fd, AUDIO_GETINFO, &ai, "&ai");
Home |
Main Index |
Thread Index |
Old Index