Home | History | Annotate | Line # | Download | only in ossaudio
ossaudio.c revision 1.5
      1 /*	$NetBSD: ossaudio.c,v 1.5 1997/03/20 16:11:29 mycroft Exp $	*/
      2 #include <sys/param.h>
      3 #include <sys/proc.h>
      4 #include <sys/systm.h>
      5 #include <sys/file.h>
      6 #include <sys/filedesc.h>
      7 #include <sys/ioctl.h>
      8 #include <sys/mount.h>
      9 #include <sys/audioio.h>
     10 
     11 #include <sys/syscallargs.h>
     12 
     13 #include <compat/linux/linux_types.h>
     14 #include <compat/linux/linux_ioctl.h>
     15 #include <compat/linux/linux_signal.h>
     16 #include <compat/linux/linux_syscallargs.h>
     17 #include <compat/linux/linux_audio.h>
     18 
     19 int
     20 linux_ioctl_audio(p, uap, retval)
     21 	register struct proc *p;
     22 	register struct linux_sys_ioctl_args /* {
     23 		syscallarg(int) fd;
     24 		syscallarg(u_long) com;
     25 		syscallarg(caddr_t) data;
     26 	} */ *uap;
     27 	register_t *retval;
     28 {
     29 	register struct file *fp;
     30 	register struct filedesc *fdp;
     31 	u_long com;
     32 	struct audio_info tmpinfo;
     33 	int idat;
     34 	int error;
     35 
     36 	fdp = p->p_fd;
     37 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
     38 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
     39 		return (EBADF);
     40 
     41 	if ((fp->f_flag & (FREAD | FWRITE)) == 0)
     42 		return (EBADF);
     43 
     44 	com = SCARG(uap, com);
     45 	retval[0] = 0;
     46 
     47 	switch (com) {
     48 	case LINUX_SNDCTL_DSP_RESET:
     49 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_FLUSH, (caddr_t)0, p);
     50 		if (error)
     51 			return error;
     52 		break;
     53 	case LINUX_SNDCTL_DSP_SYNC:
     54 	case LINUX_SNDCTL_DSP_POST:
     55 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_DRAIN, (caddr_t)0, p);
     56 		if (error)
     57 			return error;
     58 		break;
     59 	case LINUX_SNDCTL_DSP_SPEED:
     60 		AUDIO_INITINFO(&tmpinfo);
     61 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
     62 		if (error)
     63 			return error;
     64 		tmpinfo.play.sample_rate =
     65 		tmpinfo.record.sample_rate = idat;
     66 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
     67 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
     68 		if (error)
     69 			return error;
     70 		idat = tmpinfo.play.sample_rate;
     71 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
     72 		if (error)
     73 			return error;
     74 		break;
     75 	case LINUX_SNDCTL_DSP_STEREO:
     76 		AUDIO_INITINFO(&tmpinfo);
     77 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
     78 		if (error)
     79 			return error;
     80 		tmpinfo.play.channels =
     81 		tmpinfo.record.channels = idat ? 2 : 1;
     82 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
     83 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
     84 		if (error)
     85 			return error;
     86 		idat = tmpinfo.play.channels - 1;
     87 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
     88 		if (error)
     89 			return error;
     90 		break;
     91 	case LINUX_SNDCTL_DSP_CHANNELS:
     92 		AUDIO_INITINFO(&tmpinfo);
     93 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
     94 		if (error)
     95 			return error;
     96 		tmpinfo.play.channels =
     97 		tmpinfo.record.channels = idat;
     98 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
     99 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
    100 		if (error)
    101 			return error;
    102 		idat = tmpinfo.play.channels;
    103 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
    104 		if (error)
    105 			return error;
    106 		break;
    107 	case LINUX_SNDCTL_DSP_GETBLKSIZE:
    108 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
    109 		if (error)
    110 			return error;
    111 		idat = tmpinfo.blocksize;
    112 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
    113 		if (error)
    114 			return error;
    115 		break;
    116 	case LINUX_SNDCTL_DSP_SETFMT:
    117 		AUDIO_INITINFO(&tmpinfo);
    118 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
    119 		if (error)
    120 			return error;
    121 		switch (idat) {
    122 		case LINUX_AFMT_MU_LAW:
    123 			tmpinfo.play.precision =
    124 			tmpinfo.record.precision = 8;
    125 			tmpinfo.play.encoding =
    126 			tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
    127 			break;
    128 		case LINUX_AFMT_A_LAW:
    129 			tmpinfo.play.precision =
    130 			tmpinfo.record.precision = 8;
    131 			tmpinfo.play.encoding =
    132 			tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
    133 			break;
    134 		case LINUX_AFMT_U8:
    135 			tmpinfo.play.precision =
    136 			tmpinfo.record.precision = 8;
    137 			tmpinfo.play.encoding =
    138 			tmpinfo.record.encoding = AUDIO_ENCODING_LINEAR;
    139 			break;
    140 		case LINUX_AFMT_S16_LE:
    141 			tmpinfo.play.precision =
    142 			tmpinfo.record.precision = 16;
    143 			tmpinfo.play.encoding =
    144 			tmpinfo.record.encoding = AUDIO_ENCODING_LINEAR;
    145 			break;
    146 		default:
    147 			return EINVAL;
    148 		}
    149 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
    150 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
    151 		if (error)
    152 			return error;
    153 		switch (tmpinfo.play.encoding) {
    154 		case AUDIO_ENCODING_ULAW:
    155 			idat = LINUX_AFMT_MU_LAW;
    156 			break;
    157 		case AUDIO_ENCODING_ALAW:
    158 			idat = LINUX_AFMT_A_LAW;
    159 			break;
    160 		case AUDIO_ENCODING_PCM16:
    161 			idat = LINUX_AFMT_S16_LE;
    162 			break;
    163 		case AUDIO_ENCODING_PCM8:
    164 			idat = LINUX_AFMT_U8;
    165 			break;
    166 		case AUDIO_ENCODING_ADPCM:
    167 			idat = LINUX_AFMT_IMA_ADPCM;
    168 			break;
    169 		}
    170 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
    171 		if (error)
    172 			return error;
    173 		break;
    174 	case LINUX_SNDCTL_DSP_SETFRAGMENT:
    175 		AUDIO_INITINFO(&tmpinfo);
    176 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
    177 		if (error)
    178 			return error;
    179 		if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17)
    180 			return EINVAL;
    181 		tmpinfo.blocksize = 1 << (idat & 0xffff);
    182 		tmpinfo.hiwat = (idat >> 16) & 0xffff;
    183 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
    184 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
    185 		if (error)
    186 			return error;
    187 		idat = tmpinfo.blocksize;
    188 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
    189 		if (error)
    190 			return error;
    191 		break;
    192 	case LINUX_SNDCTL_DSP_GETFMTS:
    193 		idat = LINUX_AFMT_MU_LAW | LINUX_AFMT_U8 | LINUX_AFMT_S16_LE;
    194 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
    195 		if (error)
    196 			return error;
    197 		break;
    198 	default:
    199 		return EINVAL;
    200 	}
    201 
    202 	return 0;
    203 }
    204 
    205 int
    206 linux_ioctl_mixer(p, uap, retval)
    207 	register struct proc *p;
    208 	register struct linux_sys_ioctl_args /* {
    209 		syscallarg(int) fd;
    210 		syscallarg(u_long) com;
    211 		syscallarg(caddr_t) data;
    212 	} */ *uap;
    213 	register_t *retval;
    214 {
    215 	register struct file *fp;
    216 	register struct filedesc *fdp;
    217 	u_long com;
    218 #if 0
    219 	struct audio_info tmpinfo;
    220 	int idat;
    221 	int error;
    222 #endif
    223 
    224 	fdp = p->p_fd;
    225 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
    226 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
    227 		return (EBADF);
    228 
    229 	if ((fp->f_flag & (FREAD | FWRITE)) == 0)
    230 		return (EBADF);
    231 
    232 	com = SCARG(uap, com);
    233 	retval[0] = 0;
    234 
    235 	switch (com) {
    236 	default:
    237 		return EINVAL;
    238 	}
    239 }
    240