Module Name:    src
Committed By:   nia
Date:           Fri Oct 16 12:23:34 UTC 2020

Modified Files:
        src/lib/libossaudio: ossaudio.c

Log Message:
ossaudio: Various OSSv4 fixes for SNDCTL_AUDIOINFO

- Per OSSv4, make this ioctl work on the main mixer device.
  Since the native NetBSD API uses queries on individual audio devices,
  we have to reopen the correct audio device specified in the input to the
  ioctl and fetch information from that.
- Correctly return whether the device is for playback, capture, or both.
- Return the full name of the device in the name field.
- The "handle" has to be a globally unique identifier. The closest thing
  we have to that is device numbers, so use device numbers.
- Return reasonable values in min_rate/max_rate and min_channels/max_channels.

This should allow Mumble's device enumeration to work with a lot less
patching.


To generate a diff of this commit:
cvs rdiff -u -r1.44 -r1.45 src/lib/libossaudio/ossaudio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libossaudio/ossaudio.c
diff -u src/lib/libossaudio/ossaudio.c:1.44 src/lib/libossaudio/ossaudio.c:1.45
--- src/lib/libossaudio/ossaudio.c:1.44	Mon Apr 20 12:01:44 2020
+++ src/lib/libossaudio/ossaudio.c	Fri Oct 16 12:23:34 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: ossaudio.c,v 1.44 2020/04/20 12:01:44 nia Exp $	*/
+/*	$NetBSD: ossaudio.c,v 1.45 2020/10/16 12:23:34 nia Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: ossaudio.c,v 1.44 2020/04/20 12:01:44 nia Exp $");
+__RCSID("$NetBSD: ossaudio.c,v 1.45 2020/10/16 12:23:34 nia Exp $");
 
 /*
  * This is an OSS (Linux) sound API emulator.
@@ -103,6 +103,7 @@ audio_ioctl(int fd, unsigned long com, v
 	struct audio_info tmpinfo, hwfmt;
 	struct audio_offset tmpoffs;
 	struct audio_buf_info bufinfo;
+	struct audio_format_query fmtq;
 	struct count_info cntinfo;
 	struct audio_encoding tmpenc;
 	struct oss_sysinfo tmpsysinfo;
@@ -116,8 +117,9 @@ audio_ioctl(int fd, unsigned long com, v
 	u_int encoding;
 	u_int precision;
 	int idat, idata;
+	int props;
 	int retval;
-	int i;
+	int newfd;
 
 	idat = 0;
 
@@ -583,53 +585,68 @@ audio_ioctl(int fd, unsigned long com, v
 			tmpaudioinfo->dev = 0;
 
 		snprintf(tmpaudioinfo->devnode, OSS_DEVNODE_SIZE,
-		    "/dev/audio%d", tmpaudioinfo->dev); 
+		    "/dev/audio%d", tmpaudioinfo->dev);
 
-		retval = ioctl(fd, AUDIO_GETDEV, &tmpaudiodev);
-		if (retval < 0)
-			return retval;
-		retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo);
-		if (retval < 0)
+		if ((newfd = open(tmpaudioinfo->devnode, O_WRONLY)) < 0) {
+			if ((newfd = open(tmpaudioinfo->devnode, O_RDONLY)) < 0) {
+				return newfd;
+			}
+		}
+
+		retval = ioctl(newfd, AUDIO_GETDEV, &tmpaudiodev);
+		if (retval < 0) {
+			close(newfd);
 			return retval;
-		retval = ioctl(fd, AUDIO_GETPROPS, &idata);
-		if (retval < 0)
+		}
+		retval = ioctl(newfd, AUDIO_GETPROPS, &props);
+		if (retval < 0) {
+			close(newfd);
 			return retval;
+		}
 		idat = DSP_CAP_TRIGGER;
-		if (idata & AUDIO_PROP_FULLDUPLEX)
+		if (props & AUDIO_PROP_FULLDUPLEX)
 			idat |= DSP_CAP_DUPLEX;
-		if (idata & AUDIO_PROP_MMAP)
+		if (props & AUDIO_PROP_MMAP)
 			idat |= DSP_CAP_MMAP;
-		idat = PCM_CAP_INPUT | PCM_CAP_OUTPUT;
-		strlcpy(tmpaudioinfo->name, tmpaudiodev.name,
-		    sizeof tmpaudioinfo->name);
-		tmpaudioinfo->busy = tmpinfo.play.open;
+		if (props & AUDIO_PROP_CAPTURE)
+			idat |= PCM_CAP_INPUT;
+		if (props & AUDIO_PROP_PLAYBACK)
+			idat |= PCM_CAP_OUTPUT;
+		snprintf(tmpaudioinfo->name, sizeof(tmpaudioinfo->name),
+		    "%s %s", tmpaudiodev.name, tmpaudiodev.version);
+		tmpaudioinfo->busy = 0;
 		tmpaudioinfo->pid = -1;
 		tmpaudioinfo->caps = idat;
-		ioctl(fd, SNDCTL_DSP_GETFMTS, &tmpaudioinfo->iformats);
+		ioctl(newfd, SNDCTL_DSP_GETFMTS, &tmpaudioinfo->iformats);
 		tmpaudioinfo->oformats = tmpaudioinfo->iformats;
 		tmpaudioinfo->magic = -1;
-		memset(tmpaudioinfo->cmd, 0, 64);
+		memset(tmpaudioinfo->cmd, 0, sizeof(tmpaudioinfo->cmd));
 		tmpaudioinfo->card_number = -1;
-		memset(tmpaudioinfo->song_name, 0, 64);
-		memset(tmpaudioinfo->label, 0, 16);
-		tmpaudioinfo->port_number = tmpinfo.play.port;
+		memset(tmpaudioinfo->song_name, 0,
+		    sizeof(tmpaudioinfo->song_name));
+		memset(tmpaudioinfo->label, 0, sizeof(tmpaudioinfo->label));
+		tmpaudioinfo->port_number = 0;
 		tmpaudioinfo->mixer_dev = tmpaudioinfo->dev;
 		tmpaudioinfo->legacy_device = -1;
 		tmpaudioinfo->enabled = 1;
 		tmpaudioinfo->flags = -1;
-		tmpaudioinfo->min_rate = tmpinfo.play.sample_rate;
-		tmpaudioinfo->max_rate = tmpinfo.play.sample_rate;
-		tmpaudioinfo->nrates = 2;
-		for (i = 0; i < tmpaudioinfo->nrates; i++)
-			tmpaudioinfo->rates[i] = tmpinfo.play.sample_rate;
-		tmpaudioinfo->min_channels = tmpinfo.play.channels;
-		tmpaudioinfo->max_channels = tmpinfo.play.channels;
+		tmpaudioinfo->min_rate = 8000;
+		tmpaudioinfo->max_rate = 192000;
+		tmpaudioinfo->nrates = 0;
+		tmpaudioinfo->min_channels = 1;
+		tmpaudioinfo->max_channels = 2;
+		for (fmtq.index = 0; ioctl(newfd, AUDIO_QUERYFORMAT, &fmtq) != -1; ++fmtq.index) {
+			if (fmtq.fmt.channels > (unsigned)tmpaudioinfo->max_channels)
+				tmpaudioinfo->max_channels = fmtq.fmt.channels;
+		}
 		tmpaudioinfo->binding = -1;
 		tmpaudioinfo->rate_source = -1;
-		memset(tmpaudioinfo->handle, 0, 16);
+		strlcpy(tmpaudioinfo->handle, tmpaudioinfo->devnode,
+		    sizeof(tmpaudioinfo->handle));
 		tmpaudioinfo->next_play_engine = 0;
 		tmpaudioinfo->next_rec_engine = 0;
 		argp = tmpaudioinfo;
+		close(newfd);
 		break;
 	case SNDCTL_DSP_SETPLAYVOL:
 		setvol(fd, INTARG, false);

Reply via email to