[BACK]Return to ossaudio.c CVS log [TXT][DIR] Up to [local] / sys / compat / ossaudio

Annotation of sys/compat/ossaudio/ossaudio.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ossaudio.c,v 1.11 2006/02/17 17:49:53 jolan Exp $     */
                      2: /*     $NetBSD: ossaudio.c,v 1.23 1997/10/19 07:41:52 augustss Exp $   */
                      3:
                      4: /*
                      5:  * Copyright (c) 1997 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *        This product includes software developed by the NetBSD
                     19:  *        Foundation, Inc. and its contributors.
                     20:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     21:  *    contributors may be used to endorse or promote products derived
                     22:  *    from this software without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     25:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     26:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     27:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     28:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     29:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     30:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     31:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     32:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     33:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     34:  * POSSIBILITY OF SUCH DAMAGE.
                     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:                syscallarg(int) fd;
                     72:                syscallarg(u_long) com;
                     73:                syscallarg(caddr_t) data;
                     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:                /* fall into ... */
                    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:                /* fall into ... */
                    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:                /* fall into ... */
                    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; /* XXX unimplemented */
                    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) /* 0 means set to max */
                    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; /* Don't report emulated modes */
                    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; /* pretend we have 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:                /* XXX Do nothing for now. */
                    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; /* XXX unimplemented */
                    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: /* If the NetBSD mixer device should have more than 32 devices
                    525:  * some will not be available to Linux */
                    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:  * Collect the audio device information to allow faster
                    538:  * emulation of the Linux mixer ioctls.  Cache the information
                    539:  * to eliminate the overhead of repeating all the ioctls needed
                    540:  * to collect the information.
                    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: /*             { AudioNheadphone,      ?? },*/
                    563:                { AudioNoutput,         OSS_SOUND_MIXER_OGAIN },
                    564:                { AudioNinput,          OSS_SOUND_MIXER_IGAIN },
                    565: /*             { AudioNmaster,         OSS_SOUND_MIXER_SPEAKER },*/
                    566: /*             { AudioNstereo,         ?? },*/
                    567: /*             { AudioNmono,           ?? },*/
                    568:                { AudioNfmsynth,        OSS_SOUND_MIXER_SYNTH },
                    569: /*             { AudioNwave,           OSS_SOUND_MIXER_PCM },*/
                    570:                { AudioNmidi,           OSS_SOUND_MIXER_SYNTH },
                    571: /*             { AudioNmixerout,       ?? },*/
                    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:        /* Figure out what device it is so we can check if the
                    583:         * cached data is valid.
                    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:                syscallarg(int) fd;
                    654:                syscallarg(u_long) com;
                    655:                syscallarg(caddr_t) data;
                    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: /* XXX hook for sequencer emulation */
                    840: int
                    841: oss_ioctl_sequencer(p, uap, retval)
                    842:        struct proc *p;
                    843:        struct oss_sys_ioctl_args /* {
                    844:                syscallarg(int) fd;
                    845:                syscallarg(u_long) com;
                    846:                syscallarg(caddr_t) data;
                    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:  * Check that the blocksize is a power of 2 as OSS wants.
                    875:  * If not, set it to be.
                    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: }

CVSweb