Mon Mar 15 10:58:05 2021 UTC ()
ossv4 mixer API: be extra careful with the inputs to AUDIO_MIXER_READ.

some drivers (not hdaudio(4), but uaudio(4), eap(4), sb(4), various other
old cards) will return error if a AUDIO_MIXER_VALUE is requested and the
number of channels is not specified as input. this is not documented as
well as it should be, unfortunately.


(nia)
diff -r1.65 -r1.66 src/lib/libossaudio/ossaudio.c

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

--- src/lib/libossaudio/Attic/ossaudio.c 2020/12/19 12:55:28 1.65
+++ src/lib/libossaudio/Attic/ossaudio.c 2021/03/15 10:58:05 1.66
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ossaudio.c,v 1.65 2020/12/19 12:55:28 nia Exp $ */ 1/* $NetBSD: ossaudio.c,v 1.66 2021/03/15 10:58:05 nia Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997, 2020 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.65 2020/12/19 12:55:28 nia Exp $"); 30__RCSID("$NetBSD: ossaudio.c,v 1.66 2021/03/15 10:58:05 nia Exp $");
31 31
32/* 32/*
33 * This is an Open Sound System compatibility layer, which provides 33 * This is an Open Sound System compatibility layer, which provides
34 * fairly complete ioctl emulation for OSSv3 and some of OSSv4. 34 * fairly complete ioctl emulation for OSSv3 and some of OSSv4.
35 * 35 *
36 * The canonical OSS specification is available at 36 * The canonical OSS specification is available at
37 * http://manuals.opensound.com/developer/ 37 * http://manuals.opensound.com/developer/
38 *  38 *
39 * This file is similar to sys/compat/ossaudio.c with additional OSSv4 39 * This file is similar to sys/compat/ossaudio.c with additional OSSv4
40 * compatibility. 40 * compatibility.
41 */ 41 */
42 42
43#include <string.h> 43#include <string.h>
@@ -1432,26 +1432,27 @@ mixer_oss4_ioctl(int fd, unsigned long c @@ -1432,26 +1432,27 @@ mixer_oss4_ioctl(int fd, unsigned long c
1432 return -1; 1432 return -1;
1433 } 1433 }
1434 snprintf(devname, sizeof(devname), "/dev/mixer%d", mv->dev); 1434 snprintf(devname, sizeof(devname), "/dev/mixer%d", mv->dev);
1435 if ((newfd = open(devname, O_RDWR)) < 0) 1435 if ((newfd = open(devname, O_RDWR)) < 0)
1436 return newfd; 1436 return newfd;
1437 mdi.index = mc.dev = mv->ctrl - 1; 1437 mdi.index = mc.dev = mv->ctrl - 1;
1438 retval = ioctl(newfd, AUDIO_MIXER_DEVINFO, &mdi); 1438 retval = ioctl(newfd, AUDIO_MIXER_DEVINFO, &mdi);
1439 if (retval < 0) { 1439 if (retval < 0) {
1440 tmperrno = errno; 1440 tmperrno = errno;
1441 close(newfd); 1441 close(newfd);
1442 errno = tmperrno; 1442 errno = tmperrno;
1443 return retval; 1443 return retval;
1444 } 1444 }
 1445 mc.type = mdi.type;
