1 /* $NetBSD: ossaudio.c,v 1.64 2008/11/13 10:05:52 ad Exp $ */
4 * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.64 2008/11/13 10:05:52 ad Exp $");
32 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/vnode.h>
37 #include <sys/filedesc.h>
38 #include <sys/ioctl.h>
39 #include <sys/mount.h>
40 #include <sys/kernel.h>
41 #include <sys/audioio.h>
42 #include <sys/midiio.h>
43 #include <sys/kauth.h>
44 #include <sys/syscallargs.h>
45 #include <sys/module.h>
47 #include <compat/ossaudio/ossaudio.h>
48 #include <compat/ossaudio/ossaudiovar.h>
50 MODULE(MODULE_CLASS_MISC
, compat_ossaudio
, NULL
);
53 #define DPRINTF(x) if (ossdebug) printf x
59 #define TO_OSSVOL(x) (((x) * 100 + 127) / 255)
60 #define FROM_OSSVOL(x) ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100)
62 static struct audiodevinfo
*getdevinfo(file_t
*);
63 static int opaque_to_enum(struct audiodevinfo
*di
, audio_mixer_name_t
*label
, int opq
);
64 static int enum_to_ord(struct audiodevinfo
*di
, int enm
);
65 static int enum_to_mask(struct audiodevinfo
*di
, int enm
);
67 static void setblocksize(file_t
*, struct audio_info
*);
71 compat_ossaudio_getcmd(u_long cmd
)
78 _DO(OSS_SNDCTL_DSP_RESET
)
79 _DO(OSS_SNDCTL_DSP_SYNC
)
80 _DO(OSS_SNDCTL_DSP_SPEED
)
81 _DO(OSS_SOUND_PCM_READ_RATE
)
82 _DO(OSS_SNDCTL_DSP_STEREO
)
83 _DO(OSS_SNDCTL_DSP_GETBLKSIZE
)
84 _DO(OSS_SNDCTL_DSP_SETFMT
)
85 _DO(OSS_SOUND_PCM_READ_BITS
)
86 _DO(OSS_SNDCTL_DSP_CHANNELS
)
87 _DO(OSS_SOUND_PCM_READ_CHANNELS
)
88 _DO(OSS_SOUND_PCM_WRITE_FILTER
)
89 _DO(OSS_SOUND_PCM_READ_FILTER
)
90 _DO(OSS_SNDCTL_DSP_POST
)
91 _DO(OSS_SNDCTL_DSP_SUBDIVIDE
)
92 _DO(OSS_SNDCTL_DSP_SETFRAGMENT
)
93 _DO(OSS_SNDCTL_DSP_GETFMTS
)
94 _DO(OSS_SNDCTL_DSP_GETOSPACE
)
95 _DO(OSS_SNDCTL_DSP_GETISPACE
)
96 _DO(OSS_SNDCTL_DSP_NONBLOCK
)
97 _DO(OSS_SNDCTL_DSP_GETCAPS
)
98 _DO(OSS_SNDCTL_DSP_GETTRIGGER
)
99 _DO(OSS_SNDCTL_DSP_SETTRIGGER
)
100 _DO(OSS_SNDCTL_DSP_GETIPTR
)
101 _DO(OSS_SNDCTL_DSP_GETOPTR
)
102 _DO(OSS_SNDCTL_DSP_MAPINBUF
)
103 _DO(OSS_SNDCTL_DSP_MAPOUTBUF
)
104 _DO(OSS_SNDCTL_DSP_SETSYNCRO
)
105 _DO(OSS_SNDCTL_DSP_SETDUPLEX
)
106 _DO(OSS_SNDCTL_DSP_GETODELAY
)
107 _DO(OSS_SNDCTL_DSP_PROFILE
)
108 _DO(OSS_SOUND_MIXER_INFO
)
109 _DO(OSS_SOUND_OLD_MIXER_INFO
)
114 _DO(OSS_SEQ_CTRLRATE
)
115 _DO(OSS_SEQ_GETOUTCOUNT
)
116 _DO(OSS_SEQ_GETINCOUNT
)
117 _DO(OSS_SEQ_PERCMODE
)
118 _DO(OSS_SEQ_TESTMIDI
)
119 _DO(OSS_SEQ_RESETSAMPLES
)
120 _DO(OSS_SEQ_NRSYNTHS
)
125 _DO(OSS_SEQ_THRESHOLD
)
127 _DO(OSS_FM_4OP_ENABLE
)
129 _DO(OSS_SEQ_OUTOFBAND
)
133 _DO(OSS_REMOVESAMPLE
)
134 _DO(OSS_TMR_TIMEBASE
)
137 _DO(OSS_TMR_CONTINUE
)
140 _DO(OSS_TMR_METRONOME
)
144 (void)snprintf(buf
, sizeof(buf
), "*0x%lx*", cmd
);
152 compat_ossaudio_modcmd(modcmd_t cmd
, void *arg
)
156 case MODULE_CMD_INIT
:
157 case MODULE_CMD_FINI
:
165 oss_ioctl_audio(struct lwp
*l
, const struct oss_sys_ioctl_args
*uap
, register_t
*retval
)
169 syscallarg(u_long) com;
170 syscallarg(void *) data;
174 struct audio_info tmpinfo
;
175 struct audio_offset tmpoffs
;
176 struct oss_audio_buf_info bufinfo
;
177 struct oss_count_info cntinfo
;
178 struct audio_encoding tmpenc
;
182 int (*ioctlf
)(file_t
*, u_long
, void *);
184 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
)
187 if ((fp
->f_flag
& (FREAD
| FWRITE
)) == 0) {
192 com
= SCARG(uap
, com
);
193 DPRINTF(("%s: com=%s\n", __func__
, compat_ossaudio_getcmd(com
)));
197 ioctlf
= fp
->f_ops
->fo_ioctl
;
199 case OSS_SNDCTL_DSP_RESET
:
200 error
= ioctlf(fp
, AUDIO_FLUSH
, NULL
);
202 DPRINTF(("%s: AUDIO_FLUSH %d\n", __func__
, error
));
206 case OSS_SNDCTL_DSP_SYNC
:
207 error
= ioctlf(fp
, AUDIO_DRAIN
, NULL
);
209 DPRINTF(("%s: AUDIO_DRAIN %d\n", __func__
, error
));
213 case OSS_SNDCTL_DSP_POST
:
214 /* This call is merely advisory, and may be a nop. */
216 case OSS_SNDCTL_DSP_SPEED
:
217 AUDIO_INITINFO(&tmpinfo
);
218 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
220 DPRINTF(("%s: SNDCTL_DSP_SPEED %d\n",
224 tmpinfo
.play
.sample_rate
=
225 tmpinfo
.record
.sample_rate
= idat
;
226 DPRINTF(("%s: SNDCTL_DSP_SPEED > %d\n", __func__
, idat
));
227 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
229 DPRINTF(("%s: SNDCTL_DSP_SPEED %d = %d\n",
230 __func__
, idat
, error
));
234 case OSS_SOUND_PCM_READ_RATE
:
235 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
237 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
241 idat
= tmpinfo
.play
.sample_rate
;
242 DPRINTF(("%s: SNDCTL_PCM_READ_RATE < %d\n", __func__
, idat
));
243 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
245 DPRINTF(("%s: SOUND_PCM_READ_RATE %d = %d\n",
246 __func__
, idat
, error
));
250 case OSS_SNDCTL_DSP_STEREO
:
251 AUDIO_INITINFO(&tmpinfo
);
252 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
254 DPRINTF(("%s: SNDCTL_DSP_STEREO %d\n",
258 tmpinfo
.play
.channels
=
259 tmpinfo
.record
.channels
= idat
? 2 : 1;
260 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
262 DPRINTF(("%s: AUDIO_SETINFO %d\n",
266 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
268 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
272 idat
= tmpinfo
.play
.channels
- 1;
273 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
275 DPRINTF(("%s: SNDCTL_DSP_STEREO %d = %d\n",
276 __func__
, idat
, error
));
280 case OSS_SNDCTL_DSP_GETBLKSIZE
:
281 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
283 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
287 setblocksize(fp
, &tmpinfo
);
288 idat
= tmpinfo
.blocksize
;
289 DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE < %d\n",
291 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
293 DPRINTF(("%s: SNDCTL_DSP_GETBLKSIZE %d = %d\n",
294 __func__
, idat
, error
));
298 case OSS_SNDCTL_DSP_SETFMT
:
299 AUDIO_INITINFO(&tmpinfo
);
300 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
302 DPRINTF(("%s: SNDCTL_DSP_SETFMT %d\n",
307 case OSS_AFMT_MU_LAW
:
308 tmpinfo
.play
.precision
=
309 tmpinfo
.record
.precision
= 8;
310 tmpinfo
.play
.encoding
=
311 tmpinfo
.record
.encoding
= AUDIO_ENCODING_ULAW
;
314 tmpinfo
.play
.precision
=
315 tmpinfo
.record
.precision
= 8;
316 tmpinfo
.play
.encoding
=
317 tmpinfo
.record
.encoding
= AUDIO_ENCODING_ALAW
;
320 tmpinfo
.play
.precision
=
321 tmpinfo
.record
.precision
= 8;
322 tmpinfo
.play
.encoding
=
323 tmpinfo
.record
.encoding
= AUDIO_ENCODING_ULINEAR
;
326 tmpinfo
.play
.precision
=
327 tmpinfo
.record
.precision
= 8;
328 tmpinfo
.play
.encoding
=
329 tmpinfo
.record
.encoding
= AUDIO_ENCODING_SLINEAR
;
331 case OSS_AFMT_S16_LE
:
332 tmpinfo
.play
.precision
=
333 tmpinfo
.record
.precision
= 16;
334 tmpinfo
.play
.encoding
=
335 tmpinfo
.record
.encoding
= AUDIO_ENCODING_SLINEAR_LE
;
337 case OSS_AFMT_S16_BE
:
338 tmpinfo
.play
.precision
=
339 tmpinfo
.record
.precision
= 16;
340 tmpinfo
.play
.encoding
=
341 tmpinfo
.record
.encoding
= AUDIO_ENCODING_SLINEAR_BE
;
343 case OSS_AFMT_U16_LE
:
344 tmpinfo
.play
.precision
=
345 tmpinfo
.record
.precision
= 16;
346 tmpinfo
.play
.encoding
=
347 tmpinfo
.record
.encoding
= AUDIO_ENCODING_ULINEAR_LE
;
349 case OSS_AFMT_U16_BE
:
350 tmpinfo
.play
.precision
=
351 tmpinfo
.record
.precision
= 16;
352 tmpinfo
.play
.encoding
=
353 tmpinfo
.record
.encoding
= AUDIO_ENCODING_ULINEAR_BE
;
356 DPRINTF(("%s: SNDCTL_DSP_SETFMT bad fmt %d\n",
361 DPRINTF(("%s: SNDCTL_DSP_SETFMT > 0x%x\n",
363 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
365 DPRINTF(("%s: AUDIO_SETINFO %d\n",
370 case OSS_SOUND_PCM_READ_BITS
:
371 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
373 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
377 switch (tmpinfo
.play
.encoding
) {
378 case AUDIO_ENCODING_ULAW
:
379 idat
= OSS_AFMT_MU_LAW
;
381 case AUDIO_ENCODING_ALAW
:
382 idat
= OSS_AFMT_A_LAW
;
384 case AUDIO_ENCODING_SLINEAR_LE
:
385 if (tmpinfo
.play
.precision
== 16)
386 idat
= OSS_AFMT_S16_LE
;
390 case AUDIO_ENCODING_SLINEAR_BE
:
391 if (tmpinfo
.play
.precision
== 16)
392 idat
= OSS_AFMT_S16_BE
;
396 case AUDIO_ENCODING_ULINEAR_LE
:
397 if (tmpinfo
.play
.precision
== 16)
398 idat
= OSS_AFMT_U16_LE
;
402 case AUDIO_ENCODING_ULINEAR_BE
:
403 if (tmpinfo
.play
.precision
== 16)
404 idat
= OSS_AFMT_U16_BE
;
408 case AUDIO_ENCODING_ADPCM
:
409 idat
= OSS_AFMT_IMA_ADPCM
;
412 DPRINTF(("%s: SOUND_PCM_READ_BITS bad encoding %d\n",
413 __func__
, tmpinfo
.play
.encoding
));
417 DPRINTF(("%s: SOUND_PCM_READ_BITS < 0x%x\n",
419 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
421 DPRINTF(("%s: SOUND_PCM_READ_BITS %d = %d\n",
422 __func__
, idat
, error
));
426 case OSS_SNDCTL_DSP_CHANNELS
:
427 AUDIO_INITINFO(&tmpinfo
);
428 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
430 DPRINTF(("%s: SNDCTL_DSP_CHANNELS %d\n",
434 tmpinfo
.play
.channels
=
435 tmpinfo
.record
.channels
= idat
;
436 DPRINTF(("%s: SNDCTL_DSP_CHANNELS > %d\n", __func__
, idat
));
437 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
439 DPRINTF(("%s: AUDIO_SETINFO %d\n",
444 case OSS_SOUND_PCM_READ_CHANNELS
:
445 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
447 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
451 idat
= tmpinfo
.play
.channels
;
452 DPRINTF(("%s: SOUND_PCM_READ_CHANNELS < %d\n", __func__
, idat
));
453 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
455 DPRINTF(("%s: SOUND_PCM_READ_CHANNELS %d = %d\n",
456 __func__
, idat
, error
));
460 case OSS_SOUND_PCM_WRITE_FILTER
:
461 case OSS_SOUND_PCM_READ_FILTER
:
462 error
= EINVAL
; /* XXX unimplemented */
463 DPRINTF(("%s: SOUND_PCM_{READ,WRITE}_FILTER filter\n",
466 case OSS_SNDCTL_DSP_SUBDIVIDE
:
467 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
469 DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d\n",
473 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
475 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
479 setblocksize(fp
, &tmpinfo
);
481 idat
= tmpinfo
.play
.buffer_size
/ tmpinfo
.blocksize
;
482 idat
= (tmpinfo
.play
.buffer_size
/ idat
) & -4;
483 AUDIO_INITINFO(&tmpinfo
);
484 tmpinfo
.blocksize
= idat
;
485 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
487 DPRINTF(("%s: AUDIO_SETINFO %d\n",
491 idat
= tmpinfo
.play
.buffer_size
/ tmpinfo
.blocksize
;
492 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
494 DPRINTF(("%s: SNDCTL_DSP_SUBDIVIDE %d = %d\n",
495 __func__
, idat
, error
));
499 case OSS_SNDCTL_DSP_SETFRAGMENT
:
500 AUDIO_INITINFO(&tmpinfo
);
501 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
503 DPRINTF(("%s: DSP_SETFRAGMENT %d\n",
507 if ((idat
& 0xffff) < 4 || (idat
& 0xffff) > 17) {
508 DPRINTF(("%s: DSP_SETFRAGMENT bad ival%d\n",
513 tmpinfo
.blocksize
= 1 << (idat
& 0xffff);
514 tmpinfo
.hiwat
= (idat
>> 16) & 0x7fff;
515 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT blksize=%d, "
516 "hiwat=%d\n", __func__
, tmpinfo
.blocksize
, tmpinfo
.hiwat
));
517 if (tmpinfo
.hiwat
== 0) /* 0 means set to max */
518 tmpinfo
.hiwat
= 65536;
519 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
521 DPRINTF(("%s: AUDIO_SETINFO %d\n",
525 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
527 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
531 u
= tmpinfo
.blocksize
;
532 for(idat
= 0; u
> 1; idat
++, u
>>= 1)
534 idat
|= (tmpinfo
.hiwat
& 0x7fff) << 16;
535 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
537 DPRINTF(("%s: SNDCTL_DSP_SETFRAGMENT %d = %d\n",
538 __func__
, idat
, error
));
542 case OSS_SNDCTL_DSP_GETFMTS
:
543 for (idat
= 0, tmpenc
.index
= 0;
544 ioctlf(fp
, AUDIO_GETENC
, &tmpenc
) == 0;
546 switch(tmpenc
.encoding
) {
547 case AUDIO_ENCODING_ULAW
:
548 idat
|= OSS_AFMT_MU_LAW
;
550 case AUDIO_ENCODING_ALAW
:
551 idat
|= OSS_AFMT_A_LAW
;
553 case AUDIO_ENCODING_SLINEAR
:
556 case AUDIO_ENCODING_SLINEAR_LE
:
557 if (tmpenc
.precision
== 16)
558 idat
|= OSS_AFMT_S16_LE
;
562 case AUDIO_ENCODING_SLINEAR_BE
:
563 if (tmpenc
.precision
== 16)
564 idat
|= OSS_AFMT_S16_BE
;
568 case AUDIO_ENCODING_ULINEAR
:
571 case AUDIO_ENCODING_ULINEAR_LE
:
572 if (tmpenc
.precision
== 16)
573 idat
|= OSS_AFMT_U16_LE
;
577 case AUDIO_ENCODING_ULINEAR_BE
:
578 if (tmpenc
.precision
== 16)
579 idat
|= OSS_AFMT_U16_BE
;
583 case AUDIO_ENCODING_ADPCM
:
584 idat
|= OSS_AFMT_IMA_ADPCM
;
587 DPRINTF(("%s: SNDCTL_DSP_GETFMTS unknown %d\n",
588 __func__
, tmpenc
.encoding
));
592 DPRINTF(("%s: SNDCTL_DSP_GETFMTS < 0x%x\n",
594 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
596 DPRINTF(("%s: SNDCTL_DSP_GETFMTS = %x = %d\n",
597 __func__
, idat
, error
));
601 case OSS_SNDCTL_DSP_GETOSPACE
:
602 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
604 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
608 setblocksize(fp
, &tmpinfo
);
609 bufinfo
.fragsize
= tmpinfo
.blocksize
;
610 bufinfo
.fragments
= tmpinfo
.hiwat
-
611 (tmpinfo
.play
.seek
+ tmpinfo
.blocksize
- 1) /
613 bufinfo
.fragstotal
= tmpinfo
.hiwat
;
615 tmpinfo
.hiwat
* tmpinfo
.blocksize
- tmpinfo
.play
.seek
;
616 error
= copyout(&bufinfo
, SCARG(uap
, data
), sizeof bufinfo
);
618 DPRINTF(("%s: SNDCTL_DSP_GETOSPACE = %d\n",
623 case OSS_SNDCTL_DSP_GETISPACE
:
624 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
626 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
630 setblocksize(fp
, &tmpinfo
);
631 bufinfo
.fragsize
= tmpinfo
.blocksize
;
632 bufinfo
.fragments
= tmpinfo
.hiwat
-
633 (tmpinfo
.record
.seek
+ tmpinfo
.blocksize
- 1) /
635 bufinfo
.fragstotal
= tmpinfo
.hiwat
;
637 tmpinfo
.hiwat
* tmpinfo
.blocksize
- tmpinfo
.record
.seek
;
638 error
= copyout(&bufinfo
, SCARG(uap
, data
), sizeof bufinfo
);
640 DPRINTF(("%s: SNDCTL_DSP_GETISPACE %d %d %d %d = %d\n",
641 __func__
, bufinfo
.fragsize
, bufinfo
.fragments
,
642 bufinfo
.fragstotal
, bufinfo
.bytes
, error
));
646 case OSS_SNDCTL_DSP_NONBLOCK
:
648 error
= ioctlf(fp
, FIONBIO
, &idat
);
650 DPRINTF(("%s: SENDCLT_DSP_NONBLOCK %d\n",
655 case OSS_SNDCTL_DSP_GETCAPS
:
656 error
= ioctlf(fp
, AUDIO_GETPROPS
, &idata
);
658 DPRINTF(("%s: AUDIO_GETPROPS %d\n",
662 idat
= OSS_DSP_CAP_TRIGGER
; /* pretend we have trigger */
663 if (idata
& AUDIO_PROP_FULLDUPLEX
)
664 idat
|= OSS_DSP_CAP_DUPLEX
;
665 if (idata
& AUDIO_PROP_MMAP
)
666 idat
|= OSS_DSP_CAP_MMAP
;
667 DPRINTF(("%s: SNDCL_DSP_GETCAPS %s duplex, %smmap\n",
668 __func__
, (idat
& OSS_DSP_CAP_DUPLEX
) ? "full" : "half",
669 (idat
& OSS_DSP_CAP_MMAP
) ? "" : "no "));
670 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
672 DPRINTF(("%s: SNDCTL_DSP_GETCAPS %x = %d\n", __func__
,
678 case OSS_SNDCTL_DSP_GETTRIGGER
:
679 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
681 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
685 idat
= (tmpinfo
.play
.pause
? 0 : OSS_PCM_ENABLE_OUTPUT
) |
686 (tmpinfo
.record
.pause
? 0 : OSS_PCM_ENABLE_INPUT
);
687 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
689 DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n",
690 __func__
, idat
, error
));
694 case OSS_SNDCTL_DSP_SETTRIGGER
:
695 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
, p
);
697 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
701 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
703 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
707 tmpinfo
.play
.pause
= (idat
& OSS_PCM_ENABLE_OUTPUT
) == 0;
708 tmpinfo
.record
.pause
= (idat
& OSS_PCM_ENABLE_INPUT
) == 0;
709 error
= ioctlf(fp
, AUDIO_SETINFO
, &tmpinfo
);
711 DPRINTF(("%s: AUDIO_SETINFO %d\n",
715 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
717 DPRINTF(("%s: SNDCTL_DSP_SETRIGGER %x = %d\n",
718 __func__
, idat
, error
));
723 case OSS_SNDCTL_DSP_GETTRIGGER
:
724 case OSS_SNDCTL_DSP_SETTRIGGER
:
725 /* XXX Do nothing for now. */
726 idat
= OSS_PCM_ENABLE_OUTPUT
;
727 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
729 DPRINTF(("%s: SNDCTL_DSP_{GET,SET}RIGGER %x = %d\n",
730 __func__
, idat
, error
));
735 case OSS_SNDCTL_DSP_GETIPTR
:
736 error
= ioctlf(fp
, AUDIO_GETIOFFS
, &tmpoffs
);
738 DPRINTF(("%s: AUDIO_GETIOFFS %d\n",
742 cntinfo
.bytes
= tmpoffs
.samples
;
743 cntinfo
.blocks
= tmpoffs
.deltablks
;
744 cntinfo
.ptr
= tmpoffs
.offset
;
745 error
= copyout(&cntinfo
, SCARG(uap
, data
), sizeof cntinfo
);
747 DPRINTF(("%s: SNDCTL_DSP_GETIPTR %d\n",
752 case OSS_SNDCTL_DSP_GETOPTR
:
753 error
= ioctlf(fp
, AUDIO_GETOOFFS
, &tmpoffs
);
755 DPRINTF(("%s: AUDIO_GETOOFFS %d\n",
759 cntinfo
.bytes
= tmpoffs
.samples
;
760 cntinfo
.blocks
= tmpoffs
.deltablks
;
761 cntinfo
.ptr
= tmpoffs
.offset
;
762 error
= copyout(&cntinfo
, SCARG(uap
, data
), sizeof cntinfo
);
764 DPRINTF(("%s: SNDCTL_DSP_GETOPTR %d\n",
769 case OSS_SNDCTL_DSP_SETDUPLEX
:
771 error
= ioctlf(fp
, AUDIO_SETFD
, &idat
);
773 DPRINTF(("%s: AUDIO_SETFD %d = %d\n",
774 __func__
, idat
, error
));
778 case OSS_SNDCTL_DSP_MAPINBUF
:
779 DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPINBUF\n",
783 case OSS_SNDCTL_DSP_MAPOUTBUF
:
784 DPRINTF(("%s: Unimplemented SNDCTL_DSP_MAPOUTBUF\n",
788 case OSS_SNDCTL_DSP_SETSYNCRO
:
789 DPRINTF(("%s: Unimplemented SNDCTL_DSP_GETSYNCHRO\n",
793 case OSS_SNDCTL_DSP_GETODELAY
:
794 error
= ioctlf(fp
, AUDIO_GETBUFINFO
, &tmpinfo
);
796 DPRINTF(("%s: AUDIO_GETBUFINFO %d\n",
800 idat
= tmpinfo
.play
.seek
+ tmpinfo
.blocksize
/ 2;
801 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
803 DPRINTF(("%s: SNDCTL_DSP_GETODELAY %d\n",
808 case OSS_SNDCTL_DSP_PROFILE
:
809 /* This gives just a hint to the driver,
810 * implementing it as a NOP is ok
812 DPRINTF(("%s: SNDCTL_DSP_PROFILE\n", __func__
));
815 DPRINTF(("%s: Unimplemented 0x%lx\n", __func__
, com
));
821 fd_putfile(SCARG(uap
, fd
));
825 /* If the NetBSD mixer device should have more than 32 devices
826 * some will not be available to Linux */
827 #define NETBSD_MAXDEVS 64
828 struct audiodevinfo
{
831 int16_t devmap
[OSS_SOUND_MIXER_NRDEVICES
],
832 rdevmap
[NETBSD_MAXDEVS
];
833 char names
[NETBSD_MAXDEVS
][MAX_AUDIO_DEV_LEN
];
834 int enum2opaque
[NETBSD_MAXDEVS
];
835 u_long devmask
, recmask
, stereomask
;
840 opaque_to_enum(struct audiodevinfo
*di
, audio_mixer_name_t
*label
, int opq
)
844 for (i
= 0; i
< NETBSD_MAXDEVS
; i
++) {
845 o
= di
->enum2opaque
[i
];
848 if (o
== -1 && label
!= NULL
&&
849 !strncmp(di
->names
[i
], label
->name
, sizeof di
->names
[i
])) {
850 di
->enum2opaque
[i
] = opq
;
854 if (i
>= NETBSD_MAXDEVS
)
856 /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/
861 enum_to_ord(struct audiodevinfo
*di
, int enm
)
863 if (enm
>= NETBSD_MAXDEVS
)
866 /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/
867 return (di
->enum2opaque
[enm
]);
871 enum_to_mask(struct audiodevinfo
*di
, int enm
)
874 if (enm
>= NETBSD_MAXDEVS
)
877 m
= di
->enum2opaque
[enm
];
880 /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/
885 * Collect the audio device information to allow faster
886 * emulation of the Linux mixer ioctls. Cache the information
887 * to eliminate the overhead of repeating all the ioctls needed
888 * to collect the information.
890 static struct audiodevinfo
*
891 getdevinfo(file_t
*fp
)
895 static const struct {
899 { AudioNmicrophone
, OSS_SOUND_MIXER_MIC
},
900 { AudioNline
, OSS_SOUND_MIXER_LINE
},
901 { AudioNcd
, OSS_SOUND_MIXER_CD
},
902 { AudioNdac
, OSS_SOUND_MIXER_PCM
},
903 { AudioNaux
, OSS_SOUND_MIXER_LINE1
},
904 { AudioNrecord
, OSS_SOUND_MIXER_IMIX
},
905 { AudioNmaster
, OSS_SOUND_MIXER_VOLUME
},
906 { AudioNtreble
, OSS_SOUND_MIXER_TREBLE
},
907 { AudioNbass
, OSS_SOUND_MIXER_BASS
},
908 { AudioNspeaker
, OSS_SOUND_MIXER_SPEAKER
},
909 /* { AudioNheadphone, ?? },*/
910 { AudioNoutput
, OSS_SOUND_MIXER_OGAIN
},
911 { AudioNinput
, OSS_SOUND_MIXER_IGAIN
},
912 /* { AudioNmaster, OSS_SOUND_MIXER_SPEAKER },*/
913 /* { AudioNstereo, ?? },*/
914 /* { AudioNmono, ?? },*/
915 { AudioNfmsynth
, OSS_SOUND_MIXER_SYNTH
},
916 /* { AudioNwave, OSS_SOUND_MIXER_PCM },*/
917 { AudioNmidi
, OSS_SOUND_MIXER_SYNTH
},
918 /* { AudioNmixerout, ?? },*/
921 int (*ioctlf
)(file_t
*, u_long
, void *) = fp
->f_ops
->fo_ioctl
;
924 static struct audiodevinfo devcache
;
925 struct audiodevinfo
*di
= &devcache
;
929 * Figure out what device it is so we can check if the
930 * cached data is valid.
933 if (vp
->v_type
!= VCHR
)
935 if (VOP_GETATTR(vp
, &va
, kauth_cred_get()))
937 if (di
->done
&& di
->dev
== va
.va_rdev
)
941 di
->dev
= va
.va_rdev
;
947 for(i
= 0; i
< OSS_SOUND_MIXER_NRDEVICES
; i
++)
949 for(i
= 0; i
< NETBSD_MAXDEVS
; i
++) {
951 di
->names
[i
][0] = '\0';
952 di
->enum2opaque
[i
] = -1;
954 for(i
= 0; i
< NETBSD_MAXDEVS
; i
++) {
956 if (ioctlf(fp
, AUDIO_MIXER_DEVINFO
, &mi
) < 0)
959 case AUDIO_MIXER_VALUE
:
960 for(dp
= devs
; dp
->name
; dp
++) {
961 if (strcmp(dp
->name
, mi
.label
.name
) == 0)
963 dlen
= strlen(dp
->name
);
964 mlen
= strlen(mi
.label
.name
);
966 && mi
.label
.name
[mlen
-dlen
-1] == '.'
967 && strcmp(dp
->name
, mi
.label
.name
+ mlen
- dlen
) == 0)
971 di
->devmap
[dp
->code
] = i
;
972 di
->rdevmap
[i
] = dp
->code
;
973 di
->devmask
|= 1 << dp
->code
;
974 if (mi
.un
.v
.num_channels
== 2)
975 di
->stereomask
|= 1 << dp
->code
;
976 strncpy(di
->names
[i
], mi
.label
.name
,
977 sizeof di
->names
[i
]);
982 for(i
= 0; i
< NETBSD_MAXDEVS
; i
++) {
984 if (ioctlf(fp
, AUDIO_MIXER_DEVINFO
, &mi
) < 0)
986 if (strcmp(mi
.label
.name
, AudioNsource
) != 0)
990 case AUDIO_MIXER_ENUM
:
991 for(j
= 0; j
< mi
.un
.e
.num_mem
; j
++) {
992 e
= opaque_to_enum(di
,
993 &mi
.un
.e
.member
[j
].label
,
994 mi
.un
.e
.member
[j
].ord
);
996 di
->recmask
|= 1 << di
->rdevmap
[e
];
998 di
->caps
= OSS_SOUND_CAP_EXCL_INPUT
;
1000 case AUDIO_MIXER_SET
:
1001 for(j
= 0; j
< mi
.un
.s
.num_mem
; j
++) {
1002 e
= opaque_to_enum(di
,
1003 &mi
.un
.s
.member
[j
].label
,
1004 mi
.un
.s
.member
[j
].mask
);
1006 di
->recmask
|= 1 << di
->rdevmap
[e
];
1015 oss_ioctl_mixer(struct lwp
*lwp
, const struct oss_sys_ioctl_args
*uap
, register_t
*retval
)
1019 syscallarg(u_long) com;
1020 syscallarg(void *) data;
1024 struct audiodevinfo
*di
;
1026 struct oss_mixer_info omi
;
1027 struct audio_device adev
;
1032 int (*ioctlf
)(file_t
*, u_long
, void *);
1034 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
)
1037 if ((fp
->f_flag
& (FREAD
| FWRITE
)) == 0) {
1042 com
= SCARG(uap
, com
);
1043 DPRINTF(("%s: com=%s\n", __func__
, compat_ossaudio_getcmd(com
)));
1047 di
= getdevinfo(fp
);
1053 ioctlf
= fp
->f_ops
->fo_ioctl
;
1055 case OSS_GET_VERSION
:
1056 idat
= OSS_SOUND_VERSION
;
1058 case OSS_SOUND_MIXER_INFO
:
1059 case OSS_SOUND_OLD_MIXER_INFO
:
1060 error
= ioctlf(fp
, AUDIO_GETDEV
, &adev
);
1062 DPRINTF(("%s: AUDIO_GETDEV %d\n",
1066 omi
.modify_counter
= 1;
1067 strncpy(omi
.id
, adev
.name
, sizeof omi
.id
);
1068 strncpy(omi
.name
, adev
.name
, sizeof omi
.name
);
1069 error
= copyout(&omi
, SCARG(uap
, data
), OSS_IOCTL_SIZE(com
));
1071 DPRINTF(("%s: OSS_SOUND_MIXER_INFO %d\n",
1076 case OSS_SOUND_MIXER_READ_RECSRC
:
1077 if (di
->source
== -1) {
1078 DPRINTF(("%s: OSS_SOUND_MIXER_READ_RECSRC bad source\n",
1083 mc
.dev
= di
->source
;
1084 if (di
->caps
& OSS_SOUND_CAP_EXCL_INPUT
) {
1085 mc
.type
= AUDIO_MIXER_ENUM
;
1086 error
= ioctlf(fp
, AUDIO_MIXER_READ
, &mc
);
1088 DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
1092 e
= opaque_to_enum(di
, NULL
, mc
.un
.ord
);
1094 idat
= 1 << di
->rdevmap
[e
];
1096 mc
.type
= AUDIO_MIXER_SET
;
1097 error
= ioctlf(fp
, AUDIO_MIXER_READ
, &mc
);
1099 DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
1103 e
= opaque_to_enum(di
, NULL
, mc
.un
.mask
);
1105 idat
= 1 << di
->rdevmap
[e
];
1108 case OSS_SOUND_MIXER_READ_DEVMASK
:
1111 case OSS_SOUND_MIXER_READ_RECMASK
:
1114 case OSS_SOUND_MIXER_READ_STEREODEVS
:
1115 idat
= di
->stereomask
;
1117 case OSS_SOUND_MIXER_READ_CAPS
:
1120 case OSS_SOUND_MIXER_WRITE_RECSRC
:
1121 case OSS_SOUND_MIXER_WRITE_R_RECSRC
:
1122 if (di
->source
== -1) {
1123 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC bad "
1124 "source\n", __func__
));
1128 mc
.dev
= di
->source
;
1129 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1131 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC %d\n",
1135 if (di
->caps
& OSS_SOUND_CAP_EXCL_INPUT
) {
1136 mc
.type
= AUDIO_MIXER_ENUM
;
1137 for(i
= 0; i
< OSS_SOUND_MIXER_NRDEVICES
; i
++)
1138 if (idat
& (1 << i
))
1140 if (i
>= OSS_SOUND_MIXER_NRDEVICES
||
1141 di
->devmap
[i
] == -1) {
1143 DPRINTF(("%s: OSS_SOUND_MIXER_WRITE_RECSRC "
1144 "bad index %d\n", __func__
, i
));
1147 mc
.un
.ord
= enum_to_ord(di
, di
->devmap
[i
]);
1149 mc
.type
= AUDIO_MIXER_SET
;
1151 for(i
= 0; i
< OSS_SOUND_MIXER_NRDEVICES
; i
++) {
1152 if (idat
& (1 << i
)) {
1153 if (di
->devmap
[i
] == -1) {
1154 DPRINTF(("%s: OSS_SOUND_MIXER_"
1155 "WRITE_RECSRC bad devmap "
1156 "%d\n", __func__
, i
));
1160 mc
.un
.mask
|= enum_to_mask(di
,
1165 error
= ioctlf(fp
, AUDIO_MIXER_WRITE
, &mc
);
1167 DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n",
1173 if (OSS_MIXER_READ(OSS_SOUND_MIXER_FIRST
) <= com
&&
1174 com
< OSS_MIXER_READ(OSS_SOUND_MIXER_NRDEVICES
)) {
1175 n
= OSS_GET_DEV(com
);
1176 if (di
->devmap
[n
] == -1) {
1177 DPRINTF(("%s: 0x%lx bad devmap %d\n",
1183 mc
.dev
= di
->devmap
[n
];
1184 mc
.type
= AUDIO_MIXER_VALUE
;
1185 mc
.un
.value
.num_channels
= di
->stereomask
&
1187 error
= ioctlf(fp
, AUDIO_MIXER_READ
, &mc
);
1189 DPRINTF(("%s: AUDIO_MIXER_READ %d\n",
1193 if (mc
.un
.value
.num_channels
!= 2) {
1195 mc
.un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
];
1197 l
= mc
.un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
];
1198 r
= mc
.un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
];
1200 idat
= TO_OSSVOL(l
) | (TO_OSSVOL(r
) << 8);
1201 DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
1202 __func__
, n
, di
->devmap
[n
], l
, r
, idat
));
1204 } else if ((OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_FIRST
) <= com
&&
1205 com
< OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES
)) ||
1206 (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST
) <= com
&&
1207 com
< OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES
))) {
1208 n
= OSS_GET_DEV(com
);
1209 if (di
->devmap
[n
] == -1) {
1210 DPRINTF(("%s: 0x%lx bad devmap %d\n",
1215 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1217 DPRINTF(("%s: 0x%lx error %d\n",
1218 __func__
, com
, error
));
1221 l
= FROM_OSSVOL( idat
& 0xff);
1222 r
= FROM_OSSVOL((idat
>> 8) & 0xff);
1223 mc
.dev
= di
->devmap
[n
];
1224 mc
.type
= AUDIO_MIXER_VALUE
;
1225 if (di
->stereomask
& (1 << n
)) {
1226 mc
.un
.value
.num_channels
= 2;
1227 mc
.un
.value
.level
[AUDIO_MIXER_LEVEL_LEFT
] = l
;
1228 mc
.un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] = r
;
1230 mc
.un
.value
.num_channels
= 1;
1231 mc
.un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
] =
1234 DPRINTF(("%s: n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
1235 __func__
, n
, di
->devmap
[n
], l
, r
, idat
));
1236 error
= ioctlf(fp
, AUDIO_MIXER_WRITE
, &mc
);
1238 DPRINTF(("%s: AUDIO_MIXER_WRITE %d\n",
1242 if (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST
) <= com
&&
1243 com
< OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES
)) {
1249 DPRINTF(("%s: Unknown mixer ioctl 0x%lx\n", __func__
,
1255 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
1257 fd_putfile(SCARG(uap
, fd
));
1261 /* Sequencer emulation */
1263 oss_ioctl_sequencer(struct lwp
*l
, const struct oss_sys_ioctl_args
*uap
, register_t
*retval
)
1267 syscallarg(u_long) com;
1268 syscallarg(void *) data;
1273 struct synth_info si
;
1274 struct oss_synth_info osi
;
1275 struct oss_seq_event_rec oser
;
1277 int (*ioctlf
)(file_t
*, u_long
, void *);
1279 if ((fp
= fd_getfile(SCARG(uap
, fd
))) == NULL
)
1282 if ((fp
->f_flag
& (FREAD
| FWRITE
)) == 0) {
1287 com
= SCARG(uap
, com
);
1288 DPRINTF(("%s: com=%s\n", __func__
, compat_ossaudio_getcmd(com
)));
1292 ioctlf
= fp
->f_ops
->fo_ioctl
;
1295 error
= ioctlf(fp
, SEQUENCER_RESET
, &idat
);
1298 error
= ioctlf(fp
, SEQUENCER_SYNC
, &idat
);
1300 case OSS_SYNTH_INFO
:
1301 error
= copyin(SCARG(uap
, data
), &osi
, sizeof osi
);
1304 si
.device
= osi
.device
;
1305 error
= ioctlf(fp
, SEQUENCER_INFO
, &si
);
1308 strncpy(osi
.name
, si
.name
, sizeof osi
.name
);
1309 osi
.device
= si
.device
;
1310 switch(si
.synth_type
) {
1312 osi
.synth_type
= OSS_SYNTH_TYPE_FM
; break;
1313 case SYNTH_TYPE_SAMPLE
:
1314 osi
.synth_type
= OSS_SYNTH_TYPE_SAMPLE
; break;
1315 case SYNTH_TYPE_MIDI
:
1316 osi
.synth_type
= OSS_SYNTH_TYPE_MIDI
; break;
1318 osi
.synth_type
= 0; break;
1320 switch(si
.synth_subtype
) {
1321 case SYNTH_SUB_FM_TYPE_ADLIB
:
1322 osi
.synth_subtype
= OSS_FM_TYPE_ADLIB
; break;
1323 case SYNTH_SUB_FM_TYPE_OPL3
:
1324 osi
.synth_subtype
= OSS_FM_TYPE_OPL3
; break;
1325 case SYNTH_SUB_MIDI_TYPE_MPU401
:
1326 osi
.synth_subtype
= OSS_MIDI_TYPE_MPU401
; break;
1327 case SYNTH_SUB_SAMPLE_TYPE_BASIC
:
1328 osi
.synth_subtype
= OSS_SAMPLE_TYPE_BASIC
; break;
1330 osi
.synth_subtype
= 0; break;
1333 osi
.nr_voices
= si
.nr_voices
;
1335 osi
.instr_bank_size
= si
.instr_bank_size
;
1336 osi
.capabilities
= 0;
1337 if (si
.capabilities
& SYNTH_CAP_OPL3
)
1338 osi
.capabilities
|= OSS_SYNTH_CAP_OPL3
;
1339 if (si
.capabilities
& SYNTH_CAP_INPUT
)
1340 osi
.capabilities
|= OSS_SYNTH_CAP_INPUT
;
1341 error
= copyout(&osi
, SCARG(uap
, data
), sizeof osi
);
1343 case OSS_SEQ_CTRLRATE
:
1344 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1347 error
= ioctlf(fp
, SEQUENCER_CTRLRATE
, &idat
);
1352 case OSS_SEQ_GETOUTCOUNT
:
1353 error
= ioctlf(fp
, SEQUENCER_GETOUTCOUNT
, &idat
);
1358 case OSS_SEQ_GETINCOUNT
:
1359 error
= ioctlf(fp
, SEQUENCER_GETINCOUNT
, &idat
);
1364 case OSS_SEQ_NRSYNTHS
:
1365 error
= ioctlf(fp
, SEQUENCER_NRSYNTHS
, &idat
);
1370 case OSS_SEQ_NRMIDIS
:
1371 error
= ioctlf(fp
, SEQUENCER_NRMIDIS
, &idat
);
1376 case OSS_SEQ_THRESHOLD
:
1377 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1380 error
= ioctlf(fp
, SEQUENCER_THRESHOLD
, &idat
);
1383 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1386 error
= ioctlf(fp
, SEQUENCER_MEMAVL
, &idat
);
1392 error
= ioctlf(fp
, SEQUENCER_PANIC
, &idat
);
1394 case OSS_SEQ_OUTOFBAND
:
1395 error
= copyin(SCARG(uap
, data
), &oser
, sizeof oser
);
1398 error
= ioctlf(fp
, SEQUENCER_OUTOFBAND
, &oser
);
1402 case OSS_SEQ_GETTIME
:
1403 error
= ioctlf(fp
, SEQUENCER_GETTIME
, &idat
);
1408 case OSS_TMR_TIMEBASE
:
1409 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1412 error
= ioctlf(fp
, SEQUENCER_TMR_TIMEBASE
, &idat
);
1418 error
= ioctlf(fp
, SEQUENCER_TMR_START
, &idat
);
1421 error
= ioctlf(fp
, SEQUENCER_TMR_STOP
, &idat
);
1423 case OSS_TMR_CONTINUE
:
1424 error
= ioctlf(fp
, SEQUENCER_TMR_CONTINUE
, &idat
);
1427 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1430 error
= ioctlf(fp
, SEQUENCER_TMR_TEMPO
, &idat
);
1435 case OSS_TMR_SOURCE
:
1436 error
= copyin(SCARG(uap
, data
), &idat1
, sizeof idat
);
1440 if (idat1
& OSS_TMR_INTERNAL
) idat
|= SEQUENCER_TMR_INTERNAL
;
1441 error
= ioctlf(fp
, SEQUENCER_TMR_SOURCE
, &idat
);
1445 if (idat1
& SEQUENCER_TMR_INTERNAL
) idat
|= OSS_TMR_INTERNAL
;
1448 case OSS_TMR_METRONOME
:
1449 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1452 error
= ioctlf(fp
, SEQUENCER_TMR_METRONOME
, &idat
);
1454 case OSS_TMR_SELECT
:
1455 error
= copyin(SCARG(uap
, data
), &idat
, sizeof idat
);
1459 error
= ioctlf(fp
, SEQUENCER_TMR_SELECT
, &idat
);
1462 DPRINTF(("%s: Unknown sequencer command 0x%lx\n", __func__
,
1468 error
= copyout(&idat
, SCARG(uap
, data
), sizeof idat
);
1470 fd_putfile(SCARG(uap
, fd
));
1475 * Check that the blocksize is a power of 2 as OSS wants.
1476 * If not, set it to be.
1479 setblocksize(file_t
*fp
, struct audio_info
*info
)
1481 struct audio_info set
;
1484 if (info
->blocksize
& (info
->blocksize
-1)) {
1485 for(s
= 32; s
< info
->blocksize
; s
<<= 1)
1487 AUDIO_INITINFO(&set
);
1489 fp
->f_ops
->fo_ioctl(fp
, AUDIO_SETINFO
, &set
);
1490 fp
->f_ops
->fo_ioctl(fp
, AUDIO_GETBUFINFO
, info
);