libossaudio: Various OSSv4 fixes to allow reference programs to compile

- Define various new AFMT_*. These are not returned as supported
  formats by SNDCTL_DSP_GETFMTS, because it would be very silly to
  have Vorbis in the kernel.

- Implement PLAYTGT and RECSRC. For each NetBSD audio device
  we only return one playback and recording source, "primary".

- Return preferred channel configuration in capabilities.
  Either DSP_CH_STEREO, DSP_CH_MONO, or DSP_CH_MULTI
  depending on the current hardware format.

- SNDCTL_DSP_HALT_* simply flushes the audio device.
This commit is contained in:
nia 2021-05-09 11:28:25 +00:00
parent df9fc8fe01
commit 5d7326fb2a
2 changed files with 86 additions and 15 deletions

View File

@ -1,7 +1,7 @@
/* $NetBSD: ossaudio.c,v 1.66 2021/03/15 10:58:05 nia Exp $ */
/* $NetBSD: ossaudio.c,v 1.67 2021/05/09 11:28:25 nia Exp $ */
/*-
* Copyright (c) 1997, 2020 The NetBSD Foundation, Inc.
* Copyright (c) 1997-2021 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: ossaudio.c,v 1.66 2021/03/15 10:58:05 nia Exp $");
__RCSID("$NetBSD: ossaudio.c,v 1.67 2021/05/09 11:28:25 nia Exp $");
/*
* This is an Open Sound System compatibility layer, which provides
@ -127,6 +127,7 @@ audio_ioctl(int fd, unsigned long com, void *argp)
int perrors, rerrors;
static int totalperrors = 0;
static int totalrerrors = 0;
oss_mixer_enuminfo *ei;
oss_count_t osscount;
int idat;
int retval;
@ -134,6 +135,8 @@ audio_ioctl(int fd, unsigned long com, void *argp)
idat = 0;
switch (com) {
case SNDCTL_DSP_HALT_INPUT:
case SNDCTL_DSP_HALT_OUTPUT:
case SNDCTL_DSP_RESET:
retval = ioctl(fd, AUDIO_FLUSH, 0);
if (retval < 0)
@ -293,6 +296,7 @@ audio_ioctl(int fd, unsigned long com, void *argp)
* the 24-bit formats should be handled properly instead
* of falling back to 32 bits.
*/
case AFMT_S24_PACKED:
case AFMT_S24_LE:
case AFMT_S32_LE:
tmpinfo.play.precision =
@ -434,10 +438,6 @@ audio_ioctl(int fd, unsigned long com, void *argp)
case SNDCTL_DSP_SETFRAGMENT:
AUDIO_INITINFO(&tmpinfo);
idat = INTARG;
if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) {
errno = EINVAL;
return -1;
}
tmpinfo.blocksize = 1 << (idat & 0xffff);
tmpinfo.hiwat = ((unsigned)idat >> 16) & 0x7fff;
if (tmpinfo.hiwat == 0) /* 0 means set to max */
@ -662,6 +662,21 @@ audio_ioctl(int fd, unsigned long com, void *argp)
case SNDCTL_DSP_SETSYNCRO:
errno = EINVAL;
return -1; /* XXX unimplemented */
case SNDCTL_DSP_GET_PLAYTGT_NAMES:
case SNDCTL_DSP_GET_RECSRC_NAMES:
ei = (oss_mixer_enuminfo *)argp;
ei->nvalues = 1;
ei->version = 0;
ei->strindex[0] = 0;
strlcpy(ei->strings, "primary", OSS_ENUM_STRINGSIZE);
break;
case SNDCTL_DSP_SET_PLAYTGT:
case SNDCTL_DSP_SET_RECSRC:
case SNDCTL_DSP_GET_PLAYTGT:
case SNDCTL_DSP_GET_RECSRC:
/* We have one recording source and play target. */
INTARG = 0;
break;
default:
errno = EINVAL;
return -1;
@ -1114,7 +1129,7 @@ mixer_oss4_ioctl(int fd, unsigned long com, void *argp)
"%s %s", dev.name, dev.version);
tmpai->busy = 0;
tmpai->pid = -1;
ioctl(newfd, SNDCTL_DSP_GETFMTS, &tmpai->iformats);
audio_ioctl(newfd, SNDCTL_DSP_GETFMTS, &tmpai->iformats);
tmpai->oformats = tmpai->iformats;
tmpai->magic = -1; /* reserved for "internal use" */
memset(tmpai->cmd, 0, sizeof(tmpai->cmd));
@ -1603,17 +1618,40 @@ global_oss4_ioctl(int fd, unsigned long com, void *argp)
static int
getcaps(int fd, int *out)
{
struct audio_info info;
int props, caps;
int nchannels;
if (ioctl(fd, AUDIO_GETPROPS, &props) < 0)
return -1;
caps = DSP_CAP_TRIGGER;
if (ioctl(fd, AUDIO_GETFORMAT, &info) < 0)
return -1;
caps = 0;
caps |= PCM_CAP_TRIGGER;
caps |= PCM_CAP_MULTI;
caps |= PCM_CAP_FREERATE;
nchannels = (props & AUDIO_PROP_PLAYBACK) ?
info.play.channels : info.record.channels;
switch (nchannels) {
case 2:
caps |= DSP_CH_STEREO;
break;
case 1:
caps |= DSP_CH_MONO;
break;
default:
caps |= DSP_CH_MULTI;
break;
}
if (props & AUDIO_PROP_FULLDUPLEX)
caps |= DSP_CAP_DUPLEX;
caps |= PCM_CAP_DUPLEX;
if (props & AUDIO_PROP_MMAP)
caps |= DSP_CAP_MMAP;
caps |= PCM_CAP_MMAP;
if (props & AUDIO_PROP_CAPTURE)
caps |= PCM_CAP_INPUT;
if (props & AUDIO_PROP_PLAYBACK)

View File

@ -1,4 +1,4 @@
/* $NetBSD: soundcard.h,v 1.33 2020/12/03 22:10:21 nia Exp $ */
/* $NetBSD: soundcard.h,v 1.34 2021/05/09 11:28:25 nia Exp $ */
/*-
* Copyright (c) 1997, 2020 The NetBSD Foundation, Inc.
@ -60,12 +60,16 @@
#define AFMT_S8 0x00000040
#define AFMT_U16_LE 0x00000080
#define AFMT_U16_BE 0x00000100
#define AFMT_MPEG 0x00000200
#define AFMT_MPEG 0x00000200 /* Not supported */
#define AFMT_AC3 0x00000400
#define AFMT_S24_LE 0x00000800
#define AFMT_S24_BE 0x00001000
#define AFMT_S24_LE 0x00000800 /* Not supported */
#define AFMT_S24_BE 0x00001000 /* Not supported */
#define AFMT_S32_LE 0x00002000
#define AFMT_S32_BE 0x00004000
#define AFMT_FLOAT 0x00010000 /* Not supported */
#define AFMT_SPDIF_RAW 0x00020000 /* Not supported */
#define AFMT_S24_PACKED 0x00040000 /* Not supported */
#define AFMT_VORBIS 0x00080000 /* Not supported */
#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT
#define SOUND_PCM_READ_BITS _IOR ('P', 5, int)
#define SNDCTL_DSP_CHANNELS _IOWR('P', 6, int)
@ -99,6 +103,10 @@
# define DSP_CAP_DIGITALOUT PCM_CAP_DIGITALOUT
# define DSP_CAP_DIGITALIN PCM_CAP_DIGITALIN
# define DSP_CAP_ADMASK PCM_CAP_ADMASK
# define DSP_CAP_FREERATE PCM_CAP_FREERATE
# define DSP_CAP_MULTI PCM_CAP_MULTI
# define DSP_CAP_BIND PCM_CAP_BIND
# define DSP_CAP_SHADOW PCM_CAP_SHADOW
# define PCM_CAP_REVISION 0x000000ff /* Unused in NetBSD */
# define PCM_CAP_DUPLEX 0x00000100 /* Full duplex */
# define PCM_CAP_REALTIME 0x00000200 /* Unused in NetBSD */
@ -111,12 +119,21 @@
# define PCM_CAP_MODEM 0x00010000 /* Unused in NetBSD */
# define PCM_CAP_HIDDEN 0x00020000 /* Unused in NetBSD */
# define PCM_CAP_VIRTUAL 0x00040000 /* Unused in NetBSD */
# define PCM_CAP_MULTI 0x00080000 /* Simultaneous open() */
# define PCM_CAP_ANALOGOUT 0x00100000 /* Unused in NetBSD */
# define PCM_CAP_ANALOGIN 0x00200000 /* Unused in NetBSD */
# define PCM_CAP_DIGITALOUT 0x00400000 /* Unused in NetBSD */
# define PCM_CAP_DIGITALIN 0x00800000 /* Unused in NetBSD */
# define PCM_CAP_ADMASK 0x00f00000 /* Unused in NetBSD */
# define PCM_CAP_SPECIAL 0x01000000 /* Unused in NetBSD */
# define PCM_CAP_FREERATE 0x10000000 /* Freely set rate */
# define PCM_CAP_SHADOW 0x40000000 /* Unused in NetBSD */
# define PCM_CAP_BIND 0x80000000 /* Unused in NetBSD */
# define DSP_CH_ANY 0x00000000 /* No preferred mode */
# define DSP_CH_MONO 0x02000000
# define DSP_CH_STEREO 0x04000000
# define DSP_CH_MULTI 0x06000000
# define DSP_CH_MASK 0x06000000
#define SNDCTL_DSP_GETTRIGGER _IOR ('P', 16, int)
#define SNDCTL_DSP_SETTRIGGER _IOW ('P', 16, int)
# define PCM_ENABLE_INPUT 0x00000001
@ -342,6 +359,11 @@ typedef struct buffmem_desc {
/* Some OSSv4 calls. */
/* Why is yet more duplication necessary? Sigh. */
#define OSS_OPEN_READ PCM_ENABLE_INPUT
#define OSS_OPEN_WRITE PCM_ENABLE_OUTPUT
#define OSS_OPEN_READWRITE (OSS_OPEN_READ|OSS_OPEN_WRITE)
#define OSS_DEVNODE_SIZE 32
#define OSS_LABEL_SIZE 16
#define OSS_LONGNAME_SIZE 64
@ -357,10 +379,21 @@ typedef struct buffmem_desc {
#define SNDCTL_DSP_GETERROR _IOR ('P',34, struct audio_errinfo)
#define SNDCTL_DSP_CURRENT_IPTR _IOR ('P',35, oss_count_t)
#define SNDCTL_DSP_CURRENT_OPTR _IOR ('P',36, oss_count_t)
#define SNDCTL_DSP_GET_RECSRC_NAMES _IOR ('P',37, oss_mixer_enuminfo)
#define SNDCTL_DSP_GET_RECSRC _IOR ('P',38, int)
#define SNDCTL_DSP_SET_RECSRC _IOWR ('P',38, int)
#define SNDCTL_DSP_GET_PLAYTGT_NAMES _IOR ('P',39, oss_mixer_enuminfo)
#define SNDCTL_DSP_GET_PLAYTGT _IOR ('P',40, int)
#define SNDCTL_DSP_SET_PLAYTGT _IOWR ('P',40, int)
#define SNDCTL_DSP_GET_CHNORDER _IOR ('P',42, unsigned long long)
#define SNDCTL_DSP_SET_CHNORDER _IOWR ('P',42, unsigned long long)
#define SNDCTL_DSP_HALT_OUTPUT _IO ('P',70)
#define SNDCTL_DSP_RESET_OUTPUT SNDCTL_DSP_HALT_OUTPUT /* Old name */
#define SNDCTL_DSP_HALT_INPUT _IO ('P',71)
#define SNDCTL_DSP_RESET_INPUT SNDCTL_DSP_HALT_INPUT /* Old name */
#define CHID_UNDEF 0
#define CHID_L 1
#define CHID_R 2