int oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(u_long) com; syscallarg(void *) data; } */ file_t *fp; u_long com; struct audio_info tmpinfo; struct audio_offset tmpoffs; struct oss_audio_buf_info bufinfo; struct oss_count_info cntinfo; struct audio_encoding tmpenc; u_int u; int idat, idata; int error = 0; int (*ioctlf)(file_t *, u_long, void *); if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) return (EBADF); if ((fp->f_flag & (FREAD | FWRITE)) == 0) { error = EBADF; goto out; } com = SCARG(uap, com); DPRINTF(("oss_ioctl_audio: com=%08lx\n", com)); retval[0] = 0; ioctlf = fp->f_ops->fo_ioctl; switch (com) { case OSS_SNDCTL_DSP_RESET: error = ioctlf(fp, AUDIO_FLUSH, NULL); if (error) goto out; break; case OSS_SNDCTL_DSP_SYNC: error = ioctlf(fp, AUDIO_DRAIN, NULL); if (error) goto out; break; case OSS_SNDCTL_DSP_POST: /* This call is merely advisory, and may be a nop. */ break; case OSS_SNDCTL_DSP_SPEED: AUDIO_INITINFO(&tmpinfo); error = copyin(SCARG(uap, data), &idat, sizeof idat); if (error) goto out; tmpinfo.play.sample_rate = tmpinfo.record.sample_rate = idat; error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo); DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_SPEED %d = %d\n", idat, error)); if (error) goto out; /* fall into ... */ case OSS_SOUND_PCM_READ_RATE: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; idat = tmpinfo.play.sample_rate; error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_STEREO: AUDIO_INITINFO(&tmpinfo); error = copyin(SCARG(uap, data), &idat, sizeof idat); if (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) goto out; idat = tmpinfo.play.channels - 1; error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_GETBLKSIZE: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; setblocksize(fp, &tmpinfo); idat = tmpinfo.blocksize; error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_SETFMT: AUDIO_INITINFO(&tmpinfo); error = copyin(SCARG(uap, data), &idat, sizeof idat); if (error) goto out; switch (idat) { case OSS_AFMT_MU_LAW: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULAW; break; case OSS_AFMT_A_LAW: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ALAW; break; case OSS_AFMT_U8: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR; break; case OSS_AFMT_S8: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR; break; case OSS_AFMT_S16_LE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; break; case OSS_AFMT_S16_BE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; break; case OSS_AFMT_U16_LE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE; break; case OSS_AFMT_U16_BE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE; break; default: error = EINVAL; goto out; } (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo); /* fall into ... */ case OSS_SOUND_PCM_READ_BITS: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; switch (tmpinfo.play.encoding) { case AUDIO_ENCODING_ULAW: idat = OSS_AFMT_MU_LAW; break; case AUDIO_ENCODING_ALAW: idat = OSS_AFMT_A_LAW; break; case AUDIO_ENCODING_SLINEAR_LE: if (tmpinfo.play.precision == 16) idat = OSS_AFMT_S16_LE; else idat = OSS_AFMT_S8; break; case AUDIO_ENCODING_SLINEAR_BE: if (tmpinfo.play.precision == 16) idat = OSS_AFMT_S16_BE; else idat = OSS_AFMT_S8; break; case AUDIO_ENCODING_ULINEAR_LE: if (tmpinfo.play.precision == 16) idat = OSS_AFMT_U16_LE; else idat = OSS_AFMT_U8; break; case AUDIO_ENCODING_ULINEAR_BE: if (tmpinfo.play.precision == 16) idat = OSS_AFMT_U16_BE; else idat = OSS_AFMT_U8; break; case AUDIO_ENCODING_ADPCM: idat = OSS_AFMT_IMA_ADPCM; break; } error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_CHANNELS: AUDIO_INITINFO(&tmpinfo); error = copyin(SCARG(uap, data), &idat, sizeof idat); if (error) goto out; tmpinfo.play.channels = tmpinfo.record.channels = idat; (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo); /* fall into ... */ case OSS_SOUND_PCM_READ_CHANNELS: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; idat = tmpinfo.play.channels; error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SOUND_PCM_WRITE_FILTER: case OSS_SOUND_PCM_READ_FILTER: error = EINVAL; /* XXX unimplemented */ goto out; case OSS_SNDCTL_DSP_SUBDIVIDE: error = copyin(SCARG(uap, data), &idat, sizeof idat); if (error) goto out; error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); setblocksize(fp, &tmpinfo); if (error) goto out; 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) goto out; idat = tmpinfo.play.buffer_size / tmpinfo.blocksize; error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_SETFRAGMENT: AUDIO_INITINFO(&tmpinfo); error = copyin(SCARG(uap, data), &idat, sizeof idat); if (error) goto out; if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) { 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)); 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) 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) goto out; break; case OSS_SNDCTL_DSP_GETFMTS: for(idat = 0, tmpenc.index = 0; ioctlf(fp, AUDIO_GETENC, &tmpenc) == 0; tmpenc.index++) { switch(tmpenc.encoding) { case AUDIO_ENCODING_ULAW: idat |= OSS_AFMT_MU_LAW; break; case AUDIO_ENCODING_ALAW: idat |= OSS_AFMT_A_LAW; break; case AUDIO_ENCODING_SLINEAR: idat |= OSS_AFMT_S8; break; case AUDIO_ENCODING_SLINEAR_LE: if (tmpenc.precision == 16) idat |= OSS_AFMT_S16_LE; else idat |= OSS_AFMT_S8; break; case AUDIO_ENCODING_SLINEAR_BE: if (tmpenc.precision == 16) idat |= OSS_AFMT_S16_BE; else idat |= OSS_AFMT_S8; break; case AUDIO_ENCODING_ULINEAR: idat |= OSS_AFMT_U8; break; case AUDIO_ENCODING_ULINEAR_LE: if (tmpenc.precision == 16) idat |= OSS_AFMT_U16_LE; else idat |= OSS_AFMT_U8; break; case AUDIO_ENCODING_ULINEAR_BE: if (tmpenc.precision == 16) idat |= OSS_AFMT_U16_BE; else idat |= OSS_AFMT_U8; break; case AUDIO_ENCODING_ADPCM: idat |= OSS_AFMT_IMA_ADPCM; break; default: break; } } DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETFMTS = %x\n", idat)); error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_GETOSPACE: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; setblocksize(fp, &tmpinfo); bufinfo.fragsize = tmpinfo.blocksize; bufinfo.fragments = tmpinfo.hiwat - (tmpinfo.play.seek + tmpinfo.blocksize - 1) / tmpinfo.blocksize; bufinfo.fragstotal = tmpinfo.hiwat; bufinfo.bytes = tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek; error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo); if (error) goto out; break; case OSS_SNDCTL_DSP_GETISPACE: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; setblocksize(fp, &tmpinfo); bufinfo.fragsize = tmpinfo.blocksize; bufinfo.fragments = tmpinfo.hiwat - (tmpinfo.record.seek + tmpinfo.blocksize - 1) / tmpinfo.blocksize; 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) goto out; break; case OSS_SNDCTL_DSP_NONBLOCK: idat = 1; error = ioctlf(fp, FIONBIO, &idat); if (error) goto out; break; case OSS_SNDCTL_DSP_GETCAPS: error = ioctlf(fp, AUDIO_GETPROPS, &idata); if (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)); error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; #if 0 case OSS_SNDCTL_DSP_GETTRIGGER: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (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) 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) 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) goto out; break; #else case OSS_SNDCTL_DSP_GETTRIGGER: case OSS_SNDCTL_DSP_SETTRIGGER: /* XXX Do nothing for now. */ idat = OSS_PCM_ENABLE_OUTPUT; error = copyout(&idat, SCARG(uap, data), sizeof idat); goto out; #endif case OSS_SNDCTL_DSP_GETIPTR: error = ioctlf(fp, AUDIO_GETIOFFS, &tmpoffs); if (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) goto out; break; case OSS_SNDCTL_DSP_GETOPTR: error = ioctlf(fp, AUDIO_GETOOFFS, &tmpoffs); if (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) goto out; break; case OSS_SNDCTL_DSP_SETDUPLEX: idat = 1; error = ioctlf(fp, AUDIO_SETFD, &idat); goto out; case OSS_SNDCTL_DSP_MAPINBUF: case OSS_SNDCTL_DSP_MAPOUTBUF: case OSS_SNDCTL_DSP_SETSYNCRO: error = EINVAL; goto out; case OSS_SNDCTL_DSP_GETODELAY: error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo); if (error) goto out; idat = tmpinfo.play.seek + tmpinfo.blocksize / 2; error = copyout(&idat, SCARG(uap, data), sizeof idat); if (error) goto out; break; case OSS_SNDCTL_DSP_PROFILE: /* This gives just a hint to the driver, * implementing it as a NOP is ok */ break; default: error = EINVAL; goto out; } out: fd_putfile(SCARG(uap, fd)); return error; }
static int audio_ioctl(int fd, unsigned long com, void *argp) { struct audio_info tmpinfo; struct audio_offset tmpoffs; struct audio_buf_info bufinfo; struct count_info cntinfo; struct audio_encoding tmpenc; struct audio_bufinfo tmpab; u_long ldat; u_int u; int idat, idata; int tempret, retval = 0, rerr = 0; switch (com) { case SNDCTL_DSP_RESET: retval = ioctl(fd, AUDIO_FLUSH, 0); rerr = errno; break; case SNDCTL_DSP_SYNC: retval = ioctl(fd, AUDIO_DRAIN, 0); rerr = errno; break; case SNDCTL_DSP_POST: /* This call is merely advisory, and may be a nop. */ break; case SNDCTL_DSP_SPEED: AUDIO_INITINFO(&tmpinfo); tmpinfo.play.sample_rate = tmpinfo.record.sample_rate = INTARG; retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); rerr = errno; /* FALLTHRU */ case SOUND_PCM_READ_RATE: tempret = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval >= 0) { retval = tempret; rerr = errno; } INTARG = tmpinfo.play.sample_rate; break; case SNDCTL_DSP_STEREO: AUDIO_INITINFO(&tmpinfo); tmpinfo.play.channels = tmpinfo.record.channels = INTARG ? 2 : 1; retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); rerr = errno; tempret = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval >= 0) { retval = tempret; rerr = errno; } INTARG = tmpinfo.play.channels - 1; break; case SNDCTL_DSP_GETBLKSIZE: retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); rerr = errno; setblocksize(fd, &tmpinfo); INTARG = tmpinfo.blocksize; break; case SNDCTL_DSP_SETFMT: AUDIO_INITINFO(&tmpinfo); switch (INTARG) { case AFMT_MU_LAW: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULAW; break; case AFMT_A_LAW: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ALAW; break; case AFMT_U8: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR; break; case AFMT_S8: tmpinfo.play.precision = tmpinfo.record.precision = 8; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR; break; case AFMT_S16_LE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE; break; case AFMT_S16_BE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE; break; case AFMT_U16_LE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE; break; case AFMT_U16_BE: tmpinfo.play.precision = tmpinfo.record.precision = 16; tmpinfo.play.encoding = tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE; break; default: retval = -1; rerr = EINVAL; break; } if (retval == -1) { break; } else { retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); rerr = errno; } /* FALLTHRU */ case SOUND_PCM_READ_BITS: (void) ioctl(fd, AUDIO_GETINFO, &tmpinfo); switch (tmpinfo.play.encoding) { case AUDIO_ENCODING_ULAW: idat = AFMT_MU_LAW; break; case AUDIO_ENCODING_ALAW: idat = AFMT_A_LAW; break; case AUDIO_ENCODING_SLINEAR_LE: if (tmpinfo.play.precision == 16) idat = AFMT_S16_LE; else idat = AFMT_S8; break; case AUDIO_ENCODING_SLINEAR_BE: if (tmpinfo.play.precision == 16) idat = AFMT_S16_BE; else idat = AFMT_S8; break; case AUDIO_ENCODING_ULINEAR_LE: if (tmpinfo.play.precision == 16) idat = AFMT_U16_LE; else idat = AFMT_U8; break; case AUDIO_ENCODING_ULINEAR_BE: if (tmpinfo.play.precision == 16) idat = AFMT_U16_BE; else idat = AFMT_U8; break; case AUDIO_ENCODING_ADPCM: idat = AFMT_IMA_ADPCM; break; default: idat = AFMT_MU_LAW; /* XXX default encoding */ break; } INTARG = idat; break; case SNDCTL_DSP_CHANNELS: AUDIO_INITINFO(&tmpinfo); tmpinfo.play.channels = tmpinfo.record.channels = INTARG; retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); rerr = errno; /* FALLTHRU */ case SOUND_PCM_READ_CHANNELS: tempret = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval >= 0) { retval = tempret; rerr = errno; } INTARG = tmpinfo.play.channels; break; case SOUND_PCM_WRITE_FILTER: case SOUND_PCM_READ_FILTER: rerr = EINVAL; retval = -1; /* XXX unimplemented */ break; case SNDCTL_DSP_SUBDIVIDE: retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval < 0) return retval; setblocksize(fd, &tmpinfo); idat = INTARG; if (idat == 0) idat = tmpinfo.play.buffer_size / tmpinfo.blocksize; idat = (tmpinfo.play.buffer_size / idat) & -4; AUDIO_INITINFO(&tmpinfo); tmpinfo.blocksize = idat; retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); if (retval < 0) return retval; INTARG = tmpinfo.play.buffer_size / tmpinfo.blocksize; break; case SNDCTL_DSP_SETFRAGMENT: AUDIO_INITINFO(&tmpinfo); idat = INTARG; if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) return EINVAL; tmpinfo.blocksize = 1 << (idat & 0xffff); tmpinfo.hiwat = ((unsigned)idat >> 16) & 0x7fff; if (tmpinfo.hiwat == 0) /* 0 means set to max */ tmpinfo.hiwat = 65536; retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); rerr = errno; tempret = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval >= 0) { retval = tempret; rerr = errno; } u = tmpinfo.blocksize; for(idat = 0; u > 1; idat++, u >>= 1) ; idat |= (tmpinfo.hiwat & 0x7fff) << 16; INTARG = idat; break; case SNDCTL_DSP_GETFMTS: for(idat = 0, tmpenc.index = 0; ioctl(fd, AUDIO_GETENC, &tmpenc) == 0; tmpenc.index++) { switch(tmpenc.encoding) { case AUDIO_ENCODING_ULAW: idat |= AFMT_MU_LAW; break; case AUDIO_ENCODING_ALAW: idat |= AFMT_A_LAW; break; case AUDIO_ENCODING_SLINEAR: idat |= AFMT_S8; break; case AUDIO_ENCODING_SLINEAR_LE: if (tmpenc.precision == 16) idat |= AFMT_S16_LE; else idat |= AFMT_S8; break; case AUDIO_ENCODING_SLINEAR_BE: if (tmpenc.precision == 16) idat |= AFMT_S16_BE; else idat |= AFMT_S8; break; case AUDIO_ENCODING_ULINEAR: idat |= AFMT_U8; break; case AUDIO_ENCODING_ULINEAR_LE: if (tmpenc.precision == 16) idat |= AFMT_U16_LE; else idat |= AFMT_U8; break; case AUDIO_ENCODING_ULINEAR_BE: if (tmpenc.precision == 16) idat |= AFMT_U16_BE; else idat |= AFMT_U8; break; case AUDIO_ENCODING_ADPCM: idat |= AFMT_IMA_ADPCM; break; default: break; } } INTARG = idat; break; case SNDCTL_DSP_GETOSPACE: retval = ioctl(fd, AUDIO_GETPRINFO, &tmpab); rerr = errno; bufinfo.fragsize = tmpab.blksize; bufinfo.fragstotal = tmpab.hiwat; bufinfo.bytes = tmpab.hiwat * tmpab.blksize - tmpab.seek; if (tmpab.blksize != 0) bufinfo.fragments = bufinfo.bytes / tmpab.blksize; else bufinfo.fragments = 0; *(struct audio_buf_info *)argp = bufinfo; break; case SNDCTL_DSP_GETISPACE: retval = ioctl(fd, AUDIO_GETRRINFO, &tmpab); rerr = errno; bufinfo.fragsize = tmpab.blksize; bufinfo.fragstotal = tmpab.hiwat; bufinfo.bytes = tmpab.seek; if (tmpab.blksize != 0 ) bufinfo.fragments = bufinfo.bytes / tmpab.blksize; else bufinfo.fragments = 0; *(struct audio_buf_info *)argp = bufinfo; break; case SNDCTL_DSP_NONBLOCK: idat = 1; retval = ioctl(fd, FIONBIO, &idat); rerr = errno; break; case SNDCTL_DSP_GETCAPS: retval = ioctl(fd, AUDIO_GETPROPS, &idata); rerr = errno; idat = DSP_CAP_TRIGGER; if (idata & AUDIO_PROP_FULLDUPLEX) idat |= DSP_CAP_DUPLEX; if (idata & AUDIO_PROP_MMAP) idat |= DSP_CAP_MMAP; INTARG = idat; break; case SNDCTL_DSP_SETTRIGGER: idat = INTARG; AUDIO_INITINFO(&tmpinfo); if (idat & PCM_ENABLE_OUTPUT) tmpinfo.play.pause = 0; if (idat & PCM_ENABLE_INPUT) tmpinfo.record.pause = 0; retval = ioctl(fd, AUDIO_SETINFO, &tmpinfo); rerr = errno; /* FALLTHRU */ case SNDCTL_DSP_GETTRIGGER: tempret = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval >= 0) { retval = tempret; rerr = errno; } idat = (tmpinfo.play.pause ? 0 : PCM_ENABLE_OUTPUT) | (tmpinfo.record.pause ? 0 : PCM_ENABLE_INPUT); INTARG = idat; break; case SNDCTL_DSP_GETIPTR: retval = ioctl(fd, AUDIO_GETIOFFS, &tmpoffs); rerr = errno; cntinfo.bytes = tmpoffs.samples; cntinfo.blocks = tmpoffs.deltablks; cntinfo.ptr = tmpoffs.offset; *(struct count_info *)argp = cntinfo; break; case SNDCTL_DSP_GETOPTR: retval = ioctl(fd, AUDIO_GETOOFFS, &tmpoffs); rerr = errno; cntinfo.bytes = tmpoffs.samples; cntinfo.blocks = tmpoffs.deltablks; cntinfo.ptr = tmpoffs.offset; *(struct count_info *)argp = cntinfo; break; case SNDCTL_DSP_SETDUPLEX: idat = 1; retval = ioctl(fd, AUDIO_SETFD, &idat); rerr = errno; break; case SNDCTL_DSP_GETODELAY: retval = ioctl(fd, AUDIO_WSEEK, &ldat); INTARG = (int)ldat; break; case SNDCTL_DSP_MAPINBUF: case SNDCTL_DSP_MAPOUTBUF: case SNDCTL_DSP_SETSYNCRO: case SNDCTL_DSP_PROFILE: rerr = EINVAL; retval = -1; /* XXX unimplemented */ break; default: rerr = EINVAL; retval = -1; break; } errno = rerr; return retval; }