1445 switch (mdi.type) { 1446 switch (mdi.type) {
1446 case AUDIO_MIXER_ENUM: 1447 case AUDIO_MIXER_ENUM:
1447 if (mv->value >= mdi.un.e.num_mem) { 1448 if (mv->value >= mdi.un.e.num_mem) {
1448 close(newfd); 1449 close(newfd);
1449 errno = EINVAL; 1450 errno = EINVAL;
1450 return -1; 1451 return -1;
1451 } 1452 }
1452 mc.un.ord = mdi.un.e.member[mv->value].ord; 1453 mc.un.ord = mdi.un.e.member[mv->value].ord;
1453 break; 1454 break;
1454 case AUDIO_MIXER_SET: 1455 case AUDIO_MIXER_SET:
1455 if (mv->value >= mdi.un.s.num_mem) { 1456 if (mv->value >= mdi.un.s.num_mem) {
1456 close(newfd); 1457 close(newfd);
1457 errno = EINVAL; 1458 errno = EINVAL;
@@ -1459,26 +1460,27 @@ mixer_oss4_ioctl(int fd, unsigned long c @@ -1459,26 +1460,27 @@ mixer_oss4_ioctl(int fd, unsigned long c
1459 } 1460 }
1460#ifdef notyet 1461#ifdef notyet
1461 mc.un.mask = 0; 1462 mc.un.mask = 0;
1462 for (i = 0; i < mdi.un.s.num_mem; ++i) { 1463 for (i = 0; i < mdi.un.s.num_mem; ++i) {
1463 if (mv->value & (1 << i)) { 1464 if (mv->value & (1 << i)) {
1464 mc.un.mask |= mdi.un.s.member[mv->value].mask; 1465 mc.un.mask |= mdi.un.s.member[mv->value].mask;
1465 } 1466 }
1466 } 1467 }
1467#else 1468#else
1468 mc.un.mask = mdi.un.s.member[mv->value].mask; 1469 mc.un.mask = mdi.un.s.member[mv->value].mask;
1469#endif 1470#endif
1470 break; 1471 break;
1471 case AUDIO_MIXER_VALUE: 1472 case AUDIO_MIXER_VALUE:
 1473 mc.un.value.num_channels = mdi.un.v.num_channels;
1472 if (mdi.un.v.num_channels != 2) { 1474 if (mdi.un.v.num_channels != 2) {
1473 for (i = 0; i < mdi.un.v.num_channels; ++i) { 1475 for (i = 0; i < mdi.un.v.num_channels; ++i) {
1474 mc.un.value.level[i] = mv->value; 1476 mc.un.value.level[i] = mv->value;
1475 } 1477 }
1476 } else { 1478 } else {
1477 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =  1479 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1478 (mv->value >> 0) & 0xFF; 1480 (mv->value >> 0) & 0xFF;
1479 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 1481 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1480 (mv->value >> 8) & 0xFF; 1482 (mv->value >> 8) & 0xFF;
1481 } 1483 }
1482 break; 1484 break;
1483 } 1485 }
1484 retval = ioctl(newfd, AUDIO_MIXER_WRITE, &mc); 1486 retval = ioctl(newfd, AUDIO_MIXER_WRITE, &mc);
@@ -1502,26 +1504,29 @@ mixer_oss4_ioctl(int fd, unsigned long c @@ -1502,26 +1504,29 @@ mixer_oss4_ioctl(int fd, unsigned long c
1502 } 1504 }
1503 snprintf(devname, sizeof(devname), "/dev/mixer%d", mv->dev); 1505 snprintf(devname, sizeof(devname), "/dev/mixer%d", mv->dev);
1504 if ((newfd = open(devname, O_RDWR)) < 0) 1506 if ((newfd = open(devname, O_RDWR)) < 0)
1505 return newfd; 1507 return newfd;
1506 mdi.index = mc.dev = (mv->ctrl - 1); 1508 mdi.index = mc.dev = (mv->ctrl - 1);
1507 retval = ioctl(newfd, AUDIO_MIXER_DEVINFO, &mdi); 1509 retval = ioctl(newfd, AUDIO_MIXER_DEVINFO, &mdi);
1508 if (retval < 0) { 1510 if (retval < 0) {
1509 tmperrno = errno; 1511 tmperrno = errno;
1510 close(newfd); 1512 close(newfd);
1511 errno = tmperrno; 1513 errno = tmperrno;
1512 return retval; 1514 return retval;
1513 } 1515 }
1514 mc.dev = mdi.index; 1516 mc.dev = mdi.index;
 1517 mc.type = mdi.type;
 1518 if (mdi.type == AUDIO_MIXER_VALUE)
 1519 mc.un.value.num_channels = mdi.un.v.num_channels;
1515 retval = ioctl(newfd, AUDIO_MIXER_READ, &mc); 1520 retval = ioctl(newfd, AUDIO_MIXER_READ, &mc);
1516 if (retval < 0) { 1521 if (retval < 0) {
1517 tmperrno = errno; 1522 tmperrno = errno;
1518 close(newfd); 1523 close(newfd);
1519 errno = tmperrno; 1524 errno = tmperrno;
1520 return retval; 1525 return retval;
1521 } 1526 }
1522 close(newfd); 1527 close(newfd);
1523 mv->value = 0; 1528 mv->value = 0;
1524 switch (mdi.type) { 1529 switch (mdi.type) {
1525 case AUDIO_MIXER_ENUM: 1530 case AUDIO_MIXER_ENUM:
1526 for (i = 0; i < mdi.un.e.num_mem; ++i) { 1531 for (i = 0; i < mdi.un.e.num_mem; ++i) {
1527 if (mc.un.ord == mdi.un.e.member[i].ord) { 1532 if (mc.un.ord == mdi.un.e.member[i].ord) {