Home | History | Annotate | Download | only in audio
      1 /*
      2  * QEMU OSS audio driver
      3  *
      4  * Copyright (c) 2003-2005 Vassili Karpov (malc)
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 #include <stdlib.h>
     25 #include <sys/mman.h>
     26 #include <sys/types.h>
     27 #include <sys/ioctl.h>
     28 #ifdef __OpenBSD__
     29 #include <soundcard.h>
     30 #else
     31 #include <sys/soundcard.h>
     32 #endif
     33 #include "qemu-common.h"
     34 #include "host-utils.h"
     35 #include "qemu-char.h"
     36 #include "audio.h"
     37 
     38 #define AUDIO_CAP "oss"
     39 #include "audio_int.h"
     40 
     41 #if defined OSS_GETVERSION && defined SNDCTL_DSP_POLICY
     42 #define USE_DSP_POLICY
     43 #endif
     44 
     45 typedef struct OSSVoiceOut {
     46     HWVoiceOut hw;
     47     void *pcm_buf;
     48     int fd;
     49     int wpos;
     50     int nfrags;
     51     int fragsize;
     52     int mmapped;
     53     int pending;
     54 } OSSVoiceOut;
     55 
     56 typedef struct OSSVoiceIn {
     57     HWVoiceIn hw;
     58     void *pcm_buf;
     59     int fd;
     60     int nfrags;
     61     int fragsize;
     62 } OSSVoiceIn;
     63 
     64 static struct {
     65     int try_mmap;
     66     int nfrags;
     67     int fragsize;
     68     const char *devpath_out;
     69     const char *devpath_in;
     70     int debug;
     71     int exclusive;
     72     int policy;
     73 } conf = {
     74     .try_mmap = 0,
     75     .nfrags = 4,
     76     .fragsize = 4096,
     77     .devpath_out = "/dev/dsp",
     78     .devpath_in = "/dev/dsp",
     79     .debug = 0,
     80     .exclusive = 0,
     81     .policy = 5
     82 };
     83 
     84 struct oss_params {
     85     int freq;
     86     audfmt_e fmt;
     87     int nchannels;
     88     int nfrags;
     89     int fragsize;
     90 };
     91 
     92 static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
     93 {
     94     va_list ap;
     95 
     96     va_start (ap, fmt);
     97     AUD_vlog (AUDIO_CAP, fmt, ap);
     98     va_end (ap);
     99 
    100     AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
    101 }
    102 
    103 static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
    104     int err,
    105     const char *typ,
    106     const char *fmt,
    107     ...
    108     )
    109 {
    110     va_list ap;
    111 
    112     AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
    113 
    114     va_start (ap, fmt);
    115     AUD_vlog (AUDIO_CAP, fmt, ap);
    116     va_end (ap);
    117 
    118     AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
    119 }
    120 
    121 static void oss_anal_close (int *fdp)
    122 {
    123     int err;
    124 
    125     qemu_set_fd_handler (*fdp, NULL, NULL, NULL);
    126     err = close (*fdp);
    127     if (err) {
    128         oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
    129     }
    130     *fdp = -1;
    131 }
    132 
    133 static void oss_helper_poll_out (void *opaque)
    134 {
    135     (void) opaque;
    136     audio_run ("oss_poll_out");
    137 }
    138 
    139 static void oss_helper_poll_in (void *opaque)
    140 {
    141     (void) opaque;
    142     audio_run ("oss_poll_in");
    143 }
    144 
    145 static int oss_poll_out (HWVoiceOut *hw)
    146 {
    147     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
    148 
    149     return qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL);
    150 }
    151 
    152 static int oss_poll_in (HWVoiceIn *hw)
    153 {
    154     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
    155 
    156     return qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL);
    157 }
    158 
    159 static int oss_write (SWVoiceOut *sw, void *buf, int len)
    160 {
    161     return audio_pcm_sw_write (sw, buf, len);
    162 }
    163 
    164 static int aud_to_ossfmt (audfmt_e fmt)
    165 {
    166     switch (fmt) {
    167     case AUD_FMT_S8:
    168         return AFMT_S8;
    169 
    170     case AUD_FMT_U8:
    171         return AFMT_U8;
    172 
    173     case AUD_FMT_S16:
    174         return AFMT_S16_LE;
    175 
    176     case AUD_FMT_U16:
    177         return AFMT_U16_LE;
    178 
    179     default:
    180         dolog ("Internal logic error: Bad audio format %d\n", fmt);
    181 #ifdef DEBUG_AUDIO
    182         abort ();
    183 #endif
    184         return AFMT_U8;
    185     }
    186 }
    187 
    188 static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
    189 {
    190     switch (ossfmt) {
    191     case AFMT_S8:
    192         *endianness = 0;
    193         *fmt = AUD_FMT_S8;
    194         break;
    195 
    196     case AFMT_U8:
    197         *endianness = 0;
    198         *fmt = AUD_FMT_U8;
    199         break;
    200 
    201     case AFMT_S16_LE:
    202         *endianness = 0;
    203         *fmt = AUD_FMT_S16;
    204         break;
    205 
    206     case AFMT_U16_LE:
    207         *endianness = 0;
    208         *fmt = AUD_FMT_U16;
    209         break;
    210 
    211     case AFMT_S16_BE:
    212         *endianness = 1;
    213         *fmt = AUD_FMT_S16;
    214         break;
    215 
    216     case AFMT_U16_BE:
    217         *endianness = 1;
    218         *fmt = AUD_FMT_U16;
    219         break;
    220 
    221     default:
    222         dolog ("Unrecognized audio format %d\n", ossfmt);
    223         return -1;
    224     }
    225 
    226     return 0;
    227 }
    228 
    229 #if defined DEBUG_MISMATCHES || defined DEBUG
    230 static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
    231 {
    232     dolog ("parameter | requested value | obtained value\n");
    233     dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
    234     dolog ("channels  |      %10d |     %10d\n",
    235            req->nchannels, obt->nchannels);
    236     dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
    237     dolog ("nfrags    |      %10d |     %10d\n", req->nfrags, obt->nfrags);
    238     dolog ("fragsize  |      %10d |     %10d\n",
    239            req->fragsize, obt->fragsize);
    240 }
    241 #endif
    242 
    243 #ifdef USE_DSP_POLICY
    244 static int oss_get_version (int fd, int *version, const char *typ)
    245 {
    246     if (ioctl (fd, OSS_GETVERSION, &version)) {
    247 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
    248         /*
    249          * Looks like atm (20100109) FreeBSD knows OSS_GETVERSION
    250          * since 7.x, but currently only on the mixer device (or in
    251          * the Linuxolator), and in the native version that part of
    252          * the code is in fact never reached so the ioctl fails anyway.
    253          * Until this is fixed, just check the errno and if its what
    254          * FreeBSD's sound drivers return atm assume they are new enough.
    255          */
    256         if (errno == EINVAL) {
    257             *version = 0x040000;
    258             return 0;
    259         }
    260 #endif
    261         oss_logerr2 (errno, typ, "Failed to get OSS version\n");
    262         return -1;
    263     }
    264     return 0;
    265 }
    266 #endif
    267 
    268 static int oss_open (int in, struct oss_params *req,
    269                      struct oss_params *obt, int *pfd)
    270 {
    271     int fd;
    272     int oflags = conf.exclusive ? O_EXCL : 0;
    273     audio_buf_info abinfo;
    274     int fmt, freq, nchannels;
    275     int setfragment = 1;
    276     const char *dspname = in ? conf.devpath_in : conf.devpath_out;
    277     const char *typ = in ? "ADC" : "DAC";
    278 
    279     /* Kludge needed to have working mmap on Linux */
    280     oflags |= conf.try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
    281 
    282     fd = open (dspname, oflags | O_NONBLOCK);
    283     if (-1 == fd) {
    284         oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
    285         return -1;
    286     }
    287 
    288     freq = req->freq;
    289     nchannels = req->nchannels;
    290     fmt = req->fmt;
    291 
    292     if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
    293         oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
    294         goto err;
    295     }
    296 
    297     if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
    298         oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
    299                      req->nchannels);
    300         goto err;
    301     }
    302 
    303     if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
    304         oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
    305         goto err;
    306     }
    307 
    308     if (ioctl (fd, SNDCTL_DSP_NONBLOCK, NULL)) {
    309         oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
    310         goto err;
    311     }
    312 
    313 #ifdef USE_DSP_POLICY
    314     if (conf.policy >= 0) {
    315         int version;
    316 
    317         if (!oss_get_version (fd, &version, typ)) {
    318             if (conf.debug) {
    319                 dolog ("OSS version = %#x\n", version);
    320             }
    321 
    322             if (version >= 0x040000) {
    323                 int policy = conf.policy;
    324                 if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
    325                     oss_logerr2 (errno, typ,
    326                                  "Failed to set timing policy to %d\n",
    327                                  conf.policy);
    328                     goto err;
    329                 }
    330                 setfragment = 0;
    331             }
    332         }
    333     }
    334 #endif
    335 
    336     if (setfragment) {
    337         int mmmmssss = (req->nfrags << 16) | ctz32 (req->fragsize);
    338         if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
    339             oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
    340                          req->nfrags, req->fragsize);
    341             goto err;
    342         }
    343     }
    344 
    345     if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) {
    346         oss_logerr2 (errno, typ, "Failed to get buffer length\n");
    347         goto err;
    348     }
    349 
    350     if (!abinfo.fragstotal || !abinfo.fragsize) {
    351         AUD_log (AUDIO_CAP, "Returned bogus buffer information(%d, %d) for %s\n",
    352                  abinfo.fragstotal, abinfo.fragsize, typ);
    353         goto err;
    354     }
    355 
    356     obt->fmt = fmt;
    357     obt->nchannels = nchannels;
    358     obt->freq = freq;
    359     obt->nfrags = abinfo.fragstotal;
    360     obt->fragsize = abinfo.fragsize;
    361     *pfd = fd;
    362 
    363 #ifdef DEBUG_MISMATCHES
    364     if ((req->fmt != obt->fmt) ||
    365         (req->nchannels != obt->nchannels) ||
    366         (req->freq != obt->freq) ||
    367         (req->fragsize != obt->fragsize) ||
    368         (req->nfrags != obt->nfrags)) {
    369         dolog ("Audio parameters mismatch\n");
    370         oss_dump_info (req, obt);
    371     }
    372 #endif
    373 
    374 #ifdef DEBUG
    375     oss_dump_info (req, obt);
    376 #endif
    377     return 0;
    378 
    379  err:
    380     oss_anal_close (&fd);
    381     return -1;
    382 }
    383 
    384 static void oss_write_pending (OSSVoiceOut *oss)
    385 {
    386     HWVoiceOut *hw = &oss->hw;
    387 
    388     if (oss->mmapped) {
    389         return;
    390     }
    391 
    392     while (oss->pending) {
    393         int samples_written;
    394         ssize_t bytes_written;
    395         int samples_till_end = hw->samples - oss->wpos;
    396         int samples_to_write = audio_MIN (oss->pending, samples_till_end);
    397         int bytes_to_write = samples_to_write << hw->info.shift;
    398         void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift);
    399 
    400         bytes_written = write (oss->fd, pcm, bytes_to_write);
    401         if (bytes_written < 0) {
    402             if (errno != EAGAIN) {
    403                 oss_logerr (errno, "failed to write %d bytes\n",
    404                             bytes_to_write);
    405             }
    406             break;
    407         }
    408 
    409         if (bytes_written & hw->info.align) {
    410             dolog ("misaligned write asked for %d, but got %zd\n",
    411                    bytes_to_write, bytes_written);
    412             return;
    413         }
    414 
    415         samples_written = bytes_written >> hw->info.shift;
    416         oss->pending -= samples_written;
    417         oss->wpos = (oss->wpos + samples_written) % hw->samples;
    418         if (bytes_written - bytes_to_write) {
    419             break;
    420         }
    421     }
    422 }
    423 
    424 static int oss_run_out (HWVoiceOut *hw, int live)
    425 {
    426     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
    427     int err, decr;
    428     struct audio_buf_info abinfo;
    429     struct count_info cntinfo;
    430     int bufsize;
    431 
    432     bufsize = hw->samples << hw->info.shift;
    433 
    434     if (oss->mmapped) {
    435         int bytes, pos;
    436 
    437         err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
    438         if (err < 0) {
    439             oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
    440             return 0;
    441         }
    442 
    443         pos = hw->rpos << hw->info.shift;
    444         bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize);
    445         decr = audio_MIN (bytes >> hw->info.shift, live);
    446     }
    447     else {
    448         err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
    449         if (err < 0) {
    450             oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
    451             return 0;
    452         }
    453 
    454         if (abinfo.bytes > bufsize) {
    455             if (conf.debug) {
    456                 dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
    457                        "please report your OS/audio hw to av1474 (at) comtv.ru\n",
    458                        abinfo.bytes, bufsize);
    459             }
    460             abinfo.bytes = bufsize;
    461         }
    462 
    463         if (abinfo.bytes < 0) {
    464             if (conf.debug) {
    465                 dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
    466                        abinfo.bytes, bufsize);
    467             }
    468             return 0;
    469         }
    470 
    471         decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
    472         if (!decr) {
    473             return 0;
    474         }
    475     }
    476 
    477     decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending);
    478     oss->pending += decr;
    479     oss_write_pending (oss);
    480 
    481     return decr;
    482 }
    483 
    484 static void oss_fini_out (HWVoiceOut *hw)
    485 {
    486     int err;
    487     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
    488 
    489     ldebug ("oss_fini\n");
    490     oss_anal_close (&oss->fd);
    491 
    492     if (oss->pcm_buf) {
    493         if (oss->mmapped) {
    494             err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
    495             if (err) {
    496                 oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
    497                             oss->pcm_buf, hw->samples << hw->info.shift);
    498             }
    499         }
    500         else {
    501             qemu_free (oss->pcm_buf);
    502         }
    503         oss->pcm_buf = NULL;
    504     }
    505 }
    506 
    507 static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
    508 {
    509     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
    510     struct oss_params req, obt;
    511     int endianness;
    512     int err;
    513     int fd;
    514     audfmt_e effective_fmt;
    515     struct audsettings obt_as;
    516 
    517     oss->fd = -1;
    518 
    519     req.fmt = aud_to_ossfmt (as->fmt);
    520     req.freq = as->freq;
    521     req.nchannels = as->nchannels;
    522     req.fragsize = conf.fragsize;
    523     req.nfrags = conf.nfrags;
    524 
    525     if (oss_open (0, &req, &obt, &fd)) {
    526         return -1;
    527     }
    528 
    529     err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
    530     if (err) {
    531         oss_anal_close (&fd);
    532         return -1;
    533     }
    534 
    535     obt_as.freq = obt.freq;
    536     obt_as.nchannels = obt.nchannels;
    537     obt_as.fmt = effective_fmt;
    538     obt_as.endianness = endianness;
    539 
    540     audio_pcm_init_info (&hw->info, &obt_as);
    541     oss->nfrags = obt.nfrags;
    542     oss->fragsize = obt.fragsize;
    543 
    544     if (obt.nfrags * obt.fragsize & hw->info.align) {
    545         dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n",
    546                obt.nfrags * obt.fragsize, hw->info.align + 1);
    547     }
    548 
    549     hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
    550 
    551     oss->mmapped = 0;
    552     if (conf.try_mmap) {
    553         oss->pcm_buf = mmap (
    554             NULL,
    555             hw->samples << hw->info.shift,
    556             PROT_READ | PROT_WRITE,
    557             MAP_SHARED,
    558             fd,
    559             0
    560             );
    561         if (oss->pcm_buf == MAP_FAILED) {
    562             oss_logerr (errno, "Failed to map %d bytes of DAC\n",
    563                         hw->samples << hw->info.shift);
    564         }
    565         else {
    566             int err;
    567             int trig = 0;
    568             if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
    569                 oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
    570             }
    571             else {
    572                 trig = PCM_ENABLE_OUTPUT;
    573                 if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
    574                     oss_logerr (
    575                         errno,
    576                         "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
    577                         );
    578                 }
    579                 else {
    580                     oss->mmapped = 1;
    581                 }
    582             }
    583 
    584             if (!oss->mmapped) {
    585                 err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
    586                 if (err) {
    587                     oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
    588                                 oss->pcm_buf, hw->samples << hw->info.shift);
    589                 }
    590             }
    591         }
    592     }
    593 
    594     if (!oss->mmapped) {
    595         oss->pcm_buf = audio_calloc (
    596             AUDIO_FUNC,
    597             hw->samples,
    598             1 << hw->info.shift
    599             );
    600         if (!oss->pcm_buf) {
    601             dolog (
    602                 "Could not allocate DAC buffer (%d samples, each %d bytes)\n",
    603                 hw->samples,
    604                 1 << hw->info.shift
    605                 );
    606             oss_anal_close (&fd);
    607             return -1;
    608         }
    609     }
    610 
    611     oss->fd = fd;
    612     return 0;
    613 }
    614 
    615 static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
    616 {
    617     int trig;
    618     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
    619 
    620     switch (cmd) {
    621     case VOICE_ENABLE:
    622         {
    623             va_list ap;
    624             int poll_mode;
    625 
    626             va_start (ap, cmd);
    627             poll_mode = va_arg (ap, int);
    628             va_end (ap);
    629 
    630             ldebug ("enabling voice\n");
    631             if (poll_mode && oss_poll_out (hw)) {
    632                 poll_mode = 0;
    633             }
    634             hw->poll_mode = poll_mode;
    635 
    636             if (!oss->mmapped) {
    637                 return 0;
    638             }
    639 
    640             audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
    641             trig = PCM_ENABLE_OUTPUT;
    642             if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
    643                 oss_logerr (
    644                     errno,
    645                     "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
    646                     );
    647                 return -1;
    648             }
    649         }
    650         break;
    651 
    652     case VOICE_DISABLE:
    653         if (hw->poll_mode) {
    654             qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
    655             hw->poll_mode = 0;
    656         }
    657 
    658         if (!oss->mmapped) {
    659             return 0;
    660         }
    661 
    662         ldebug ("disabling voice\n");
    663         trig = 0;
    664         if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
    665             oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
    666             return -1;
    667         }
    668         break;
    669     }
    670     return 0;
    671 }
    672 
    673 static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
    674 {
    675     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
    676     struct oss_params req, obt;
    677     int endianness;
    678     int err;
    679     int fd;
    680     audfmt_e effective_fmt;
    681     struct audsettings obt_as;
    682 
    683     oss->fd = -1;
    684 
    685     req.fmt = aud_to_ossfmt (as->fmt);
    686     req.freq = as->freq;
    687     req.nchannels = as->nchannels;
    688     req.fragsize = conf.fragsize;
    689     req.nfrags = conf.nfrags;
    690     if (oss_open (1, &req, &obt, &fd)) {
    691         return -1;
    692     }
    693 
    694     err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
    695     if (err) {
    696         oss_anal_close (&fd);
    697         return -1;
    698     }
    699 
    700     obt_as.freq = obt.freq;
    701     obt_as.nchannels = obt.nchannels;
    702     obt_as.fmt = effective_fmt;
    703     obt_as.endianness = endianness;
    704 
    705     audio_pcm_init_info (&hw->info, &obt_as);
    706     oss->nfrags = obt.nfrags;
    707     oss->fragsize = obt.fragsize;
    708 
    709     if (obt.nfrags * obt.fragsize & hw->info.align) {
    710         dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n",
    711                obt.nfrags * obt.fragsize, hw->info.align + 1);
    712     }
    713 
    714     hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
    715     oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
    716     if (!oss->pcm_buf) {
    717         dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
    718                hw->samples, 1 << hw->info.shift);
    719         oss_anal_close (&fd);
    720         return -1;
    721     }
    722 
    723     oss->fd = fd;
    724     return 0;
    725 }
    726 
    727 static void oss_fini_in (HWVoiceIn *hw)
    728 {
    729     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
    730 
    731     oss_anal_close (&oss->fd);
    732 
    733     if (oss->pcm_buf) {
    734         qemu_free (oss->pcm_buf);
    735         oss->pcm_buf = NULL;
    736     }
    737 }
    738 
    739 static int oss_run_in (HWVoiceIn *hw)
    740 {
    741     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
    742     int hwshift = hw->info.shift;
    743     int i;
    744     int live = audio_pcm_hw_get_live_in (hw);
    745     int dead = hw->samples - live;
    746     size_t read_samples = 0;
    747     struct {
    748         int add;
    749         int len;
    750     } bufs[2] = {
    751         { .add = hw->wpos, .len = 0 },
    752         { .add = 0,        .len = 0 }
    753     };
    754 
    755     if (!dead) {
    756         return 0;
    757     }
    758 
    759     if (hw->wpos + dead > hw->samples) {
    760         bufs[0].len = (hw->samples - hw->wpos) << hwshift;
    761         bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
    762     }
    763     else {
    764         bufs[0].len = dead << hwshift;
    765     }
    766 
    767     for (i = 0; i < 2; ++i) {
    768         ssize_t nread;
    769 
    770         if (bufs[i].len) {
    771             void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
    772             nread = read (oss->fd, p, bufs[i].len);
    773 
    774             if (nread > 0) {
    775                 if (nread & hw->info.align) {
    776                     dolog ("warning: Misaligned read %zd (requested %d), "
    777                            "alignment %d\n", nread, bufs[i].add << hwshift,
    778                            hw->info.align + 1);
    779                 }
    780                 read_samples += nread >> hwshift;
    781                 hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
    782                           &nominal_volume);
    783             }
    784 
    785             if (bufs[i].len - nread) {
    786                 if (nread == -1) {
    787                     switch (errno) {
    788                     case EINTR:
    789                     case EAGAIN:
    790                         break;
    791                     default:
    792                         oss_logerr (
    793                             errno,
    794                             "Failed to read %d bytes of audio (to %p)\n",
    795                             bufs[i].len, p
    796                             );
    797                         break;
    798                     }
    799                 }
    800                 break;
    801             }
    802         }
    803     }
    804 
    805     hw->wpos = (hw->wpos + read_samples) % hw->samples;
    806     return read_samples;
    807 }
    808 
    809 static int oss_read (SWVoiceIn *sw, void *buf, int size)
    810 {
    811     return audio_pcm_sw_read (sw, buf, size);
    812 }
    813 
    814 static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
    815 {
    816     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
    817 
    818     switch (cmd) {
    819     case VOICE_ENABLE:
    820         {
    821             va_list ap;
    822             int poll_mode;
    823 
    824             va_start (ap, cmd);
    825             poll_mode = va_arg (ap, int);
    826             va_end (ap);
    827 
    828             if (poll_mode && oss_poll_in (hw)) {
    829                 poll_mode = 0;
    830             }
    831             hw->poll_mode = poll_mode;
    832         }
    833         break;
    834 
    835     case VOICE_DISABLE:
    836         if (hw->poll_mode) {
    837             hw->poll_mode = 0;
    838             qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
    839         }
    840         break;
    841     }
    842     return 0;
    843 }
    844 
    845 static void *oss_audio_init (void)
    846 {
    847     return &conf;
    848 }
    849 
    850 static void oss_audio_fini (void *opaque)
    851 {
    852     (void) opaque;
    853 }
    854 
    855 static struct audio_option oss_options[] = {
    856     {
    857         .name  = "FRAGSIZE",
    858         .tag   = AUD_OPT_INT,
    859         .valp  = &conf.fragsize,
    860         .descr = "Fragment size in bytes"
    861     },
    862     {
    863         .name  = "NFRAGS",
    864         .tag   = AUD_OPT_INT,
    865         .valp  = &conf.nfrags,
    866         .descr = "Number of fragments"
    867     },
    868     {
    869         .name  = "MMAP",
    870         .tag   = AUD_OPT_BOOL,
    871         .valp  = &conf.try_mmap,
    872         .descr = "Try using memory mapped access"
    873     },
    874     {
    875         .name  = "DAC_DEV",
    876         .tag   = AUD_OPT_STR,
    877         .valp  = &conf.devpath_out,
    878         .descr = "Path to DAC device"
    879     },
    880     {
    881         .name  = "ADC_DEV",
    882         .tag   = AUD_OPT_STR,
    883         .valp  = &conf.devpath_in,
    884         .descr = "Path to ADC device"
    885     },
    886     {
    887         .name  = "EXCLUSIVE",
    888         .tag   = AUD_OPT_BOOL,
    889         .valp  = &conf.exclusive,
    890         .descr = "Open device in exclusive mode (vmix wont work)"
    891     },
    892 #ifdef USE_DSP_POLICY
    893     {
    894         .name  = "POLICY",
    895         .tag   = AUD_OPT_INT,
    896         .valp  = &conf.policy,
    897         .descr = "Set the timing policy of the device, -1 to use fragment mode",
    898     },
    899 #endif
    900     {
    901         .name  = "DEBUG",
    902         .tag   = AUD_OPT_BOOL,
    903         .valp  = &conf.debug,
    904         .descr = "Turn on some debugging messages"
    905     },
    906     { /* End of list */ }
    907 };
    908 
    909 static struct audio_pcm_ops oss_pcm_ops = {
    910     .init_out = oss_init_out,
    911     .fini_out = oss_fini_out,
    912     .run_out  = oss_run_out,
    913     .write    = oss_write,
    914     .ctl_out  = oss_ctl_out,
    915 
    916     .init_in  = oss_init_in,
    917     .fini_in  = oss_fini_in,
    918     .run_in   = oss_run_in,
    919     .read     = oss_read,
    920     .ctl_in   = oss_ctl_in
    921 };
    922 
    923 struct audio_driver oss_audio_driver = {
    924     .name           = "oss",
    925     .descr          = "OSS http://www.opensound.com",
    926     .options        = oss_options,
    927     .init           = oss_audio_init,
    928     .fini           = oss_audio_fini,
    929     .pcm_ops        = &oss_pcm_ops,
    930     .can_be_default = 1,
    931     .max_voices_out = INT_MAX,
    932     .max_voices_in  = INT_MAX,
    933     .voice_size_out = sizeof (OSSVoiceOut),
    934     .voice_size_in  = sizeof (OSSVoiceIn)
    935 };
    936