diff --git a/lib/libossaudio/ossaudio.c b/lib/libossaudio/ossaudio.c index 9acc45422abf..cb4cb6a8ee2c 100644 --- a/lib/libossaudio/ossaudio.c +++ b/lib/libossaudio/ossaudio.c @@ -1,4 +1,4 @@ -/* $NetBSD: ossaudio.c,v 1.55 2020/10/22 19:39:48 nia Exp $ */ +/* $NetBSD: ossaudio.c,v 1.56 2020/10/23 09:05:20 nia Exp $ */ /*- * Copyright (c) 1997, 2020 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include -__RCSID("$NetBSD: ossaudio.c,v 1.55 2020/10/22 19:39:48 nia Exp $"); +__RCSID("$NetBSD: ossaudio.c,v 1.56 2020/10/23 09:05:20 nia Exp $"); /* * This is an Open Sound System compatibility layer, which provides @@ -67,6 +67,7 @@ __RCSID("$NetBSD: ossaudio.c,v 1.55 2020/10/22 19:39:48 nia Exp $"); static struct audiodevinfo *getdevinfo(int); +static int getaudiocount(void); static int getmixercount(void); static int getmixercontrolcount(int); @@ -1016,6 +1017,7 @@ static int mixer_oss4_ioctl(int fd, unsigned long com, void *argp) { oss_audioinfo *tmpai; + oss_card_info *cardinfo; oss_mixext *ext; oss_mixext_root root; oss_mixer_enuminfo *ei; @@ -1147,6 +1149,43 @@ mixer_oss4_ioctl(int fd, unsigned long com, void *argp) argp = tmpai; close(newfd); break; + case SNDCTL_CARDINFO: + cardinfo = (oss_card_info *)argp; + if (cardinfo == NULL) + return EINVAL; + if (cardinfo->card != -1) { + snprintf(devname, sizeof(devname), + "/dev/audio%d", cardinfo->card); + newfd = open(devname, O_RDONLY); + if (newfd < 0) + return retval; + } else { + newfd = fd; + } + retval = ioctl(newfd, AUDIO_GETDEV, &dev); + tmperrno = errno; + if (newfd != fd) + close(newfd); + if (retval < 0) { + errno = tmperrno; + return retval; + } + strlcpy(cardinfo->shortname, dev.name, + sizeof(cardinfo->shortname)); + snprintf(cardinfo->longname, sizeof(cardinfo->longname), + "%s %s %s", dev.name, dev.version, dev.config); + memset(cardinfo->hw_info, 0, sizeof(cardinfo->hw_info)); + /* + * OSSv4 does not document this ioctl, and claims it should + * not be used by applications and is provided for "utiltiy + * programs included in OSS". We follow the Solaris + * implementation (which is doucmented) and leave these fields + * unset. + */ + cardinfo->flags = 0; + cardinfo->intr_count = 0; + cardinfo->ack_count = 0; + break; case SNDCTL_SYSINFO: memset(&sysinfo, 0, sizeof(sysinfo)); strlcpy(sysinfo.product, @@ -1156,13 +1195,14 @@ mixer_oss4_ioctl(int fd, unsigned long com, void *argp) strlcpy(sysinfo.license, "BSD", sizeof(sysinfo.license)); sysinfo.versionnum = SOUND_VERSION; - sysinfo.numaudios = OSS_MAX_AUDIO_DEVS; + sysinfo.numaudios = + sysinfo.numcards = + getaudiocount(); sysinfo.numaudioengines = 1; sysinfo.numsynths = 1; sysinfo.nummidis = -1; sysinfo.numtimers = -1; - sysinfo.nummixers = OSS_MAX_AUDIO_DEVS; - sysinfo.numcards = 1; + sysinfo.nummixers = getmixercount(); *(struct oss_sysinfo *)argp = sysinfo; break; case SNDCTL_MIXERINFO: @@ -1552,6 +1592,27 @@ global_oss4_ioctl(int fd, unsigned long com, void *argp) return retval; } +static int +getaudiocount(void) +{ + char devname[32]; + int ndevs = 0; + int tmpfd; + int tmperrno = errno; + + do { + snprintf(devname, sizeof(devname), + "/dev/audio%d", ndevs); + if ((tmpfd = open(devname, O_RDONLY)) != -1 || + (tmpfd = open(devname, O_WRONLY)) != -1) { + ndevs++; + close(tmpfd); + } + } while (tmpfd != -1); + errno = tmperrno; + return ndevs; +} + static int getmixercount(void) { diff --git a/lib/libossaudio/soundcard.h b/lib/libossaudio/soundcard.h index 5f2afaa58f03..adf9950fca1a 100644 --- a/lib/libossaudio/soundcard.h +++ b/lib/libossaudio/soundcard.h @@ -1,4 +1,4 @@ -/* $NetBSD: soundcard.h,v 1.30 2020/10/20 08:57:45 nia Exp $ */ +/* $NetBSD: soundcard.h,v 1.31 2020/10/23 09:05:20 nia Exp $ */ /*- * Copyright (c) 1997, 2020 The NetBSD Foundation, Inc. @@ -407,6 +407,17 @@ typedef struct oss_audioinfo { int filler[184]; /* For expansion */ } oss_audioinfo; +typedef struct oss_card_info { + int card; + char shortname[16]; + char longname[128]; + int flags; + char hw_info[400]; + int intr_count; + int ack_count; + int filler[154]; +} oss_card_info; + #define SNDCTL_SYSINFO _IOR ('X', 1, oss_sysinfo) #define OSS_SYSINFO SNDCTL_SYSINFO /* Old name */ #define SNDCTL_MIX_NRMIX _IOR ('X',2, int) @@ -417,6 +428,7 @@ typedef struct oss_audioinfo { #define SNDCTL_AUDIOINFO _IOWR ('X',7, oss_audioinfo) #define SNDCTL_MIX_ENUMINFO _IOWR ('X',8, oss_mixer_enuminfo) #define SNDCTL_MIXERINFO _IOWR ('X',10, oss_mixerinfo) +#define SNDCTL_CARDINFO _IOWR ('X',11, oss_card_info) #define SNDCTL_ENGINEINFO _IOWR ('X',12, oss_audioinfo) #define SNDCTL_AUDIOINFO_EX _IOWR ('X',13, oss_audioinfo) #define SNDCTL_MIX_DESCRIPTION _IOWR ('X',14, oss_mixer_enuminfo)