xref: /netbsd-src/sys/compat/ossaudio/ossaudio.c (revision 81b108b45f75f89f1e3ffad9fb6f074e771c0935)
1 #include <sys/param.h>
2 #include <sys/proc.h>
3 #include <sys/systm.h>
4 #include <sys/file.h>
5 #include <sys/filedesc.h>
6 #include <sys/ioctl.h>
7 #include <sys/mount.h>
8 #include <sys/audioio.h>
9 
10 #include <sys/syscallargs.h>
11 
12 #include <compat/linux/linux_types.h>
13 #include <compat/linux/linux_ioctl.h>
14 #include <compat/linux/linux_signal.h>
15 #include <compat/linux/linux_syscallargs.h>
16 #include <compat/linux/linux_audio.h>
17 
18 int
19 linux_ioctl_audio(p, uap, retval)
20 	register struct proc *p;
21 	register struct linux_sys_ioctl_args /* {
22 		syscallarg(int) fd;
23 		syscallarg(u_long) com;
24 		syscallarg(caddr_t) data;
25 	} */ *uap;
26 	register_t *retval;
27 {
28 	register struct file *fp;
29 	register struct filedesc *fdp;
30 	u_long com;
31 	struct audio_info tmpinfo;
32 	int idat;
33 	int error;
34 
35 	fdp = p->p_fd;
36 	if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
37 	    (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
38 		return (EBADF);
39 
40 	if ((fp->f_flag & (FREAD | FWRITE)) == 0)
41 		return (EBADF);
42 
43 	com = SCARG(uap, com);
44 	retval[0] = 0;
45 
46 	switch (com) {
47 	case LINUX_SNDCTL_DSP_RESET:
48 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_FLUSH, (caddr_t)0, p);
49 		if (error)
50 			return error;
51 		break;
52 	case LINUX_SNDCTL_DSP_SYNC:
53 	case LINUX_SNDCTL_DSP_POST:
54 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_DRAIN, (caddr_t)0, p);
55 		if (error)
56 			return error;
57 		break;
58 	case LINUX_SNDCTL_DSP_SPEED:
59 		AUDIO_INITINFO(&tmpinfo);
60 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
61 		if (error)
62 			return error;
63 		tmpinfo.play.sample_rate =
64 		tmpinfo.record.sample_rate = idat;
65 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
66 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
67 		if (error)
68 			return error;
69 		idat = tmpinfo.play.sample_rate;
70 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
71 		if (error)
72 			return error;
73 		break;
74 	case LINUX_SNDCTL_DSP_STEREO:
75 		AUDIO_INITINFO(&tmpinfo);
76 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
77 		if (error)
78 			return error;
79 		tmpinfo.play.channels =
80 		tmpinfo.record.channels = idat ? 2 : 1;
81 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
82 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
83 		if (error)
84 			return error;
85 		idat = tmpinfo.play.channels - 1;
86 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
87 		if (error)
88 			return error;
89 		break;
90 	case LINUX_SNDCTL_DSP_GETBLKSIZE:
91 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
92 		if (error)
93 			return error;
94 		idat = tmpinfo.blocksize;
95 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
96 		if (error)
97 			return error;
98 		break;
99 	case LINUX_SNDCTL_DSP_SETFMT:
100 		AUDIO_INITINFO(&tmpinfo);
101 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
102 		if (error)
103 			return error;
104 		switch (idat) {
105 		case LINUX_AFMT_MU_LAW:
106 			tmpinfo.play.precision =
107 			tmpinfo.record.precision = 8;
108 			tmpinfo.play.encoding =
109 			tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
110 			break;
111 		case LINUX_AFMT_A_LAW:
112 			tmpinfo.play.precision =
113 			tmpinfo.record.precision = 8;
114 			tmpinfo.play.encoding =
115 			tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
116 			break;
117 		case LINUX_AFMT_U8:
118 			tmpinfo.play.precision =
119 			tmpinfo.record.precision = 8;
120 			tmpinfo.play.encoding =
121 			tmpinfo.record.encoding = AUDIO_ENCODING_LINEAR;
122 			break;
123 		case LINUX_AFMT_S16_LE:
124 			tmpinfo.play.precision =
125 			tmpinfo.record.precision = 16;
126 			tmpinfo.play.encoding =
127 			tmpinfo.record.encoding = AUDIO_ENCODING_LINEAR;
128 			break;
129 		default:
130 			return EINVAL;
131 		}
132 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
133 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
134 		if (error)
135 			return error;
136 		/*XXXX*/
137 		break;
138 	case LINUX_SNDCTL_DSP_SETFRAGMENT:
139 		AUDIO_INITINFO(&tmpinfo);
140 		error = copyin(SCARG(uap, data), &idat, sizeof idat);
141 		if (error)
142 			return error;
143 		if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17)
144 			return EINVAL;
145 		tmpinfo.blocksize = 1 << (idat & 0xffff);
146 		tmpinfo.hiwat = (idat >> 16) & 0xffff;
147 		(void) (*fp->f_ops->fo_ioctl)(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
148 		error = (*fp->f_ops->fo_ioctl)(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
149 		if (error)
150 			return error;
151 		idat = tmpinfo.blocksize;
152 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
153 		if (error)
154 			return error;
155 		break;
156 	case LINUX_SNDCTL_DSP_GETFMTS:
157 		idat = LINUX_AFMT_MU_LAW | LINUX_AFMT_U8 | LINUX_AFMT_S16_LE;
158 		error = copyout(&idat, SCARG(uap, data), sizeof idat);
159 		if (error)
160 			return error;
161 		break;
162 	default:
163 		return EINVAL;
164 	}
165 
166 	return 0;
167 }
168