The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/ossaudio/ossaudio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ossaudio.c,v 1.63 2008/04/28 20:23:45 martin Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   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.
   15  *
   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.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: ossaudio.c,v 1.63 2008/04/28 20:23:45 martin Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/proc.h>
   34 #include <sys/systm.h>
   35 #include <sys/file.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 
   46 #include <compat/ossaudio/ossaudio.h>
   47 #include <compat/ossaudio/ossaudiovar.h>
   48 
   49 #ifdef AUDIO_DEBUG
   50 #define DPRINTF(x) if (ossdebug) printf x
   51 int ossdebug = 0;
   52 #else
   53 #define DPRINTF(x)
   54 #endif
   55 
   56 #define TO_OSSVOL(x)    (((x) * 100 + 127) / 255)
   57 #define FROM_OSSVOL(x)  ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100)
   58 
   59 static struct audiodevinfo *getdevinfo(file_t *);
   60 static int opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq);
   61 static int enum_to_ord(struct audiodevinfo *di, int enm);
   62 static int enum_to_mask(struct audiodevinfo *di, int enm);
   63 
   64 static void setblocksize(file_t *, struct audio_info *);
   65 
   66 
   67 int
   68 oss_ioctl_audio(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval)
   69 {
   70         /* {
   71                 syscallarg(int) fd;
   72                 syscallarg(u_long) com;
   73                 syscallarg(void *) data;
   74         } */
   75         file_t *fp;
   76         u_long com;
   77         struct audio_info tmpinfo;
   78         struct audio_offset tmpoffs;
   79         struct oss_audio_buf_info bufinfo;
   80         struct oss_count_info cntinfo;
   81         struct audio_encoding tmpenc;
   82         u_int u;
   83         int idat, idata;
   84         int error = 0;
   85         int (*ioctlf)(file_t *, u_long, void *);
   86 
   87         if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
   88                 return (EBADF);
   89 
   90         if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
   91                 error = EBADF;
   92                 goto out;
   93         }
   94 
   95         com = SCARG(uap, com);
   96         DPRINTF(("oss_ioctl_audio: com=%08lx\n", com));
   97 
   98         retval[0] = 0;
   99 
  100         ioctlf = fp->f_ops->fo_ioctl;
  101         switch (com) {
  102         case OSS_SNDCTL_DSP_RESET:
  103                 error = ioctlf(fp, AUDIO_FLUSH, NULL);
  104                 if (error)
  105                         goto out;
  106                 break;
  107         case OSS_SNDCTL_DSP_SYNC:
  108                 error = ioctlf(fp, AUDIO_DRAIN, NULL);
  109                 if (error)
  110                         goto out;
  111                 break;
  112         case OSS_SNDCTL_DSP_POST:
  113                 /* This call is merely advisory, and may be a nop. */
  114                 break;
  115         case OSS_SNDCTL_DSP_SPEED:
  116                 AUDIO_INITINFO(&tmpinfo);
  117                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  118                 if (error)
  119                         goto out;
  120                 tmpinfo.play.sample_rate =
  121                 tmpinfo.record.sample_rate = idat;
  122                 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  123                 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_SPEED %d = %d\n",
  124                          idat, error));
  125                 if (error)
  126                         goto out;
  127                 /* fall into ... */
  128         case OSS_SOUND_PCM_READ_RATE:
  129                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  130                 if (error)
  131                         goto out;
  132                 idat = tmpinfo.play.sample_rate;
  133                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  134                 if (error)
  135                         goto out;
  136                 break;
  137         case OSS_SNDCTL_DSP_STEREO:
  138                 AUDIO_INITINFO(&tmpinfo);
  139                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  140                 if (error)
  141                         goto out;
  142                 tmpinfo.play.channels =
  143                 tmpinfo.record.channels = idat ? 2 : 1;
  144                 (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  145                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  146                 if (error)
  147                         goto out;
  148                 idat = tmpinfo.play.channels - 1;
  149                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  150                 if (error)
  151                         goto out;
  152                 break;
  153         case OSS_SNDCTL_DSP_GETBLKSIZE:
  154                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  155                 if (error)
  156                         goto out;
  157                 setblocksize(fp, &tmpinfo);
  158                 idat = tmpinfo.blocksize;
  159                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  160                 if (error)
  161                         goto out;
  162                 break;
  163         case OSS_SNDCTL_DSP_SETFMT:
  164                 AUDIO_INITINFO(&tmpinfo);
  165                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  166                 if (error)
  167                         goto out;
  168                 switch (idat) {
  169                 case OSS_AFMT_MU_LAW:
  170                         tmpinfo.play.precision =
  171                         tmpinfo.record.precision = 8;
  172                         tmpinfo.play.encoding =
  173                         tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
  174                         break;
  175                 case OSS_AFMT_A_LAW:
  176                         tmpinfo.play.precision =
  177                         tmpinfo.record.precision = 8;
  178                         tmpinfo.play.encoding =
  179                         tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
  180                         break;
  181                 case OSS_AFMT_U8:
  182                         tmpinfo.play.precision =
  183                         tmpinfo.record.precision = 8;
  184                         tmpinfo.play.encoding =
  185                         tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR;
  186                         break;
  187                 case OSS_AFMT_S8:
  188                         tmpinfo.play.precision =
  189                         tmpinfo.record.precision = 8;
  190                         tmpinfo.play.encoding =
  191                         tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR;
  192                         break;
  193                 case OSS_AFMT_S16_LE:
  194                         tmpinfo.play.precision =
  195                         tmpinfo.record.precision = 16;
  196                         tmpinfo.play.encoding =
  197                         tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
  198                         break;
  199                 case OSS_AFMT_S16_BE:
  200                         tmpinfo.play.precision =
  201                         tmpinfo.record.precision = 16;
  202                         tmpinfo.play.encoding =
  203                         tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
  204                         break;
  205                 case OSS_AFMT_U16_LE:
  206                         tmpinfo.play.precision =
  207                         tmpinfo.record.precision = 16;
  208                         tmpinfo.play.encoding =
  209                         tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE;
  210                         break;
  211                 case OSS_AFMT_U16_BE:
  212                         tmpinfo.play.precision =
  213                         tmpinfo.record.precision = 16;
  214                         tmpinfo.play.encoding =
  215                         tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
  216                         break;
  217                 default:
  218                         error = EINVAL;
  219                         goto out;
  220                 }
  221                 (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  222                 /* fall into ... */
  223         case OSS_SOUND_PCM_READ_BITS:
  224                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  225                 if (error)
  226                         goto out;
  227                 switch (tmpinfo.play.encoding) {
  228                 case AUDIO_ENCODING_ULAW:
  229                         idat = OSS_AFMT_MU_LAW;
  230                         break;
  231                 case AUDIO_ENCODING_ALAW:
  232                         idat = OSS_AFMT_A_LAW;
  233                         break;
  234                 case AUDIO_ENCODING_SLINEAR_LE:
  235                         if (tmpinfo.play.precision == 16)
  236                                 idat = OSS_AFMT_S16_LE;
  237                         else
  238                                 idat = OSS_AFMT_S8;
  239                         break;
  240                 case AUDIO_ENCODING_SLINEAR_BE:
  241                         if (tmpinfo.play.precision == 16)
  242                                 idat = OSS_AFMT_S16_BE;
  243                         else
  244                                 idat = OSS_AFMT_S8;
  245                         break;
  246                 case AUDIO_ENCODING_ULINEAR_LE:
  247                         if (tmpinfo.play.precision == 16)
  248                                 idat = OSS_AFMT_U16_LE;
  249                         else
  250                                 idat = OSS_AFMT_U8;
  251                         break;
  252                 case AUDIO_ENCODING_ULINEAR_BE:
  253                         if (tmpinfo.play.precision == 16)
  254                                 idat = OSS_AFMT_U16_BE;
  255                         else
  256                                 idat = OSS_AFMT_U8;
  257                         break;
  258                 case AUDIO_ENCODING_ADPCM:
  259                         idat = OSS_AFMT_IMA_ADPCM;
  260                         break;
  261                 }
  262                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  263                 if (error)
  264                         goto out;
  265                 break;
  266         case OSS_SNDCTL_DSP_CHANNELS:
  267                 AUDIO_INITINFO(&tmpinfo);
  268                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  269                 if (error)
  270                         goto out;
  271                 tmpinfo.play.channels =
  272                 tmpinfo.record.channels = idat;
  273                 (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  274                 /* fall into ... */
  275         case OSS_SOUND_PCM_READ_CHANNELS:
  276                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  277                 if (error)
  278                         goto out;
  279                 idat = tmpinfo.play.channels;
  280                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  281                 if (error)
  282                         goto out;
  283                 break;
  284         case OSS_SOUND_PCM_WRITE_FILTER:
  285         case OSS_SOUND_PCM_READ_FILTER:
  286                 error = EINVAL; /* XXX unimplemented */
  287                 goto out;
  288         case OSS_SNDCTL_DSP_SUBDIVIDE:
  289                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  290                 if (error)
  291                         goto out;
  292                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  293                 setblocksize(fp, &tmpinfo);
  294                 if (error)
  295                         goto out;
  296                 if (idat == 0)
  297                         idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
  298                 idat = (tmpinfo.play.buffer_size / idat) & -4;
  299                 AUDIO_INITINFO(&tmpinfo);
  300                 tmpinfo.blocksize = idat;
  301                 error = ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  302                 if (error)
  303                         goto out;
  304                 idat = tmpinfo.play.buffer_size / tmpinfo.blocksize;
  305                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  306                 if (error)
  307                         goto out;
  308                 break;
  309         case OSS_SNDCTL_DSP_SETFRAGMENT:
  310                 AUDIO_INITINFO(&tmpinfo);
  311                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  312                 if (error)
  313                         goto out;
  314                 if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) {
  315                         error = EINVAL;
  316                         goto out;
  317                 }
  318                 tmpinfo.blocksize = 1 << (idat & 0xffff);
  319                 tmpinfo.hiwat = (idat >> 16) & 0x7fff;
  320                 DPRINTF(("oss_audio: SETFRAGMENT blksize=%d, hiwat=%d\n",
  321                          tmpinfo.blocksize, tmpinfo.hiwat));
  322                 if (tmpinfo.hiwat == 0) /* 0 means set to max */
  323                         tmpinfo.hiwat = 65536;
  324                 (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  325                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  326                 if (error)
  327                         goto out;
  328                 u = tmpinfo.blocksize;
  329                 for(idat = 0; u > 1; idat++, u >>= 1)
  330                         ;
  331                 idat |= (tmpinfo.hiwat & 0x7fff) << 16;
  332                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  333                 if (error)
  334                         goto out;
  335                 break;
  336         case OSS_SNDCTL_DSP_GETFMTS:
  337                 for(idat = 0, tmpenc.index = 0;
  338                     ioctlf(fp, AUDIO_GETENC, &tmpenc) == 0;
  339                     tmpenc.index++) {
  340                         switch(tmpenc.encoding) {
  341                         case AUDIO_ENCODING_ULAW:
  342                                 idat |= OSS_AFMT_MU_LAW;
  343                                 break;
  344                         case AUDIO_ENCODING_ALAW:
  345                                 idat |= OSS_AFMT_A_LAW;
  346                                 break;
  347                         case AUDIO_ENCODING_SLINEAR:
  348                                 idat |= OSS_AFMT_S8;
  349                                 break;
  350                         case AUDIO_ENCODING_SLINEAR_LE:
  351                                 if (tmpenc.precision == 16)
  352                                         idat |= OSS_AFMT_S16_LE;
  353                                 else
  354                                         idat |= OSS_AFMT_S8;
  355                                 break;
  356                         case AUDIO_ENCODING_SLINEAR_BE:
  357                                 if (tmpenc.precision == 16)
  358                                         idat |= OSS_AFMT_S16_BE;
  359                                 else
  360                                         idat |= OSS_AFMT_S8;
  361                                 break;
  362                         case AUDIO_ENCODING_ULINEAR:
  363                                 idat |= OSS_AFMT_U8;
  364                                 break;
  365                         case AUDIO_ENCODING_ULINEAR_LE:
  366                                 if (tmpenc.precision == 16)
  367                                         idat |= OSS_AFMT_U16_LE;
  368                                 else
  369                                         idat |= OSS_AFMT_U8;
  370                                 break;
  371                         case AUDIO_ENCODING_ULINEAR_BE:
  372                                 if (tmpenc.precision == 16)
  373                                         idat |= OSS_AFMT_U16_BE;
  374                                 else
  375                                         idat |= OSS_AFMT_U8;
  376                                 break;
  377                         case AUDIO_ENCODING_ADPCM:
  378                                 idat |= OSS_AFMT_IMA_ADPCM;
  379                                 break;
  380                         default:
  381                                 break;
  382                         }
  383                 }
  384                 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETFMTS = %x\n", idat));
  385                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  386                 if (error)
  387                         goto out;
  388                 break;
  389         case OSS_SNDCTL_DSP_GETOSPACE:
  390                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  391                 if (error)
  392                         goto out;
  393                 setblocksize(fp, &tmpinfo);
  394                 bufinfo.fragsize = tmpinfo.blocksize;
  395                 bufinfo.fragments = tmpinfo.hiwat -
  396                     (tmpinfo.play.seek + tmpinfo.blocksize - 1) /
  397                     tmpinfo.blocksize;
  398                 bufinfo.fragstotal = tmpinfo.hiwat;
  399                 bufinfo.bytes =
  400                     tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek;
  401                 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
  402                 if (error)
  403                         goto out;
  404                 break;
  405         case OSS_SNDCTL_DSP_GETISPACE:
  406                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  407                 if (error)
  408                         goto out;
  409                 setblocksize(fp, &tmpinfo);
  410                 bufinfo.fragsize = tmpinfo.blocksize;
  411                 bufinfo.fragments = tmpinfo.hiwat -
  412                     (tmpinfo.record.seek + tmpinfo.blocksize - 1) /
  413                     tmpinfo.blocksize;
  414                 bufinfo.fragstotal = tmpinfo.hiwat;
  415                 bufinfo.bytes =
  416                     tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.record.seek;
  417                 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETxSPACE = %d %d %d %d\n",
  418                          bufinfo.fragsize, bufinfo.fragments,
  419                          bufinfo.fragstotal, bufinfo.bytes));
  420                 error = copyout(&bufinfo, SCARG(uap, data), sizeof bufinfo);
  421                 if (error)
  422                         goto out;
  423                 break;
  424         case OSS_SNDCTL_DSP_NONBLOCK:
  425                 idat = 1;
  426                 error = ioctlf(fp, FIONBIO, &idat);
  427                 if (error)
  428                         goto out;
  429                 break;
  430         case OSS_SNDCTL_DSP_GETCAPS:
  431                 error = ioctlf(fp, AUDIO_GETPROPS, &idata);
  432                 if (error)
  433                         goto out;
  434                 idat = OSS_DSP_CAP_TRIGGER; /* pretend we have trigger */
  435                 if (idata & AUDIO_PROP_FULLDUPLEX)
  436                         idat |= OSS_DSP_CAP_DUPLEX;
  437                 if (idata & AUDIO_PROP_MMAP)
  438                         idat |= OSS_DSP_CAP_MMAP;
  439                 DPRINTF(("oss_sys_ioctl: SNDCTL_DSP_GETCAPS = %x\n", idat));
  440                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  441                 if (error)
  442                         goto out;
  443                 break;
  444 #if 0
  445         case OSS_SNDCTL_DSP_GETTRIGGER:
  446                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  447                 if (error)
  448                         goto out;
  449                 idat = (tmpinfo.play.pause ? 0 : OSS_PCM_ENABLE_OUTPUT) |
  450                        (tmpinfo.record.pause ? 0 : OSS_PCM_ENABLE_INPUT);
  451                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  452                 if (error)
  453                         goto out;
  454                 break;
  455         case OSS_SNDCTL_DSP_SETTRIGGER:
  456                 (void) ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo, p);
  457                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  458                 if (error)
  459                         goto out;
  460                 tmpinfo.play.pause = (idat & OSS_PCM_ENABLE_OUTPUT) == 0;
  461                 tmpinfo.record.pause = (idat & OSS_PCM_ENABLE_INPUT) == 0;
  462                 (void) ioctlf(fp, AUDIO_SETINFO, &tmpinfo);
  463                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  464                 if (error)
  465                         goto out;
  466                 break;
  467 #else
  468         case OSS_SNDCTL_DSP_GETTRIGGER:
  469         case OSS_SNDCTL_DSP_SETTRIGGER:
  470                 /* XXX Do nothing for now. */
  471                 idat = OSS_PCM_ENABLE_OUTPUT;
  472                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  473                 goto out;
  474 #endif
  475         case OSS_SNDCTL_DSP_GETIPTR:
  476                 error = ioctlf(fp, AUDIO_GETIOFFS, &tmpoffs);
  477                 if (error)
  478                         goto out;
  479                 cntinfo.bytes = tmpoffs.samples;
  480                 cntinfo.blocks = tmpoffs.deltablks;
  481                 cntinfo.ptr = tmpoffs.offset;
  482                 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
  483                 if (error)
  484                         goto out;
  485                 break;
  486         case OSS_SNDCTL_DSP_GETOPTR:
  487                 error = ioctlf(fp, AUDIO_GETOOFFS, &tmpoffs);
  488                 if (error)
  489                         goto out;
  490                 cntinfo.bytes = tmpoffs.samples;
  491                 cntinfo.blocks = tmpoffs.deltablks;
  492                 cntinfo.ptr = tmpoffs.offset;
  493                 error = copyout(&cntinfo, SCARG(uap, data), sizeof cntinfo);
  494                 if (error)
  495                         goto out;
  496                 break;
  497         case OSS_SNDCTL_DSP_SETDUPLEX:
  498                 idat = 1;
  499                 error = ioctlf(fp, AUDIO_SETFD, &idat);
  500                 goto out;
  501         case OSS_SNDCTL_DSP_MAPINBUF:
  502         case OSS_SNDCTL_DSP_MAPOUTBUF:
  503         case OSS_SNDCTL_DSP_SETSYNCRO:
  504                 error = EINVAL;
  505                 goto out;
  506         case OSS_SNDCTL_DSP_GETODELAY:
  507                 error = ioctlf(fp, AUDIO_GETBUFINFO, &tmpinfo);
  508                 if (error)
  509                         goto out;
  510                 idat = tmpinfo.play.seek + tmpinfo.blocksize / 2;
  511                 error = copyout(&idat, SCARG(uap, data), sizeof idat);
  512                 if (error)
  513                         goto out;
  514                 break;
  515         case OSS_SNDCTL_DSP_PROFILE:
  516                 /* This gives just a hint to the driver,
  517                  * implementing it as a NOP is ok
  518                  */
  519                 break;
  520         default:
  521                 error = EINVAL;
  522                 goto out;
  523         }
  524 
  525  out:
  526         fd_putfile(SCARG(uap, fd));
  527         return error;
  528 }
  529 
  530 /* If the NetBSD mixer device should have more than 32 devices
  531  * some will not be available to Linux */
  532 #define NETBSD_MAXDEVS 64
  533 struct audiodevinfo {
  534         int done;
  535         dev_t dev;
  536         int16_t devmap[OSS_SOUND_MIXER_NRDEVICES],
  537                 rdevmap[NETBSD_MAXDEVS];
  538         char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN];
  539         int enum2opaque[NETBSD_MAXDEVS];
  540         u_long devmask, recmask, stereomask;
  541         u_long caps, source;
  542 };
  543 
  544 static int
  545 opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq)
  546 {
  547         int i, o;
  548 
  549         for (i = 0; i < NETBSD_MAXDEVS; i++) {
  550                 o = di->enum2opaque[i];
  551                 if (o == opq)
  552                         break;
  553                 if (o == -1 && label != NULL &&
  554                     !strncmp(di->names[i], label->name, sizeof di->names[i])) {
  555                         di->enum2opaque[i] = opq;
  556                         break;
  557                 }
  558         }
  559         if (i >= NETBSD_MAXDEVS)
  560                 i = -1;
  561         /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/
  562         return (i);
  563 }
  564 
  565 static int
  566 enum_to_ord(struct audiodevinfo *di, int enm)
  567 {
  568         if (enm >= NETBSD_MAXDEVS)
  569                 return (-1);
  570 
  571         /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/
  572         return (di->enum2opaque[enm]);
  573 }
  574 
  575 static int
  576 enum_to_mask(struct audiodevinfo *di, int enm)
  577 {
  578         int m;
  579         if (enm >= NETBSD_MAXDEVS)
  580                 return (0);
  581 
  582         m = di->enum2opaque[enm];
  583         if (m == -1)
  584                 m = 0;
  585         /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/
  586         return (m);
  587 }
  588 
  589 /*
  590  * Collect the audio device information to allow faster
  591  * emulation of the Linux mixer ioctls.  Cache the information
  592  * to eliminate the overhead of repeating all the ioctls needed
  593  * to collect the information.
  594  */
  595 static struct audiodevinfo *
  596 getdevinfo(file_t *fp)
  597 {
  598         mixer_devinfo_t mi;
  599         int i, j, e;
  600         static const struct {
  601                 const char *name;
  602                 int code;
  603         } *dp, devs[] = {
  604                 { AudioNmicrophone,     OSS_SOUND_MIXER_MIC },
  605                 { AudioNline,           OSS_SOUND_MIXER_LINE },
  606                 { AudioNcd,             OSS_SOUND_MIXER_CD },
  607                 { AudioNdac,            OSS_SOUND_MIXER_PCM },
  608                 { AudioNaux,            OSS_SOUND_MIXER_LINE1 },
  609                 { AudioNrecord,         OSS_SOUND_MIXER_IMIX },
  610                 { AudioNmaster,         OSS_SOUND_MIXER_VOLUME },
  611                 { AudioNtreble,         OSS_SOUND_MIXER_TREBLE },
  612                 { AudioNbass,           OSS_SOUND_MIXER_BASS },
  613                 { AudioNspeaker,        OSS_SOUND_MIXER_SPEAKER },
  614 /*              { AudioNheadphone,      ?? },*/
  615                 { AudioNoutput,         OSS_SOUND_MIXER_OGAIN },
  616                 { AudioNinput,          OSS_SOUND_MIXER_IGAIN },
  617 /*              { AudioNmaster,         OSS_SOUND_MIXER_SPEAKER },*/
  618 /*              { AudioNstereo,         ?? },*/
  619 /*              { AudioNmono,           ?? },*/
  620                 { AudioNfmsynth,        OSS_SOUND_MIXER_SYNTH },
  621 /*              { AudioNwave,           OSS_SOUND_MIXER_PCM },*/
  622                 { AudioNmidi,           OSS_SOUND_MIXER_SYNTH },
  623 /*              { AudioNmixerout,       ?? },*/
  624                 { 0, -1 }
  625         };
  626         int (*ioctlf)(file_t *, u_long, void *) = fp->f_ops->fo_ioctl;
  627         struct vnode *vp;
  628         struct vattr va;
  629         static struct audiodevinfo devcache;
  630         struct audiodevinfo *di = &devcache;
  631         int mlen, dlen;
  632 
  633         /*
  634          * Figure out what device it is so we can check if the
  635          * cached data is valid.
  636          */
  637         vp = fp->f_data;
  638         if (vp->v_type != VCHR)
  639                 return 0;
  640         if (VOP_GETATTR(vp, &va, kauth_cred_get()))
  641                 return 0;
  642         if (di->done && di->dev == va.va_rdev)
  643                 return di;
  644 
  645         di->done = 1;
  646         di->dev = va.va_rdev;
  647         di->devmask = 0;
  648         di->recmask = 0;
  649         di->stereomask = 0;
  650         di->source = ~0;
  651         di->caps = 0;
  652         for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
  653                 di->devmap[i] = -1;
  654         for(i = 0; i < NETBSD_MAXDEVS; i++) {
  655                 di->rdevmap[i] = -1;
  656                 di->names[i][0] = '\0';
  657                 di->enum2opaque[i] = -1;
  658         }
  659         for(i = 0; i < NETBSD_MAXDEVS; i++) {
  660                 mi.index = i;
  661                 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, &mi) < 0)
  662                         break;
  663                 switch(mi.type) {
  664                 case AUDIO_MIXER_VALUE:
  665                         for(dp = devs; dp->name; dp++) {
  666                                 if (strcmp(dp->name, mi.label.name) == 0)
  667                                         break;
  668                                 dlen = strlen(dp->name);
  669                                 mlen = strlen(mi.label.name);
  670                                 if (dlen < mlen
  671                                     && mi.label.name[mlen-dlen-1] == '.'
  672                                     && strcmp(dp->name, mi.label.name + mlen - dlen) == 0)
  673                                         break;
  674                         }
  675                         if (dp->code >= 0) {
  676                                 di->devmap[dp->code] = i;
  677                                 di->rdevmap[i] = dp->code;
  678                                 di->devmask |= 1 << dp->code;
  679                                 if (mi.un.v.num_channels == 2)
  680                                         di->stereomask |= 1 << dp->code;
  681                                 strncpy(di->names[i], mi.label.name,
  682                                         sizeof di->names[i]);
  683                         }
  684                         break;
  685                 }
  686         }
  687         for(i = 0; i < NETBSD_MAXDEVS; i++) {
  688                 mi.index = i;
  689                 if (ioctlf(fp, AUDIO_MIXER_DEVINFO, &mi) < 0)
  690                         break;
  691                 if (strcmp(mi.label.name, AudioNsource) != 0)
  692                         continue;
  693                 di->source = i;
  694                 switch(mi.type) {
  695                 case AUDIO_MIXER_ENUM:
  696                         for(j = 0; j < mi.un.e.num_mem; j++) {
  697                                 e = opaque_to_enum(di,
  698                                                    &mi.un.e.member[j].label,
  699                                                    mi.un.e.member[j].ord);
  700                                 if (e >= 0)
  701                                         di->recmask |= 1 << di->rdevmap[e];
  702                         }
  703                         di->caps = OSS_SOUND_CAP_EXCL_INPUT;
  704                         break;
  705                 case AUDIO_MIXER_SET:
  706                         for(j = 0; j < mi.un.s.num_mem; j++) {
  707                                 e = opaque_to_enum(di,
  708                                                    &mi.un.s.member[j].label,
  709                                                    mi.un.s.member[j].mask);
  710                                 if (e >= 0)
  711                                         di->recmask |= 1 << di->rdevmap[e];
  712                         }
  713                         break;
  714                 }
  715         }
  716         return di;
  717 }
  718 
  719 int
  720 oss_ioctl_mixer(struct lwp *lwp, const struct oss_sys_ioctl_args *uap, register_t *retval)
  721 {
  722         /* {
  723                 syscallarg(int) fd;
  724                 syscallarg(u_long) com;
  725                 syscallarg(void *) data;
  726         } */
  727         file_t *fp;
  728         u_long com;
  729         struct audiodevinfo *di;
  730         mixer_ctrl_t mc;
  731         struct oss_mixer_info omi;
  732         struct audio_device adev;
  733         int idat;
  734         int i;
  735         int error;
  736         int l, r, n, e;
  737         int (*ioctlf)(file_t *, u_long, void *);
  738 
  739         if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
  740                 return (EBADF);
  741 
  742         if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
  743                 error = EBADF;
  744                 goto out;
  745         }
  746 
  747         com = SCARG(uap, com);
  748         DPRINTF(("oss_ioctl_mixer: com=%08lx\n", com));
  749 
  750         retval[0] = 0;
  751 
  752         di = getdevinfo(fp);
  753         if (di == 0) {
  754                 error = EINVAL;
  755                 goto out;
  756         }
  757 
  758         ioctlf = fp->f_ops->fo_ioctl;
  759         switch (com) {
  760         case OSS_GET_VERSION:
  761                 idat = OSS_SOUND_VERSION;
  762                 break;
  763         case OSS_SOUND_MIXER_INFO:
  764         case OSS_SOUND_OLD_MIXER_INFO:
  765                 error = ioctlf(fp, AUDIO_GETDEV, &adev);
  766                 if (error)
  767                         goto out;
  768                 omi.modify_counter = 1;
  769                 strncpy(omi.id, adev.name, sizeof omi.id);
  770                 strncpy(omi.name, adev.name, sizeof omi.name);
  771                 error = copyout(&omi, SCARG(uap, data), OSS_IOCTL_SIZE(com));
  772                 goto out;
  773         case OSS_SOUND_MIXER_READ_RECSRC:
  774                 if (di->source == -1) {
  775                         error = EINVAL;
  776                         goto out;
  777                 }
  778                 mc.dev = di->source;
  779                 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
  780                         mc.type = AUDIO_MIXER_ENUM;
  781                         error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
  782                         if (error)
  783                                 goto out;
  784                         e = opaque_to_enum(di, NULL, mc.un.ord);
  785                         if (e >= 0)
  786                                 idat = 1 << di->rdevmap[e];
  787                 } else {
  788                         mc.type = AUDIO_MIXER_SET;
  789                         error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
  790                         if (error)
  791                                 goto out;
  792                         e = opaque_to_enum(di, NULL, mc.un.mask);
  793                         if (e >= 0)
  794                                 idat = 1 << di->rdevmap[e];
  795                 }
  796                 break;
  797         case OSS_SOUND_MIXER_READ_DEVMASK:
  798                 idat = di->devmask;
  799                 break;
  800         case OSS_SOUND_MIXER_READ_RECMASK:
  801                 idat = di->recmask;
  802                 break;
  803         case OSS_SOUND_MIXER_READ_STEREODEVS:
  804                 idat = di->stereomask;
  805                 break;
  806         case OSS_SOUND_MIXER_READ_CAPS:
  807                 idat = di->caps;
  808                 break;
  809         case OSS_SOUND_MIXER_WRITE_RECSRC:
  810         case OSS_SOUND_MIXER_WRITE_R_RECSRC:
  811                 if (di->source == -1) {
  812                         error = EINVAL;
  813                         goto out;
  814                 }
  815                 mc.dev = di->source;
  816                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
  817                 if (error)
  818                         goto out;
  819                 if (di->caps & OSS_SOUND_CAP_EXCL_INPUT) {
  820                         mc.type = AUDIO_MIXER_ENUM;
  821                         for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++)
  822                                 if (idat & (1 << i))
  823                                         break;
  824                         if (i >= OSS_SOUND_MIXER_NRDEVICES ||
  825                             di->devmap[i] == -1) {
  826                                 error = EINVAL;
  827                                 goto out;
  828                         }
  829                         mc.un.ord = enum_to_ord(di, di->devmap[i]);
  830                 } else {
  831                         mc.type = AUDIO_MIXER_SET;
  832                         mc.un.mask = 0;
  833                         for(i = 0; i < OSS_SOUND_MIXER_NRDEVICES; i++) {
  834                                 if (idat & (1 << i)) {
  835                                         if (di->devmap[i] == -1) {
  836                                                 error = EINVAL;
  837                                                 goto out;
  838                                         }
  839                                         mc.un.mask |= enum_to_mask(di, di->devmap[i]);
  840                                 }
  841                         }
  842                 }
  843                 error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc);
  844                 goto out;
  845         default:
  846                 if (OSS_MIXER_READ(OSS_SOUND_MIXER_FIRST) <= com &&
  847                     com < OSS_MIXER_READ(OSS_SOUND_MIXER_NRDEVICES)) {
  848                         n = OSS_GET_DEV(com);
  849                         if (di->devmap[n] == -1) {
  850                                 error = EINVAL;
  851                                 goto out;
  852                         }
  853                     doread:
  854                         mc.dev = di->devmap[n];
  855                         mc.type = AUDIO_MIXER_VALUE;
  856                         mc.un.value.num_channels = di->stereomask & (1<<n) ? 2 : 1;
  857                         error = ioctlf(fp, AUDIO_MIXER_READ, &mc);
  858                         if (error)
  859                                 goto out;
  860                         if (mc.un.value.num_channels != 2) {
  861                                 l = r = mc.un.value.level[AUDIO_MIXER_LEVEL_MONO];
  862                         } else {
  863                                 l = mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT];
  864                                 r = mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
  865                         }
  866                         idat = TO_OSSVOL(l) | (TO_OSSVOL(r) << 8);
  867                         DPRINTF(("OSS_MIXER_READ  n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
  868                                  n, di->devmap[n], l, r, idat));
  869                         break;
  870                 } else if ((OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_FIRST) <= com &&
  871                            com < OSS_MIXER_WRITE_R(OSS_SOUND_MIXER_NRDEVICES)) ||
  872                            (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
  873                            com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES))) {
  874                         n = OSS_GET_DEV(com);
  875                         if (di->devmap[n] == -1) {
  876                                 error = EINVAL;
  877                                 goto out;
  878                         }
  879                         error = copyin(SCARG(uap, data), &idat, sizeof idat);
  880                         if (error)
  881                                 goto out;
  882                         l = FROM_OSSVOL( idat       & 0xff);
  883                         r = FROM_OSSVOL((idat >> 8) & 0xff);
  884                         mc.dev = di->devmap[n];
  885                         mc.type = AUDIO_MIXER_VALUE;
  886                         if (di->stereomask & (1<<n)) {
  887                                 mc.un.value.num_channels = 2;
  888                                 mc.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
  889                                 mc.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
  890                         } else {
  891                                 mc.un.value.num_channels = 1;
  892                                 mc.un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r)/2;
  893                         }
  894                         DPRINTF(("OSS_MIXER_WRITE n=%d (dev=%d) l=%d, r=%d, idat=%04x\n",
  895                                  n, di->devmap[n], l, r, idat));
  896                         error = ioctlf(fp, AUDIO_MIXER_WRITE, &mc);
  897                         if (error)
  898                                 goto out;
  899                         if (OSS_MIXER_WRITE(OSS_SOUND_MIXER_FIRST) <= com &&
  900                            com < OSS_MIXER_WRITE(OSS_SOUND_MIXER_NRDEVICES)) {
  901                                 error = 0;
  902                                 goto out;
  903                         }
  904                         goto doread;
  905                 } else {
  906 #ifdef AUDIO_DEBUG
  907                         printf("oss_audio: unknown mixer ioctl %04lx\n", com);
  908 #endif
  909                         error = EINVAL;
  910                         goto out;
  911                 }
  912         }
  913         error = copyout(&idat, SCARG(uap, data), sizeof idat);
  914  out:
  915         fd_putfile(SCARG(uap, fd));
  916         return error;
  917 }
  918 
  919 /* Sequencer emulation */
  920 int
  921 oss_ioctl_sequencer(struct lwp *l, const struct oss_sys_ioctl_args *uap, register_t *retval)
  922 {
  923         /* {
  924                 syscallarg(int) fd;
  925                 syscallarg(u_long) com;
  926                 syscallarg(void *) data;
  927         } */
  928         file_t *fp;
  929         u_long com;
  930         int idat, idat1;
  931         struct synth_info si;
  932         struct oss_synth_info osi;
  933         struct oss_seq_event_rec oser;
  934         int error;
  935         int (*ioctlf)(file_t *, u_long, void *);
  936 
  937         if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
  938                 return (EBADF);
  939 
  940         if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
  941                 error = EBADF;
  942                 goto out;
  943         }
  944 
  945         com = SCARG(uap, com);
  946         DPRINTF(("oss_ioctl_sequencer: com=%08lx\n", com));
  947 
  948         retval[0] = 0;
  949 
  950         ioctlf = fp->f_ops->fo_ioctl;
  951         switch (com) {
  952         case OSS_SEQ_RESET:
  953                 error = ioctlf(fp, SEQUENCER_RESET, &idat);
  954                 goto out;
  955         case OSS_SEQ_SYNC:
  956                 error = ioctlf(fp, SEQUENCER_SYNC, &idat);
  957                 goto out;
  958         case OSS_SYNTH_INFO:
  959                 error = copyin(SCARG(uap, data), &osi, sizeof osi);
  960                 if (error)
  961                         goto out;
  962                 si.device = osi.device;
  963                 error = ioctlf(fp, SEQUENCER_INFO, &si);
  964                 if (error)
  965                         goto out;
  966                 strncpy(osi.name, si.name, sizeof osi.name);
  967                 osi.device = si.device;
  968                 switch(si.synth_type) {
  969                 case SYNTH_TYPE_FM:
  970                         osi.synth_type = OSS_SYNTH_TYPE_FM; break;
  971                 case SYNTH_TYPE_SAMPLE:
  972                         osi.synth_type = OSS_SYNTH_TYPE_SAMPLE; break;
  973                 case SYNTH_TYPE_MIDI:
  974                         osi.synth_type = OSS_SYNTH_TYPE_MIDI; break;
  975                 default:
  976                         osi.synth_type = 0; break;
  977                 }
  978                 switch(si.synth_subtype) {
  979                 case SYNTH_SUB_FM_TYPE_ADLIB:
  980                         osi.synth_subtype = OSS_FM_TYPE_ADLIB; break;
  981                 case SYNTH_SUB_FM_TYPE_OPL3:
  982                         osi.synth_subtype = OSS_FM_TYPE_OPL3; break;
  983                 case SYNTH_SUB_MIDI_TYPE_MPU401:
  984                         osi.synth_subtype = OSS_MIDI_TYPE_MPU401; break;
  985                 case SYNTH_SUB_SAMPLE_TYPE_BASIC:
  986                         osi.synth_subtype = OSS_SAMPLE_TYPE_BASIC; break;
  987                 default:
  988                         osi.synth_subtype = 0; break;
  989                 }
  990                 osi.perc_mode = 0;
  991                 osi.nr_voices = si.nr_voices;
  992                 osi.nr_drums = 0;
  993                 osi.instr_bank_size = si.instr_bank_size;
  994                 osi.capabilities = 0;
  995                 if (si.capabilities & SYNTH_CAP_OPL3)
  996                         osi.capabilities |= OSS_SYNTH_CAP_OPL3;
  997                 if (si.capabilities & SYNTH_CAP_INPUT)
  998                         osi.capabilities |= OSS_SYNTH_CAP_INPUT;
  999                 error = copyout(&osi, SCARG(uap, data), sizeof osi);
 1000                 goto out;
 1001         case OSS_SEQ_CTRLRATE:
 1002                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1003                 if (error)
 1004                         goto out;
 1005                 error = ioctlf(fp, SEQUENCER_CTRLRATE, &idat);
 1006                 if (error)
 1007                         goto out;
 1008                 retval[0] = idat;
 1009                 break;
 1010         case OSS_SEQ_GETOUTCOUNT:
 1011                 error = ioctlf(fp, SEQUENCER_GETOUTCOUNT, &idat);
 1012                 if (error)
 1013                         goto out;
 1014                 retval[0] = idat;
 1015                 break;
 1016         case OSS_SEQ_GETINCOUNT:
 1017                 error = ioctlf(fp, SEQUENCER_GETINCOUNT, &idat);
 1018                 if (error)
 1019                         goto out;
 1020                 retval[0] = idat;
 1021                 break;
 1022         case OSS_SEQ_NRSYNTHS:
 1023                 error = ioctlf(fp, SEQUENCER_NRSYNTHS, &idat);
 1024                 if (error)
 1025                         goto out;
 1026                 retval[0] = idat;
 1027                 break;
 1028         case OSS_SEQ_NRMIDIS:
 1029                 error = ioctlf(fp, SEQUENCER_NRMIDIS, &idat);
 1030                 if (error)
 1031                         goto out;
 1032                 retval[0] = idat;
 1033                 break;
 1034         case OSS_SEQ_THRESHOLD:
 1035                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1036                 if (error)
 1037                         goto out;
 1038                 error = ioctlf(fp, SEQUENCER_THRESHOLD, &idat);
 1039                 goto out;
 1040         case OSS_MEMAVL:
 1041                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1042                 if (error)
 1043                         goto out;
 1044                 error = ioctlf(fp, SEQUENCER_MEMAVL, &idat);
 1045                 if (error)
 1046                         goto out;
 1047                 retval[0] = idat;
 1048                 break;
 1049         case OSS_SEQ_PANIC:
 1050                 error = ioctlf(fp, SEQUENCER_PANIC, &idat);
 1051                 goto out;
 1052         case OSS_SEQ_OUTOFBAND:
 1053                 error = copyin(SCARG(uap, data), &oser, sizeof oser);
 1054                 if (error)
 1055                         goto out;
 1056                 error = ioctlf(fp, SEQUENCER_OUTOFBAND, &oser);
 1057                 if (error)
 1058                         goto out;
 1059                 break;
 1060         case OSS_SEQ_GETTIME:
 1061                 error = ioctlf(fp, SEQUENCER_GETTIME, &idat);
 1062                 if (error)
 1063                         goto out;
 1064                 retval[0] = idat;
 1065                 break;
 1066         case OSS_TMR_TIMEBASE:
 1067                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1068                 if (error)
 1069                         goto out;
 1070                 error = ioctlf(fp, SEQUENCER_TMR_TIMEBASE, &idat);
 1071                 if (error)
 1072                         goto out;
 1073                 retval[0] = idat;
 1074                 break;
 1075         case OSS_TMR_START:
 1076                 error = ioctlf(fp, SEQUENCER_TMR_START, &idat);
 1077                 goto out;
 1078         case OSS_TMR_STOP:
 1079                 error = ioctlf(fp, SEQUENCER_TMR_STOP, &idat);
 1080                 goto out;
 1081         case OSS_TMR_CONTINUE:
 1082                 error = ioctlf(fp, SEQUENCER_TMR_CONTINUE, &idat);
 1083                 goto out;
 1084         case OSS_TMR_TEMPO:
 1085                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1086                 if (error)
 1087                         goto out;
 1088                 error = ioctlf(fp, SEQUENCER_TMR_TEMPO, &idat);
 1089                 if (error)
 1090                         goto out;
 1091                 retval[0] = idat;
 1092                 break;
 1093         case OSS_TMR_SOURCE:
 1094                 error = copyin(SCARG(uap, data), &idat1, sizeof idat);
 1095                 if (error)
 1096                         goto out;
 1097                 idat = 0;
 1098                 if (idat1 & OSS_TMR_INTERNAL) idat |= SEQUENCER_TMR_INTERNAL;
 1099                 error = ioctlf(fp, SEQUENCER_TMR_SOURCE, &idat);
 1100                 if (error)
 1101                         goto out;
 1102                 idat1 = idat;
 1103                 if (idat1 & SEQUENCER_TMR_INTERNAL) idat |= OSS_TMR_INTERNAL;
 1104                 retval[0] = idat;
 1105                 break;
 1106         case OSS_TMR_METRONOME:
 1107                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1108                 if (error)
 1109                         goto out;
 1110                 error = ioctlf(fp, SEQUENCER_TMR_METRONOME, &idat);
 1111                 goto out;
 1112         case OSS_TMR_SELECT:
 1113                 error = copyin(SCARG(uap, data), &idat, sizeof idat);
 1114                 if (error)
 1115                         goto out;
 1116                 retval[0] = idat;
 1117                 error = ioctlf(fp, SEQUENCER_TMR_SELECT, &idat);
 1118                 goto out;
 1119         default:
 1120                 error = EINVAL;
 1121                 goto out;
 1122         }
 1123 
 1124         error = copyout(&idat, SCARG(uap, data), sizeof idat);
 1125  out:
 1126         fd_putfile(SCARG(uap, fd));
 1127         return error;
 1128 }
 1129 
 1130 /*
 1131  * Check that the blocksize is a power of 2 as OSS wants.
 1132  * If not, set it to be.
 1133  */
 1134 static void
 1135 setblocksize(file_t *fp, struct audio_info *info)
 1136 {
 1137         struct audio_info set;
 1138         int s;
 1139 
 1140          if (info->blocksize & (info->blocksize-1)) {
 1141                 for(s = 32; s < info->blocksize; s <<= 1)
 1142                         ;
 1143                 AUDIO_INITINFO(&set);
 1144                 set.blocksize = s;
 1145                 fp->f_ops->fo_ioctl(fp, AUDIO_SETINFO, &set);
 1146                 fp->f_ops->fo_ioctl(fp, AUDIO_GETBUFINFO, info);
 1147         }
 1148 }

Cache object: 538c20481d59fd34fb43a40371afdfdb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.