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