add a lot more debugging and error checking. Alas, skype seems to be happy

getting back our values, but still does not work.
This commit is contained in:
christos 2009-08-22 23:31:16 +00:00
parent a05687c954
commit 84ec419140

View File

@ -1,4 +1,4 @@
/* $NetBSD: ossaudio.c,v 1.64 2008/11/13 10:05:52 ad Exp $ */
/* $NetBSD: ossaudio.c,v 1.65 2009/08/22 23:31:16 christos Exp $ */
/*-
* Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.64 2008/11/13 10:05:52 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.65 2009/08/22 23:31:16 christos Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -66,6 +66,88 @@ static int enum_to_mask(struct audiodevinfo *di, int enm);
static void setblocksize(file_t *, struct audio_info *);
#ifdef AUDIO_DEBUG
static const char *
compat_ossaudio_getcmd(u_long cmd)
{
static char buf[64];
switch (cmd) {
#define _DO(_a) \
case _a: \
return # _a;
_DO(OSS_SNDCTL_DSP_RESET)
_DO(OSS_SNDCTL_DSP_SYNC)
_DO(OSS_SNDCTL_DSP_SPEED)
_DO(OSS_SOUND_PCM_READ_RATE)
_DO(OSS_SNDCTL_DSP_STEREO)
_DO(OSS_SNDCTL_DSP_GETBLKSIZE)
_DO(OSS_SNDCTL_DSP_SETFMT)
_DO(OSS_SOUND_PCM_READ_BITS)
_DO(OSS_SNDCTL_DSP_CHANNELS)
_DO(OSS_SOUND_PCM_READ_CHANNELS)
_DO(OSS_SOUND_PCM_WRITE_FILTER)
_DO(OSS_SOUND_PCM_READ_FILTER)
_DO(OSS_SNDCTL_DSP_POST)
_DO(OSS_SNDCTL_DSP_SUBDIVIDE)
_DO(OSS_SNDCTL_DSP_SETFRAGMENT)
_DO(OSS_SNDCTL_DSP_GETFMTS)
_DO(OSS_SNDCTL_DSP_GETOSPACE)
_DO(OSS_SNDCTL_DSP_GETISPACE)
_DO(OSS_SNDCTL_DSP_NONBLOCK)
_DO(OSS_SNDCTL_DSP_GETCAPS)
_DO(OSS_SNDCTL_DSP_GETTRIGGER)
_DO(OSS_SNDCTL_DSP_SETTRIGGER)
_DO(OSS_SNDCTL_DSP_GETIPTR)
_DO(OSS_SNDCTL_DSP_GETOPTR)
_DO(OSS_SNDCTL_DSP_MAPINBUF)
_DO(OSS_SNDCTL_DSP_MAPOUTBUF)
_DO(OSS_SNDCTL_DSP_SETSYNCRO)
_DO(OSS_SNDCTL_DSP_SETDUPLEX)
_DO(OSS_SNDCTL_DSP_GETODELAY)
_DO(OSS_SNDCTL_DSP_PROFILE)
_DO(OSS_SOUND_MIXER_INFO)
_DO(OSS_SOUND_OLD_MIXER_INFO)
_DO(OSS_GET_VERSION)
_DO(OSS_SEQ_RESET)
_DO(OSS_SEQ_SYNC)
_DO(OSS_SYNTH_INFO)
_DO(OSS_SEQ_CTRLRATE)
_DO(OSS_SEQ_GETOUTCOUNT)
_DO(OSS_SEQ_GETINCOUNT)
_DO(OSS_SEQ_PERCMODE)
_DO(OSS_SEQ_TESTMIDI)
_DO(OSS_SEQ_RESETSAMPLES)
_DO(OSS_SEQ_NRSYNTHS)
_DO(OSS_SEQ_NRMIDIS)
#ifdef notyet
_DO(OSS_MIDI_INFO)
#endif
_DO(OSS_SEQ_THRESHOLD)
_DO(OSS_MEMAVL)
_DO(OSS_FM_4OP_ENABLE)
_DO(OSS_SEQ_PANIC)
_DO(OSS_SEQ_OUTOFBAND)
_DO(OSS_SEQ_GETTIME)
_DO(OSS_ID)
_DO(OSS_CONTROL)
_DO(OSS_REMOVESAMPLE)
_DO(OSS_TMR_TIMEBASE)
_DO(OSS_TMR_START)
_DO(OSS_TMR_STOP)
_DO(OSS_TMR_CONTINUE)
_DO(OSS_TMR_TEMPO)
_DO(OSS_TMR_SOURCE)
_DO(OSS_TMR_METRONOME)
_DO(OSS_TMR_SELECT)
#undef _DO
default:
(void)snprintf(buf, sizeof(buf), "*0x%lx*", cmd);
return buf;
}
}
#endif
static int
compat_ossaudio_modcmd(modcmd_t cmd, void *arg)
{
@ -108,7 +190,7 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
}
com = SCARG(uap, com);
DPRINTF(("oss_ioctl_audio: com=%08lx\n", com));
DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com)));
retval[0] = 0;
@ -116,13 +198,17 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
switch (com) {
case OSS_SNDCTL_DSP_RESET:
error = ioctlf(fp, AUDIO_FLUSH, NULL);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_FLUSH %d\n", __func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_SYNC:
error = ioctlf(fp, AUDIO_DRAIN, NULL);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_DRAIN %d\n", __func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_POST:
/* This call is merely advisory, and may be a nop. */
@ -130,56 +216,93 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
case OSS_SNDCTL_DSP_SPEED:
AUDIO_INITINFO(&tmpinfo);
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SPEED %d\n",
__func__, error));
goto out;
}
tmpinfo.play.sample_rate =
tmpinfo.record.sample_rate = idat;
DPRINTF(("%s: SNDCTL_DSP_SPEED > %d\n", __func__, idat));
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_SPEED %d = %d\n",
idat, error));
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SPEED %d = %d\n",
__func__, idat, error));
goto out;
}
/* fall into ... */
case OSS_SOUND_PCM_READ_RATE:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
idat = tmpinfo.play.sample_rate;
DPRINTF(("%s: SNDCTL_PCM_READ_RATE < %d\n", __func__, idat));
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SOUND_PCM_READ_RATE %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_STEREO:
AUDIO_INITINFO(&tmpinfo);
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_STEREO %d\n",
__func__, error));
goto out;
}
tmpinfo.play.channels =
tmpinfo.record.channels = idat ? 2 : 1;
(void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_SETINFO %d\n",
__func__, error));
goto out;
}
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
idat = tmpinfo.play.channels - 1;
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_STEREO %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_GETBLKSIZE:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
setblocksize(fp, &tmpinfo);
idat = tmpinfo.blocksize;
DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE < %d\n",
__func__, idat));
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_SETFMT:
AUDIO_INITINFO(&tmpinfo);
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SETFMT %d\n",
__func__, error));
goto out;
}
switch (idat) {
case OSS_AFMT_MU_LAW:
tmpinfo.play.precision =
@ -230,15 +353,27 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
break;
default:
DPRINTF(("%s: SNDCTL_DSP_SETFMT bad fmt %d\n",
__func__, idat));
error = EINVAL;
goto out;
}
(void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n",
__func__, idat));
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_SETINFO %d\n",
__func__, error));
goto out;
}
/* fall into ... */
case OSS_SOUND_PCM_READ_BITS:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
switch (tmpinfo.play.encoding) {
case AUDIO_ENCODING_ULAW:
idat = OSS_AFMT_MU_LAW;
@ -273,83 +408,139 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
case AUDIO_ENCODING_ADPCM:
idat = OSS_AFMT_IMA_ADPCM;
break;
}
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
default:
DPRINTF(("%s: SOUND_PCM_READ_BITS bad encoding %d\n",
__func__, tmpinfo.play.encoding));
error = EINVAL;
goto out;
}
DPRINTF(("%s: SOUND_PCM_READ_BITS < 0x%x\n",
__func__, idat));
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error) {
DPRINTF(("%s: SOUND_PCM_READ_BITS %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_CHANNELS:
AUDIO_INITINFO(&tmpinfo);
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_CHANNELS %d\n",
__func__, error));
goto out;
}
tmpinfo.play.channels =
tmpinfo.record.channels = idat;
(void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
DPRINTF(("%s: SNDCTL_DSP_CHANNELS > %d\n", __func__, idat));
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_SETINFO %d\n",
__func__, error));
goto out;
}
/* fall into ... */
case OSS_SOUND_PCM_READ_CHANNELS:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
idat = tmpinfo.play.channels;
DPRINTF(("%s: SOUND_PCM_READ_CHANNELS < %d\n", __func__, idat));
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SOUND_PCM_READ_CHANNELS %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SOUND_PCM_WRITE_FILTER:
case OSS_SOUND_PCM_READ_FILTER:
error = EINVAL; /* XXX unimplemented */
DPRINTF(("%s: SOUND_PCM_{READ,WRITE}_FILTER filter\n",
__func__));
goto out;
case OSS_SNDCTL_DSP_SUBDIVIDE:
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d\n",
__func__, error));
goto out;
}
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
setblocksize(fp, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
setblocksize(fp, &tmpinfo);
if (idat == 0)
idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
idat = (tmpinfo.play.buffer_size / idat) & -4;
AUDIO_INITINFO(&tmpinfo);
tmpinfo.blocksize = idat;
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_SETINFO %d\n",
__func__, error));
goto out;
}
idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_SETFRAGMENT:
AUDIO_INITINFO(&tmpinfo);
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: DSP_SETFRAGMENT %d\n",
__func__, error));
goto out;
}
if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) {
DPRINTF(("%s: DSP_SETFRAGMENT bad ival%d\n",
__func__, idat));
error = EINVAL;
goto out;
}
tmpinfo.blocksize = 1 << (idat & 0xffff);
tmpinfo.hiwat = (idat >> 16) & 0x7fff;
DPRINTF(("oss_audio: SETFRAGMENT blksize=%d, hiwat=%d\n",
tmpinfo.blocksize, tmpinfo.hiwat));
DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT blksize=%d, "
"hiwat=%d\n", __func__, tmpinfo.blocksize, tmpinfo.hiwat));
if (tmpinfo.hiwat == 0) /* 0 means set to max */
tmpinfo.hiwat = 65536;
(void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_SETINFO %d\n",
__func__, error));
goto out;
}
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
u = tmpinfo.blocksize;
for(idat = 0; u > 1; idat++, u >>= 1)
;
idat |= (tmpinfo.hiwat & 0x7fff) << 16;
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_GETFMTS:
for(idat = 0, tmpenc.index = 0;
for (idat = 0, tmpenc.index = 0;
ioctlf(fp, AUDIO_GETENC, &tmpenc) == 0;
tmpenc.index++) {
switch(tmpenc.encoding) {
@ -393,18 +584,27 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
idat |= OSS_AFMT_IMA_ADPCM;
break;
default:
DPRINTF(("%s: SNDCTL_DSP_GETFMTS unknown %d\n",
__func__, tmpenc.encoding));
break;
}
}
DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETFMTS = %x\n", idat));
DPRINTF(("%s: SNDCTL_DSP_GETFMTS < 0x%x\n",
__func__, idat));
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETFMTS = %x = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_GETOSPACE:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
setblocksize(fp, &tmpinfo);
bufinfo.fragsize = tmpinfo.blocksize;
bufinfo.fragments = tmpinfo.hiwat -
@ -414,13 +614,19 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
bufinfo.bytes =
tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek;
error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETOSPACE = %d\n",
__func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_GETISPACE:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
setblocksize(fp, &tmpinfo);
bufinfo.fragsize = tmpinfo.blocksize;
bufinfo.fragments = tmpinfo.hiwat -
@ -429,55 +635,89 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
bufinfo.fragstotal = tmpinfo.hiwat;
bufinfo.bytes =
tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.record.seek;
DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETxSPACE = %d %d %d %d\n",
bufinfo.fragsize, bufinfo.fragments,
bufinfo.fragstotal, bufinfo.bytes));
error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETISPACE %d %d %d %d = %d\n",
__func__, bufinfo.fragsize, bufinfo.fragments,
bufinfo.fragstotal, bufinfo.bytes, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_NONBLOCK:
idat = 1;
error = ioctlf(fp, FIONBIO, &idat);
if (error)
if (error) {
DPRINTF(("%s: SENDCLT_DSP_NONBLOCK %d\n",
__func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_GETCAPS:
error = ioctlf(fp, AUDIO_GETPROPS, &idata);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETPROPS %d\n",
__func__, error));
goto out;
}
idat = OSS_DSP_CAP_TRIGGER; /* pretend we have trigger */
if (idata & AUDIO_PROP_FULLDUPLEX)
idat |= OSS_DSP_CAP_DUPLEX;
if (idata & AUDIO_PROP_MMAP)
idat |= OSS_DSP_CAP_MMAP;
DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETCAPS = %x\n", idat));
DPRINTF(("%s: SNDCL_DSP_GETCAPS %s duplex, %smmap\n",
__func__, (idat & OSS_DSP_CAP_DUPLEX) ? "full" : "half",
(idat & OSS_DSP_CAP_MMAP) ? "" : "no "));
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETCAPS %x = %d\n", __func__,
idat, error));
goto out;
}
break;
#if 0
case OSS_SNDCTL_DSP_GETTRIGGER:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
idat = (tmpinfo.play.pause ? 0 : OSS_PCM_ENABLE_OUTPUT) |
(tmpinfo.record.pause ? 0 : OSS_PCM_ENABLE_INPUT);
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_SETTRIGGER:
(void) ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo, p);
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo, p);
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
tmpinfo.play.pause = (idat & OSS_PCM_ENABLE_OUTPUT) == 0;
tmpinfo.record.pause = (idat & OSS_PCM_ENABLE_INPUT) == 0;
(void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
if (error) {
DPRINTF(("%s: AUDIO_SETINFO %d\n",
__func__, error));
goto out;
}
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error) {
DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n",
__func__, idat, error));
goto out;
}
break;
#else
case OSS_SNDCTL_DSP_GETTRIGGER:
@ -485,54 +725,94 @@ oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t
/* XXX Do nothing for now. */
idat = OSS_PCM_ENABLE_OUTPUT;
error = copyout(&idat, SCARG(uap, data), sizeof idat);
goto out;
if (error) {
DPRINTF(("%s: SNDCTL_DSP_{GET,SET}RIGGER %x = %d\n",
__func__, idat, error));
goto out;
}
break;
#endif
case OSS_SNDCTL_DSP_GETIPTR:
error = ioctlf(fp, AUDIO_GETIOFFS, &tmpoffs);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETIOFFS %d\n",
__func__, error));
goto out;
}
cntinfo.bytes = tmpoffs.samples;
cntinfo.blocks = tmpoffs.deltablks;
cntinfo.ptr = tmpoffs.offset;
error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETIPTR %d\n",
__func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_GETOPTR:
error = ioctlf(fp, AUDIO_GETOOFFS, &tmpoffs);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETOOFFS %d\n",
__func__, error));
goto out;
}
cntinfo.bytes = tmpoffs.samples;
cntinfo.blocks = tmpoffs.deltablks;
cntinfo.ptr = tmpoffs.offset;
error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETOPTR %d\n",
__func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_SETDUPLEX:
idat = 1;
error = ioctlf(fp, AUDIO_SETFD, &idat);
goto out;
if (error) {
DPRINTF(("%s: AUDIO_SETFD %d = %d\n",
__func__, idat, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_MAPINBUF:
DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPINBUF\n",
__func__));
error = EINVAL;
goto out;
case OSS_SNDCTL_DSP_MAPOUTBUF:
DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPOUTBUF\n",
__func__));
error = EINVAL;
goto out;
case OSS_SNDCTL_DSP_SETSYNCRO:
DPRINTF(("%s: Unimplemented SNDCTL_DSP_GETSYNCHRO\n",
__func__));
error = EINVAL;
goto out;
case OSS_SNDCTL_DSP_GETODELAY:
error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
__func__, error));
goto out;
}
idat = tmpinfo.play.seek + tmpinfo.blocksize / 2;
error = copyout(&idat, SCARG(uap, data), sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: SNDCTL_DSP_GETODELAY %d\n",
__func__, error));
goto out;
}
break;
case OSS_SNDCTL_DSP_PROFILE:
/* This gives just a hint to the driver,
* implementing it as a NOP is ok
*/
DPRINTF(("%s: SNDCTL_DSP_PROFILE\n", __func__));
break;
default:
DPRINTF(("%s: Unimplemented 0x%lx\n", __func__, com));
error = EINVAL;
goto out;
}
@ -760,7 +1040,7 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
}
com = SCARG(uap, com);
DPRINTF(("oss_ioctl_mixer: com=%08lx\n", com));
DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com)));
retval[0] = 0;
@ -778,15 +1058,25 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
case OSS_SOUND_MIXER_INFO:
case OSS_SOUND_OLD_MIXER_INFO:
error = ioctlf(fp, AUDIO_GETDEV, &adev);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_GETDEV %d\n",
__func__, error));
goto out;
}
omi.modify_counter = 1;
strncpy(omi.id, adev.name, sizeof omi.id);
strncpy(omi.name, adev.name, sizeof omi.name);
error = copyout(&omi, SCARG(uap, data), OSS_IOCTL_SIZE(com));
goto out;
if (error) {
DPRINTF(("%s: OSS_SOUND_MIXER_INFO %d\n",
__func__, error));
goto out;
}
break;
case OSS_SOUND_MIXER_READ_RECSRC:
if (di->source == -1) {
DPRINTF(("%s: OSS_SOUND_MIXER_READ_RECSRC bad source\n",
__func__));
error = EINVAL;
goto out;
}
@ -794,16 +1084,22 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
mc.type = AUDIO_MIXER_ENUM;
error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
__func__, error));
goto out;
}
e = opaque_to_enum(di, NULL, mc.un.ord);
if (e >= 0)
idat = 1 << di->rdevmap[e];
} else {
mc.type = AUDIO_MIXER_SET;
error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
__func__, error));
goto out;
}
e = opaque_to_enum(di, NULL, mc.un.mask);
if (e >= 0)
idat = 1 << di->rdevmap[e];
@ -824,13 +1120,18 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
case OSS_SOUND_MIXER_WRITE_RECSRC:
case OSS_SOUND_MIXER_WRITE_R_RECSRC:
if (di->source == -1) {
DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC bad "
"source\n", __func__));
error = EINVAL;
goto out;
}
mc.dev = di->source;
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC %d\n",
__func__, error));
goto out;
}
if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
mc.type = AUDIO_MIXER_ENUM;
for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
@ -839,6 +1140,8 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
if (i >= OSS_SOUND_MIXER_NRDEVICES ||
di->devmap[i] == -1) {
error = EINVAL;
DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC "
"bad index %d\n", __func__, i));
goto out;
}
mc.un.ord = enum_to_ord(di, di->devmap[i]);
@ -848,69 +1151,94 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) {
if (idat & (1 << i)) {
if (di->devmap[i] == -1) {
DPRINTF(("%s: OSS_SOUND_MIXER_"
"WRITE_RECSRC bad devmap "
"%d\n", __func__, i));
error = EINVAL;
goto out;
}
mc.un.mask |= enum_to_mask(di, di->devmap[i]);
mc.un.mask |= enum_to_mask(di,
di->devmap[i]);
}
}
}
error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc);
if (error) {
DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n",
__func__, error));
goto out;
}
goto out;
default:
if (OSS_MIXER_READ(OSS_SOUND_MIXER_FIRST) <= com &&
com < OSS_MIXER_READ(OSS_SOUND_MIXER_NRDEVICES)) {
n = OSS_GET_DEV(com);
if (di->devmap[n] == -1) {
DPRINTF(("%s: 0x%lx bad devmap %d\n",
__func__, com, n));
error = EINVAL;
goto out;
}
doread:
mc.dev = di->devmap[n];
mc.type = AUDIO_MIXER_VALUE;
mc.un.value.num_channels = di->stereomask & (1<<n) ? 2 : 1;
mc.un.value.num_channels = di->stereomask &
(1 << n) ? 2 : 1;
error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
__func__, error));
goto out;
}
if (mc.un.value.num_channels != 2) {
l = r = mc.un.value.level[AUDIO_MIXER_LEVEL_MONO];
l = r =
mc.un.value.level[AUDIO_MIXER_LEVEL_MONO];
} else {
l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT];
r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
}
idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8);
DPRINTF(("OSS_MIXER_READ n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
n, di->devmap[n], l, r, idat));
DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
__func__, n, di->devmap[n], l, r, idat));
break;
} else if ((OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_FIRST) <= com &&
com < OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES)) ||
(OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES))) {
com < OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES)) ||
(OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES))) {
n = OSS_GET_DEV(com);
if (di->devmap[n] == -1) {
DPRINTF(("%s: 0x%lx bad devmap %d\n",
__func__, com, n));
error = EINVAL;
goto out;
}
error = copyin(SCARG(uap, data), &idat, sizeof idat);
if (error)
if (error) {
DPRINTF(("%s: 0x%lx error %d\n",
__func__, com, error));
goto out;
}
l = FROM_OSSVOL( idat & 0xff);
r = FROM_OSSVOL((idat >> 8) & 0xff);
mc.dev = di->devmap[n];
mc.type = AUDIO_MIXER_VALUE;
if (di->stereomask & (1<<n)) {
if (di->stereomask & (1 << n)) {
mc.un.value.num_channels = 2;
mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
} else {
mc.un.value.num_channels = 1;
mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r)/2;
mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] =
(l + r) / 2;
}
DPRINTF(("OSS_MIXER_WRITE n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
n, di->devmap[n], l, r, idat));
DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
__func__, n, di->devmap[n], l, r, idat));
error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc);
if (error)
if (error) {
DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n",
__func__, error));
goto out;
}
if (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES)) {
error = 0;
@ -918,9 +1246,8 @@ oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_
}
goto doread;
} else {
#ifdef AUDIO_DEBUG
printf("oss_audio: unknown mixer ioctl %04lx\n", com);
#endif
DPRINTF(("%s: Unknown mixer ioctl 0x%lx\n", __func__,
com));
error = EINVAL;
goto out;
}
@ -958,7 +1285,7 @@ oss_ioctl_sequencer(struct lwp *l, const struct oss_sys_ioctl_args *uap, registe
}
com = SCARG(uap, com);
DPRINTF(("oss_ioctl_sequencer: com=%08lx\n", com));
DPRINTF(("%s: com=%s\n", __func__, compat_ossaudio_getcmd(com)));
retval[0] = 0;
@ -1132,6 +1459,8 @@ oss_ioctl_sequencer(struct lwp *l, const struct oss_sys_ioctl_args *uap, registe
error = ioctlf(fp, SEQUENCER_TMR_SELECT, &idat);
goto out;
default:
DPRINTF(("%s: Unknown sequencer command 0x%lx\n", __func__,
com));
error = EINVAL;
goto out;
}