This source file includes following definitions.
- oss_ioctl_audio
- getdevinfo
- oss_ioctl_mixer
- oss_ioctl_sequencer
- setblocksize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <sys/param.h>
38 #include <sys/proc.h>
39 #include <sys/systm.h>
40 #include <sys/file.h>
41 #include <sys/vnode.h>
42 #include <sys/filedesc.h>
43 #include <sys/ioctl.h>
44 #include <sys/mount.h>
45 #include <sys/audioio.h>
46
47 #include <sys/syscallargs.h>
48
49 #include <compat/ossaudio/ossaudio.h>
50 #include <compat/ossaudio/ossaudiovar.h>
51
52 #ifdef AUDIO_DEBUG
53 #define DPRINTF(x) if (ossdebug) printf x
54 int ossdebug = 0;
55 #else
56 #define DPRINTF(x)
57 #endif
58
59 #define TO_OSSVOL(x) ((x) * 100 / 255)
60 #define FROM_OSSVOL(x) ((x) * 255 / 100)
61
62 static struct audiodevinfo *getdevinfo(struct file *, struct proc *);
63
64 static void setblocksize(struct file *, struct audio_info *, struct proc *);
65
66
67 int
68 oss_ioctl_audio(p, uap, retval)
69 struct proc *p;
70 struct oss_sys_ioctl_args
71
72
73
74 *uap;
75 register_t *retval;
76 {
77 struct file *fp;
78 struct filedesc *fdp;
79 u_long com;
80 struct audio_info tmpinfo;
81 struct audio_offset tmpoffs;
82 struct oss_audio_buf_info bufinfo;
83 struct oss_count_info cntinfo;
84 struct audio_encoding tmpenc;
85 u_int u;
86 int idat, idata;
87 int error;
88 int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
89
90 fdp = p->p_fd;
91 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
92 return (EBADF);
93 FREF(fp);
94
95 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
96 error = EBADF;
97 goto out;
98 }
99
100 ioctlf = fp->f_ops->fo_ioctl;
101
102 com = SCARG(uap, com);
103 retval[0] = 0;
104
105 DPRINTF(("oss_sys_ioctl: com=%08lx\n", com));
106 switch (com) {
107 case OSS_SNDCTL_DSP_RESET:
108 error = ioctlf(fp, AUDIO_FLUSH, (caddr_t)0, p);
109 if (error)
110 goto out;
111 break;
112 case OSS_SNDCTL_DSP_SYNC:
113 case OSS_SNDCTL_DSP_POST:
114 error = ioctlf(fp, AUDIO_DRAIN, (caddr_t)0, p);
115 if (error)
116 goto out;
117 break;
118 case OSS_SNDCTL_DSP_SPEED:
119 AUDIO_INITINFO(&tmpinfo);
120 error = copyin(SCARG(uap, data), &idat, sizeof idat);
121 if (error)
122 goto out;
123 tmpinfo.play.sample_rate =
124 tmpinfo.record.sample_rate = idat;
125 error = ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
126 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_SPEED %d = %d\n",
127 idat, error));
128 if (error)
129 goto out;
130
131 case OSS_SOUND_PCM_READ_RATE:
132 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
133 if (error)
134 goto out;
135 idat = tmpinfo.play.sample_rate;
136 error = copyout(&idat, SCARG(uap, data), sizeof idat);
137 if (error)
138 goto out;
139 break;
140 case OSS_SNDCTL_DSP_STEREO:
141 AUDIO_INITINFO(&tmpinfo);
142 error = copyin(SCARG(uap, data), &idat, sizeof idat);
143 if (error)
144 goto out;
145 tmpinfo.play.channels =
146 tmpinfo.record.channels = idat ? 2 : 1;
147 (void) ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
148 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
149 if (error)
150 goto out;
151 idat = tmpinfo.play.channels - 1;
152 error = copyout(&idat, SCARG(uap, data), sizeof idat);
153 if (error)
154 goto out;
155 break;
156 case OSS_SNDCTL_DSP_GETBLKSIZE:
157 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
158 if (error)
159 goto out;
160 setblocksize(fp, &tmpinfo, p);
161 idat = tmpinfo.blocksize;
162 error = copyout(&idat, SCARG(uap, data), sizeof idat);
163 if (error)
164 goto out;
165 break;
166 case OSS_SNDCTL_DSP_SETFMT:
167 AUDIO_INITINFO(&tmpinfo);
168 error = copyin(SCARG(uap, data), &idat, sizeof idat);
169 if (error)
170 goto out;
171 switch (idat) {
172 case OSS_AFMT_MU_LAW:
173 tmpinfo.play.precision =
174 tmpinfo.record.precision = 8;
175 tmpinfo.play.encoding =
176 tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
177 break;
178 case OSS_AFMT_A_LAW:
179 tmpinfo.play.precision =
180 tmpinfo.record.precision = 8;
181 tmpinfo.play.encoding =
182 tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
183 break;
184 case OSS_AFMT_U8:
185 tmpinfo.play.precision =
186 tmpinfo.record.precision = 8;
187 tmpinfo.play.encoding =
188 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR;
189 break;
190 case OSS_AFMT_S8:
191 tmpinfo.play.precision =
192 tmpinfo.record.precision = 8;
193 tmpinfo.play.encoding =
194 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR;
195 break;
196 case OSS_AFMT_S16_LE:
197 tmpinfo.play.precision =
198 tmpinfo.record.precision = 16;
199 tmpinfo.play.encoding =
200 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
201 break;
202 case OSS_AFMT_S16_BE:
203 tmpinfo.play.precision =
204 tmpinfo.record.precision = 16;
205 tmpinfo.play.encoding =
206 tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
207 break;
208 case OSS_AFMT_U16_LE:
209 tmpinfo.play.precision =
210 tmpinfo.record.precision = 16;
211 tmpinfo.play.encoding =
212 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE;
213 break;
214 case OSS_AFMT_U16_BE:
215 tmpinfo.play.precision =
216 tmpinfo.record.precision = 16;
217 tmpinfo.play.encoding =
218 tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
219 break;
220 default:
221 error = EINVAL;
222 goto out;
223 }
224 (void) ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
225
226 case OSS_SOUND_PCM_READ_BITS:
227 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
228 if (error)
229 goto out;
230 switch (tmpinfo.play.encoding) {
231 case AUDIO_ENCODING_ULAW:
232 idat = OSS_AFMT_MU_LAW;
233 break;
234 case AUDIO_ENCODING_ALAW:
235 idat = OSS_AFMT_A_LAW;
236 break;
237 case AUDIO_ENCODING_SLINEAR_LE:
238 if (tmpinfo.play.precision == 16)
239 idat = OSS_AFMT_S16_LE;
240 else
241 idat = OSS_AFMT_S8;
242 break;
243 case AUDIO_ENCODING_SLINEAR_BE:
244 if (tmpinfo.play.precision == 16)
245 idat = OSS_AFMT_S16_BE;
246 else
247 idat = OSS_AFMT_S8;
248 break;
249 case AUDIO_ENCODING_ULINEAR_LE:
250 if (tmpinfo.play.precision == 16)
251 idat = OSS_AFMT_U16_LE;
252 else
253 idat = OSS_AFMT_U8;
254 break;
255 case AUDIO_ENCODING_ULINEAR_BE:
256 if (tmpinfo.play.precision == 16)
257 idat = OSS_AFMT_U16_BE;
258 else
259 idat = OSS_AFMT_U8;
260 break;
261 case AUDIO_ENCODING_ADPCM:
262 idat = OSS_AFMT_IMA_ADPCM;
263 break;
264 }
265 error = copyout(&idat, SCARG(uap, data), sizeof idat);
266 if (error)
267 goto out;
268 break;
269 case OSS_SNDCTL_DSP_CHANNELS:
270 AUDIO_INITINFO(&tmpinfo);
271 error = copyin(SCARG(uap, data), &idat, sizeof idat);
272 if (error)
273 goto out;
274 tmpinfo.play.channels =
275 tmpinfo.record.channels = idat;
276 (void) ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
277
278 case OSS_SOUND_PCM_READ_CHANNELS:
279 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
280 if (error)
281 goto out;
282 idat = tmpinfo.play.channels;
283 error = copyout(&idat, SCARG(uap, data), sizeof idat);
284 if (error)
285 goto out;
286 break;
287 case OSS_SOUND_PCM_WRITE_FILTER:
288 case OSS_SOUND_PCM_READ_FILTER:
289 error = EINVAL;
290 goto out;
291 case OSS_SNDCTL_DSP_SUBDIVIDE:
292 error = copyin(SCARG(uap, data), &idat, sizeof idat);
293 if (error)
294 goto out;
295 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
296 setblocksize(fp, &tmpinfo, p);
297 if (error)
298 goto out;
299 if (idat == 0)
300 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
301 idat = (tmpinfo.play.buffer_size / idat) & -4;
302 AUDIO_INITINFO(&tmpinfo);
303 tmpinfo.blocksize = idat;
304 error = ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
305 if (error)
306 goto out;
307 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
308 error = copyout(&idat, SCARG(uap, data), sizeof idat);
309 if (error)
310 goto out;
311 break;
312 case OSS_SNDCTL_DSP_SETFRAGMENT:
313 AUDIO_INITINFO(&tmpinfo);
314 error = copyin(SCARG(uap, data), &idat, sizeof idat);
315 if (error)
316 goto out;
317 if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) {
318 error = EINVAL;
319 goto out;
320 }
321 tmpinfo.blocksize = 1 << (idat & 0xffff);
322 tmpinfo.hiwat = (idat >> 16) & 0x7fff;
323 DPRINTF(("oss_audio: SETFRAGMENT blksize=%d, hiwat=%d\n",
324 tmpinfo.blocksize, tmpinfo.hiwat));
325 if (tmpinfo.hiwat == 0)
326 tmpinfo.hiwat = 65536;
327 (void) ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
328 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
329 if (error)
330 goto out;
331 u = tmpinfo.blocksize;
332 for(idat = 0; u > 1; idat++, u >>= 1)
333 ;
334 idat |= (tmpinfo.hiwat & 0x7fff) << 16;
335 error = copyout(&idat, SCARG(uap, data), sizeof idat);
336 if (error)
337 goto out;
338 break;
339 case OSS_SNDCTL_DSP_GETFMTS:
340 for(idat = 0, tmpenc.index = 0;
341 ioctlf(fp, AUDIO_GETENC, (caddr_t)&tmpenc, p) == 0;
342 tmpenc.index++) {
343 if (tmpenc.flags & AUDIO_ENCODINGFLAG_EMULATED)
344 continue;
345 switch(tmpenc.encoding) {
346 case AUDIO_ENCODING_ULAW:
347 idat |= OSS_AFMT_MU_LAW;
348 break;
349 case AUDIO_ENCODING_ALAW:
350 idat |= OSS_AFMT_A_LAW;
351 break;
352 case AUDIO_ENCODING_SLINEAR:
353 idat |= OSS_AFMT_S8;
354 break;
355 case AUDIO_ENCODING_SLINEAR_LE:
356 if (tmpenc.precision == 16)
357 idat |= OSS_AFMT_S16_LE;
358 else
359 idat |= OSS_AFMT_S8;
360 break;
361 case AUDIO_ENCODING_SLINEAR_BE:
362 if (tmpenc.precision == 16)
363 idat |= OSS_AFMT_S16_BE;
364 else
365 idat |= OSS_AFMT_S8;
366 break;
367 case AUDIO_ENCODING_ULINEAR:
368 idat |= OSS_AFMT_U8;
369 break;
370 case AUDIO_ENCODING_ULINEAR_LE:
371 if (tmpenc.precision == 16)
372 idat |= OSS_AFMT_U16_LE;
373 else
374 idat |= OSS_AFMT_U8;
375 break;
376 case AUDIO_ENCODING_ULINEAR_BE:
377 if (tmpenc.precision == 16)
378 idat |= OSS_AFMT_U16_BE;
379 else
380 idat |= OSS_AFMT_U8;
381 break;
382 case AUDIO_ENCODING_ADPCM:
383 idat |= OSS_AFMT_IMA_ADPCM;
384 break;
385 default:
386 break;
387 }
388 }
389 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETFMTS = %x\n", idat));
390 error = copyout(&idat, SCARG(uap, data), sizeof idat);
391 if (error)
392 goto out;
393 break;
394 case OSS_SNDCTL_DSP_GETOSPACE:
395 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
396 if (error)
397 goto out;
398 setblocksize(fp, &tmpinfo, p);
399 bufinfo.fragsize = tmpinfo.blocksize;
400 bufinfo.fragments = tmpinfo.hiwat -
401 (tmpinfo.play.seek + tmpinfo.blocksize - 1) /
402 tmpinfo.blocksize;
403 bufinfo.fragstotal = tmpinfo.hiwat;
404 bufinfo.bytes =
405 tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek;
406 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
407 if (error)
408 goto out;
409 break;
410 case OSS_SNDCTL_DSP_GETISPACE:
411 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
412 if (error)
413 goto out;
414 setblocksize(fp, &tmpinfo, p);
415 bufinfo.fragsize = tmpinfo.blocksize;
416 bufinfo.fragments = tmpinfo.hiwat -
417 (tmpinfo.record.seek + tmpinfo.blocksize - 1) /
418 tmpinfo.blocksize;
419 bufinfo.fragstotal = tmpinfo.hiwat;
420 bufinfo.bytes =
421 tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.record.seek;
422 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETxSPACE = %d %d %d %d\n",
423 bufinfo.fragsize, bufinfo.fragments,
424 bufinfo.fragstotal, bufinfo.bytes));
425 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
426 if (error)
427 goto out;
428 break;
429 case OSS_SNDCTL_DSP_NONBLOCK:
430 idat = 1;
431 error = ioctlf(fp, FIONBIO, (caddr_t)&idat, p);
432 if (error)
433 goto out;
434 break;
435 case OSS_SNDCTL_DSP_GETCAPS:
436 error = ioctlf(fp, AUDIO_GETPROPS, (caddr_t)&idata, p);
437 if (error)
438 goto out;
439 idat = OSS_DSP_CAP_TRIGGER;
440 if (idata & AUDIO_PROP_FULLDUPLEX)
441 idat |= OSS_DSP_CAP_DUPLEX;
442 if (idata & AUDIO_PROP_MMAP)
443 idat |= OSS_DSP_CAP_MMAP;
444 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETCAPS = %x\n", idat));
445 error = copyout(&idat, SCARG(uap, data), sizeof idat);
446 if (error)
447 goto out;
448 break;
449 #if 0
450 case OSS_SNDCTL_DSP_GETTRIGGER:
451 error = ioctlf(fp, AUDIO_GETINFO, (caddr_t)&tmpinfo, p);
452 if (error)
453 goto out;
454 idat = (tmpinfo.play.pause ? 0 : OSS_PCM_ENABLE_OUTPUT) |
455 (tmpinfo.record.pause ? 0 : OSS_PCM_ENABLE_INPUT);
456 error = copyout(&idat, SCARG(uap, data), sizeof idat);
457 if (error)
458 goto out;
459 break;
460 case OSS_SNDCTL_DSP_SETTRIGGER:
461 AUDIO_INITINFO(&tmpinfo);
462 error = copyin(SCARG(uap, data), &idat, sizeof idat);
463 if (error)
464 goto out;
465 tmpinfo.play.pause = (idat & OSS_PCM_ENABLE_OUTPUT) == 0;
466 tmpinfo.record.pause = (idat & OSS_PCM_ENABLE_INPUT) == 0;
467 (void) ioctlf(fp, AUDIO_SETINFO, (caddr_t)&tmpinfo, p);
468 error = copyout(&idat, SCARG(uap, data), sizeof idat);
469 if (error)
470 goto out;
471 break;
472 #else
473 case OSS_SNDCTL_DSP_GETTRIGGER:
474 case OSS_SNDCTL_DSP_SETTRIGGER:
475
476 idat = OSS_PCM_ENABLE_OUTPUT;
477 error = copyout(&idat, SCARG(uap, data), sizeof idat);
478 goto out;
479 #endif
480 case OSS_SNDCTL_DSP_GETIPTR:
481 error = ioctlf(fp, AUDIO_GETIOFFS, (caddr_t)&tmpoffs, p);
482 if (error)
483 goto out;
484 cntinfo.bytes = tmpoffs.samples;
485 cntinfo.blocks = tmpoffs.deltablks;
486 cntinfo.ptr = tmpoffs.offset;
487 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
488 if (error)
489 goto out;
490 break;
491 case OSS_SNDCTL_DSP_GETOPTR:
492 error = ioctlf(fp, AUDIO_GETOOFFS, (caddr_t)&tmpoffs, p);
493 if (error)
494 goto out;
495 cntinfo.bytes = tmpoffs.samples;
496 cntinfo.blocks = tmpoffs.deltablks;
497 cntinfo.ptr = tmpoffs.offset;
498 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
499 if (error)
500 goto out;
501 break;
502 case OSS_SNDCTL_DSP_SETDUPLEX:
503 idat = 1;
504 error = ioctlf(fp, AUDIO_SETFD, (caddr_t)&idat, p);
505 goto out;
506 case OSS_SNDCTL_DSP_MAPINBUF:
507 case OSS_SNDCTL_DSP_MAPOUTBUF:
508 case OSS_SNDCTL_DSP_SETSYNCRO:
509 case OSS_SNDCTL_DSP_PROFILE:
510 error = EINVAL;
511 goto out;
512 default:
513 error = EINVAL;
514 goto out;
515 }
516
517 error = 0;
518
519 out:
520 FRELE(fp);
521 return (error);
522 }
523
524
525
526 #define NETBSD_MAXDEVS 64
527 struct audiodevinfo {
528 int done;
529 dev_t dev;
530 int16_t devmap[OSS_SOUND_MIXER_NRDEVICES],
531 rdevmap[NETBSD_MAXDEVS];
532 u_long devmask, recmask, stereomask;
533 u_long caps, source;
534 };
535
536
537
538
539
540
541
542 static struct audiodevinfo *
543 getdevinfo(fp, p)
544 struct file *fp;
545 struct proc *p;
546 {
547 mixer_devinfo_t mi;
548 int i;
549 static const struct oss_devs {
550 const char *name;
551 int code;
552 } devs[] = {
553 { AudioNmicrophone, OSS_SOUND_MIXER_MIC },
554 { AudioNline, OSS_SOUND_MIXER_LINE },
555 { AudioNcd, OSS_SOUND_MIXER_CD },
556 { AudioNdac, OSS_SOUND_MIXER_PCM },
557 { AudioNrecord, OSS_SOUND_MIXER_IMIX },
558 { AudioNmaster, OSS_SOUND_MIXER_VOLUME },
559 { AudioNtreble, OSS_SOUND_MIXER_TREBLE },
560 { AudioNbass, OSS_SOUND_MIXER_BASS },
561 { AudioNspeaker, OSS_SOUND_MIXER_SPEAKER },
562
563 { AudioNoutput, OSS_SOUND_MIXER_OGAIN },
564 { AudioNinput, OSS_SOUND_MIXER_IGAIN },
565
566
567
568 { AudioNfmsynth, OSS_SOUND_MIXER_SYNTH },
569
570 { AudioNmidi, OSS_SOUND_MIXER_SYNTH },
571
572 { 0, -1 }
573 };
574 register const struct oss_devs *dp;
575 int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *) =
576 fp->f_ops->fo_ioctl;
577 struct vnode *vp;
578 struct vattr va;
579 static struct audiodevinfo devcache = { 0 };
580 register struct audiodevinfo *di = &devcache;
581
582
583
584
585 vp = (struct vnode *)fp->f_data;
586 if (vp->v_type != VCHR)
587 return 0;
588 if (VOP_GETATTR(vp, &va, p->p_ucred, p))
589 return 0;
590 if (di->done && di->dev == va.va_rdev)
591 return di;
592
593 di->done = 1;
594 di->dev = va.va_rdev;
595 di->devmask = 0;
596 di->recmask = 0;
597 di->stereomask = 0;
598 di->source = -1;
599 di->caps = 0;
600 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
601 di->devmap[i] = -1;
602 for(i = 0; i < NETBSD_MAXDEVS; i++)
603 di->rdevmap[i] = -1;
604 for(i = 0; i < NETBSD_MAXDEVS; i++) {
605 mi.index = i;
606 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, (caddr_t)&mi, p) < 0)
607 break;
608 switch(mi.type) {
609 case AUDIO_MIXER_VALUE:
610 for(dp = devs; dp->name; dp++)
611 if (strcmp(dp->name, mi.label.name) == 0)
612 break;
613 if (dp->code >= 0) {
614 di->devmap[dp->code] = i;
615 di->rdevmap[i] = dp->code;
616 di->devmask |= 1 << dp->code;
617 if (mi.un.v.num_channels == 2)
618 di->stereomask |= 1 << dp->code;
619 }
620 break;
621 case AUDIO_MIXER_ENUM:
622 if (strcmp(mi.label.name, AudioNsource) == 0) {
623 int j;
624 di->source = i;
625 for(j = 0; j < mi.un.e.num_mem; j++)
626 di->recmask |= 1 << di->rdevmap[mi.un.e.member[j].ord];
627 di->caps = OSS_SOUND_CAP_EXCL_INPUT;
628 }
629 break;
630 case AUDIO_MIXER_SET:
631 if (strcmp(mi.label.name, AudioNsource) == 0) {
632 int j;
633 di->source = i;
634 for(j = 0; j < mi.un.s.num_mem; j++) {
635 int k, mask = mi.un.s.member[j].mask;
636 if (mask) {
637 for(k = 0; !(mask & 1); mask >>= 1, k++)
638 ;
639 di->recmask |= 1 << di->rdevmap[k];
640 }
641 }
642 }
643 break;
644 }
645 }
646 return di;
647 }
648
649 int
650 oss_ioctl_mixer(p, uap, retval)
651 struct proc *p;
652 struct oss_sys_ioctl_args
653
654
655
656 *uap;
657 register_t *retval;
658 {
659 struct file *fp;
660 struct filedesc *fdp;
661 u_long com;
662 struct audiodevinfo *di;
663 mixer_ctrl_t mc;
664 int idat;
665 int i;
666 int error;
667 int l, r, n;
668 int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
669
670 fdp = p->p_fd;
671 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
672 return (EBADF);
673 FREF(fp);
674
675 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
676 error = EBADF;
677 goto out;
678 }
679
680 com = SCARG(uap, com);
681 retval[0] = 0;
682
683 di = getdevinfo(fp, p);
684 if (di == 0) {
685 error = EINVAL;
686 goto out;
687 }
688
689 ioctlf = fp->f_ops->fo_ioctl;
690 switch (com) {
691 case OSS_SOUND_MIXER_READ_RECSRC:
692 if (di->source == -1) {
693 error = EINVAL;
694 goto out;
695 }
696 mc.dev = di->source;
697 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
698 mc.type = AUDIO_MIXER_ENUM;
699 error = ioctlf(fp, AUDIO_MIXER_READ, (caddr_t)&mc, p);
700 if (error)
701 goto out;
702 idat = 1 << di->rdevmap[mc.un.ord];
703 } else {
704 int k;
705 unsigned int mask;
706 mc.type = AUDIO_MIXER_SET;
707 error = ioctlf(fp, AUDIO_MIXER_READ, (caddr_t)&mc, p);
708 if (error)
709 goto out;
710 idat = 0;
711 for(mask = mc.un.mask, k = 0; mask; mask >>= 1, k++)
712 if (mask & 1)
713 idat |= 1 << di->rdevmap[k];
714 }
715 break;
716 case OSS_SOUND_MIXER_READ_DEVMASK:
717 idat = di->devmask;
718 break;
719 case OSS_SOUND_MIXER_READ_RECMASK:
720 idat = di->recmask;
721 break;
722 case OSS_SOUND_MIXER_READ_STEREODEVS:
723 idat = di->stereomask;
724 break;
725 case OSS_SOUND_MIXER_READ_CAPS:
726 idat = di->caps;
727 break;
728 case OSS_SOUND_MIXER_WRITE_RECSRC:
729 case OSS_SOUND_MIXER_WRITE_R_RECSRC:
730 if (di->source == -1) {
731 error = EINVAL;
732 goto out;
733 }
734 mc.dev = di->source;
735 error = copyin(SCARG(uap, data), &idat, sizeof idat);
736 if (error)
737 goto out;
738 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
739 mc.type = AUDIO_MIXER_ENUM;
740 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
741 if (idat & (1 << i))
742 break;
743 if (i >= OSS_SOUND_MIXER_NRDEVICES ||
744 di->devmap[i] == -1) {
745 error = EINVAL;
746 goto out;
747 }
748 mc.un.ord = di->devmap[i];
749 } else {
750 mc.type = AUDIO_MIXER_SET;
751 mc.un.mask = 0;
752 for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) {
753 if (idat & (1 << i)) {
754 if (di->devmap[i] == -1) {
755 error = EINVAL;
756 goto out;
757 }
758 mc.un.mask |= 1 << di->devmap[i];
759 }
760 }
761 }
762 error = ioctlf(fp, AUDIO_MIXER_WRITE, (caddr_t)&mc, p);
763 goto out;
764 default:
765 if (OSS_MIXER_READ(OSS_SOUND_MIXER_FIRST) <= com &&
766 com < OSS_MIXER_READ(OSS_SOUND_MIXER_NRDEVICES)) {
767 n = OSS_GET_DEV(com);
768 if (di->devmap[n] == -1) {
769 error = EINVAL;
770 goto out;
771 }
772 doread:
773 mc.dev = di->devmap[n];
774 mc.type = AUDIO_MIXER_VALUE;
775 mc.un.value.num_channels = di->stereomask & (1<<n) ? 2 : 1;
776 error = ioctlf(fp, AUDIO_MIXER_READ, (caddr_t)&mc, p);
777 if (error)
778 goto out;
779 if (mc.un.value.num_channels != 2) {
780 l = r = mc.un.value.level[AUDIO_MIXER_LEVEL_MONO];
781 } else {
782 l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT];
783 r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
784 }
785 idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8);
786 DPRINTF(("OSS_MIXER_READ n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
787 n, di->devmap[n], l, r, idat));
788 break;
789 } else if ((OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_FIRST) <= com &&
790 com < OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES)) ||
791 (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
792 com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES))) {
793 n = OSS_GET_DEV(com);
794 if (di->devmap[n] == -1) {
795 error = EINVAL;
796 goto out;
797 }
798 error = copyin(SCARG(uap, data), &idat, sizeof idat);
799 if (error)
800 goto out;
801 l = FROM_OSSVOL( idat & 0xff);
802 r = FROM_OSSVOL((idat >> 8) & 0xff);
803 mc.dev = di->devmap[n];
804 mc.type = AUDIO_MIXER_VALUE;
805 if (di->stereomask & (1<<n)) {
806 mc.un.value.num_channels = 2;
807 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
808 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
809 } else {
810 mc.un.value.num_channels = 1;
811 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r)/2;
812 }
813 DPRINTF(("OSS_MIXER_WRITE n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
814 n, di->devmap[n], l, r, idat));
815 error = ioctlf(fp, AUDIO_MIXER_WRITE, (caddr_t)&mc, p);
816 if (error)
817 goto out;
818 if (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
819 com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES)) {
820 error = 0;
821 goto out;
822 }
823 goto doread;
824 } else {
825 #ifdef AUDIO_DEBUG
826 printf("oss_audio: unknown mixer ioctl %04lx\n", com);
827 #endif
828 error = EINVAL;
829 goto out;
830 }
831 }
832 error = copyout(&idat, SCARG(uap, data), sizeof idat);
833
834 out:
835 FRELE(fp);
836 return (error);
837 }
838
839
840 int
841 oss_ioctl_sequencer(p, uap, retval)
842 struct proc *p;
843 struct oss_sys_ioctl_args
844
845
846
847 *uap;
848 register_t *retval;
849 {
850 struct file *fp;
851 struct filedesc *fdp;
852 #if 0
853 u_long com;
854 int idat;
855 int error;
856 #endif
857
858 fdp = p->p_fd;
859 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
860 return (EBADF);
861
862 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
863 return (EBADF);
864
865 #if 0
866 com = SCARG(uap, com);
867 #endif
868 retval[0] = 0;
869
870 return EINVAL;
871 }
872
873
874
875
876
877 static void setblocksize(fp, info, p)
878 struct file *fp;
879 struct audio_info *info;
880 struct proc *p;
881 {
882 struct audio_info set;
883 int s;
884
885 if (info->blocksize & (info->blocksize-1)) {
886 for(s = 32; s < info->blocksize; s <<= 1)
887 ;
888 AUDIO_INITINFO(&set);
889 set.blocksize = s;
890 fp->f_ops->fo_ioctl(fp, AUDIO_SETINFO, (caddr_t)&set, p);
891 fp->f_ops->fo_ioctl(fp, AUDIO_GETINFO, (caddr_t)info, p);
892 }
893 }