qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

alsaaudio.c (26107B)


      1 /*
      2  * QEMU ALSA audio driver
      3  *
      4  * Copyright (c) 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 
     25 #include "qemu/osdep.h"
     26 #include <alsa/asoundlib.h>
     27 #include "qemu/main-loop.h"
     28 #include "qemu/module.h"
     29 #include "audio.h"
     30 #include "trace.h"
     31 
     32 #pragma GCC diagnostic ignored "-Waddress"
     33 
     34 #define AUDIO_CAP "alsa"
     35 #include "audio_int.h"
     36 
     37 #define DEBUG_ALSA 0
     38 
     39 struct pollhlp {
     40     snd_pcm_t *handle;
     41     struct pollfd *pfds;
     42     int count;
     43     int mask;
     44     AudioState *s;
     45 };
     46 
     47 typedef struct ALSAVoiceOut {
     48     HWVoiceOut hw;
     49     snd_pcm_t *handle;
     50     struct pollhlp pollhlp;
     51     Audiodev *dev;
     52 } ALSAVoiceOut;
     53 
     54 typedef struct ALSAVoiceIn {
     55     HWVoiceIn hw;
     56     snd_pcm_t *handle;
     57     struct pollhlp pollhlp;
     58     Audiodev *dev;
     59 } ALSAVoiceIn;
     60 
     61 struct alsa_params_req {
     62     int freq;
     63     snd_pcm_format_t fmt;
     64     int nchannels;
     65 };
     66 
     67 struct alsa_params_obt {
     68     int freq;
     69     AudioFormat fmt;
     70     int endianness;
     71     int nchannels;
     72     snd_pcm_uframes_t samples;
     73 };
     74 
     75 static void G_GNUC_PRINTF (2, 3) alsa_logerr (int err, const char *fmt, ...)
     76 {
     77     va_list ap;
     78 
     79     va_start (ap, fmt);
     80     AUD_vlog (AUDIO_CAP, fmt, ap);
     81     va_end (ap);
     82 
     83     AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
     84 }
     85 
     86 static void G_GNUC_PRINTF (3, 4) alsa_logerr2 (
     87     int err,
     88     const char *typ,
     89     const char *fmt,
     90     ...
     91     )
     92 {
     93     va_list ap;
     94 
     95     AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
     96 
     97     va_start (ap, fmt);
     98     AUD_vlog (AUDIO_CAP, fmt, ap);
     99     va_end (ap);
    100 
    101     AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
    102 }
    103 
    104 static void alsa_fini_poll (struct pollhlp *hlp)
    105 {
    106     int i;
    107     struct pollfd *pfds = hlp->pfds;
    108 
    109     if (pfds) {
    110         for (i = 0; i < hlp->count; ++i) {
    111             qemu_set_fd_handler (pfds[i].fd, NULL, NULL, NULL);
    112         }
    113         g_free (pfds);
    114     }
    115     hlp->pfds = NULL;
    116     hlp->count = 0;
    117     hlp->handle = NULL;
    118 }
    119 
    120 static void alsa_anal_close1 (snd_pcm_t **handlep)
    121 {
    122     int err = snd_pcm_close (*handlep);
    123     if (err) {
    124         alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
    125     }
    126     *handlep = NULL;
    127 }
    128 
    129 static void alsa_anal_close (snd_pcm_t **handlep, struct pollhlp *hlp)
    130 {
    131     alsa_fini_poll (hlp);
    132     alsa_anal_close1 (handlep);
    133 }
    134 
    135 static int alsa_recover (snd_pcm_t *handle)
    136 {
    137     int err = snd_pcm_prepare (handle);
    138     if (err < 0) {
    139         alsa_logerr (err, "Failed to prepare handle %p\n", handle);
    140         return -1;
    141     }
    142     return 0;
    143 }
    144 
    145 static int alsa_resume (snd_pcm_t *handle)
    146 {
    147     int err = snd_pcm_resume (handle);
    148     if (err < 0) {
    149         alsa_logerr (err, "Failed to resume handle %p\n", handle);
    150         return -1;
    151     }
    152     return 0;
    153 }
    154 
    155 static void alsa_poll_handler (void *opaque)
    156 {
    157     int err, count;
    158     snd_pcm_state_t state;
    159     struct pollhlp *hlp = opaque;
    160     unsigned short revents;
    161 
    162     count = poll (hlp->pfds, hlp->count, 0);
    163     if (count < 0) {
    164         dolog ("alsa_poll_handler: poll %s\n", strerror (errno));
    165         return;
    166     }
    167 
    168     if (!count) {
    169         return;
    170     }
    171 
    172     /* XXX: ALSA example uses initial count, not the one returned by
    173        poll, correct? */
    174     err = snd_pcm_poll_descriptors_revents (hlp->handle, hlp->pfds,
    175                                             hlp->count, &revents);
    176     if (err < 0) {
    177         alsa_logerr (err, "snd_pcm_poll_descriptors_revents");
    178         return;
    179     }
    180 
    181     if (!(revents & hlp->mask)) {
    182         trace_alsa_revents(revents);
    183         return;
    184     }
    185 
    186     state = snd_pcm_state (hlp->handle);
    187     switch (state) {
    188     case SND_PCM_STATE_SETUP:
    189         alsa_recover (hlp->handle);
    190         break;
    191 
    192     case SND_PCM_STATE_XRUN:
    193         alsa_recover (hlp->handle);
    194         break;
    195 
    196     case SND_PCM_STATE_SUSPENDED:
    197         alsa_resume (hlp->handle);
    198         break;
    199 
    200     case SND_PCM_STATE_PREPARED:
    201         audio_run(hlp->s, "alsa run (prepared)");
    202         break;
    203 
    204     case SND_PCM_STATE_RUNNING:
    205         audio_run(hlp->s, "alsa run (running)");
    206         break;
    207 
    208     default:
    209         dolog ("Unexpected state %d\n", state);
    210     }
    211 }
    212 
    213 static int alsa_poll_helper (snd_pcm_t *handle, struct pollhlp *hlp, int mask)
    214 {
    215     int i, count, err;
    216     struct pollfd *pfds;
    217 
    218     count = snd_pcm_poll_descriptors_count (handle);
    219     if (count <= 0) {
    220         dolog ("Could not initialize poll mode\n"
    221                "Invalid number of poll descriptors %d\n", count);
    222         return -1;
    223     }
    224 
    225     pfds = audio_calloc ("alsa_poll_helper", count, sizeof (*pfds));
    226     if (!pfds) {
    227         dolog ("Could not initialize poll mode\n");
    228         return -1;
    229     }
    230 
    231     err = snd_pcm_poll_descriptors (handle, pfds, count);
    232     if (err < 0) {
    233         alsa_logerr (err, "Could not initialize poll mode\n"
    234                      "Could not obtain poll descriptors\n");
    235         g_free (pfds);
    236         return -1;
    237     }
    238 
    239     for (i = 0; i < count; ++i) {
    240         if (pfds[i].events & POLLIN) {
    241             qemu_set_fd_handler (pfds[i].fd, alsa_poll_handler, NULL, hlp);
    242         }
    243         if (pfds[i].events & POLLOUT) {
    244             trace_alsa_pollout(i, pfds[i].fd);
    245             qemu_set_fd_handler (pfds[i].fd, NULL, alsa_poll_handler, hlp);
    246         }
    247         trace_alsa_set_handler(pfds[i].events, i, pfds[i].fd, err);
    248 
    249     }
    250     hlp->pfds = pfds;
    251     hlp->count = count;
    252     hlp->handle = handle;
    253     hlp->mask = mask;
    254     return 0;
    255 }
    256 
    257 static int alsa_poll_out (HWVoiceOut *hw)
    258 {
    259     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    260 
    261     return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLOUT);
    262 }
    263 
    264 static int alsa_poll_in (HWVoiceIn *hw)
    265 {
    266     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
    267 
    268     return alsa_poll_helper (alsa->handle, &alsa->pollhlp, POLLIN);
    269 }
    270 
    271 static snd_pcm_format_t aud_to_alsafmt (AudioFormat fmt, int endianness)
    272 {
    273     switch (fmt) {
    274     case AUDIO_FORMAT_S8:
    275         return SND_PCM_FORMAT_S8;
    276 
    277     case AUDIO_FORMAT_U8:
    278         return SND_PCM_FORMAT_U8;
    279 
    280     case AUDIO_FORMAT_S16:
    281         if (endianness) {
    282             return SND_PCM_FORMAT_S16_BE;
    283         } else {
    284             return SND_PCM_FORMAT_S16_LE;
    285         }
    286 
    287     case AUDIO_FORMAT_U16:
    288         if (endianness) {
    289             return SND_PCM_FORMAT_U16_BE;
    290         } else {
    291             return SND_PCM_FORMAT_U16_LE;
    292         }
    293 
    294     case AUDIO_FORMAT_S32:
    295         if (endianness) {
    296             return SND_PCM_FORMAT_S32_BE;
    297         } else {
    298             return SND_PCM_FORMAT_S32_LE;
    299         }
    300 
    301     case AUDIO_FORMAT_U32:
    302         if (endianness) {
    303             return SND_PCM_FORMAT_U32_BE;
    304         } else {
    305             return SND_PCM_FORMAT_U32_LE;
    306         }
    307 
    308     case AUDIO_FORMAT_F32:
    309         if (endianness) {
    310             return SND_PCM_FORMAT_FLOAT_BE;
    311         } else {
    312             return SND_PCM_FORMAT_FLOAT_LE;
    313         }
    314 
    315     default:
    316         dolog ("Internal logic error: Bad audio format %d\n", fmt);
    317 #ifdef DEBUG_AUDIO
    318         abort ();
    319 #endif
    320         return SND_PCM_FORMAT_U8;
    321     }
    322 }
    323 
    324 static int alsa_to_audfmt (snd_pcm_format_t alsafmt, AudioFormat *fmt,
    325                            int *endianness)
    326 {
    327     switch (alsafmt) {
    328     case SND_PCM_FORMAT_S8:
    329         *endianness = 0;
    330         *fmt = AUDIO_FORMAT_S8;
    331         break;
    332 
    333     case SND_PCM_FORMAT_U8:
    334         *endianness = 0;
    335         *fmt = AUDIO_FORMAT_U8;
    336         break;
    337 
    338     case SND_PCM_FORMAT_S16_LE:
    339         *endianness = 0;
    340         *fmt = AUDIO_FORMAT_S16;
    341         break;
    342 
    343     case SND_PCM_FORMAT_U16_LE:
    344         *endianness = 0;
    345         *fmt = AUDIO_FORMAT_U16;
    346         break;
    347 
    348     case SND_PCM_FORMAT_S16_BE:
    349         *endianness = 1;
    350         *fmt = AUDIO_FORMAT_S16;
    351         break;
    352 
    353     case SND_PCM_FORMAT_U16_BE:
    354         *endianness = 1;
    355         *fmt = AUDIO_FORMAT_U16;
    356         break;
    357 
    358     case SND_PCM_FORMAT_S32_LE:
    359         *endianness = 0;
    360         *fmt = AUDIO_FORMAT_S32;
    361         break;
    362 
    363     case SND_PCM_FORMAT_U32_LE:
    364         *endianness = 0;
    365         *fmt = AUDIO_FORMAT_U32;
    366         break;
    367 
    368     case SND_PCM_FORMAT_S32_BE:
    369         *endianness = 1;
    370         *fmt = AUDIO_FORMAT_S32;
    371         break;
    372 
    373     case SND_PCM_FORMAT_U32_BE:
    374         *endianness = 1;
    375         *fmt = AUDIO_FORMAT_U32;
    376         break;
    377 
    378     case SND_PCM_FORMAT_FLOAT_LE:
    379         *endianness = 0;
    380         *fmt = AUDIO_FORMAT_F32;
    381         break;
    382 
    383     case SND_PCM_FORMAT_FLOAT_BE:
    384         *endianness = 1;
    385         *fmt = AUDIO_FORMAT_F32;
    386         break;
    387 
    388     default:
    389         dolog ("Unrecognized audio format %d\n", alsafmt);
    390         return -1;
    391     }
    392 
    393     return 0;
    394 }
    395 
    396 static void alsa_dump_info (struct alsa_params_req *req,
    397                             struct alsa_params_obt *obt,
    398                             snd_pcm_format_t obtfmt,
    399                             AudiodevAlsaPerDirectionOptions *apdo)
    400 {
    401     dolog("parameter | requested value | obtained value\n");
    402     dolog("format    |      %10d |     %10d\n", req->fmt, obtfmt);
    403     dolog("channels  |      %10d |     %10d\n",
    404           req->nchannels, obt->nchannels);
    405     dolog("frequency |      %10d |     %10d\n", req->freq, obt->freq);
    406     dolog("============================================\n");
    407     dolog("requested: buffer len %" PRId32 " period len %" PRId32 "\n",
    408           apdo->buffer_length, apdo->period_length);
    409     dolog("obtained: samples %ld\n", obt->samples);
    410 }
    411 
    412 static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
    413 {
    414     int err;
    415     snd_pcm_sw_params_t *sw_params;
    416 
    417     snd_pcm_sw_params_alloca (&sw_params);
    418 
    419     err = snd_pcm_sw_params_current (handle, sw_params);
    420     if (err < 0) {
    421         dolog ("Could not fully initialize DAC\n");
    422         alsa_logerr (err, "Failed to get current software parameters\n");
    423         return;
    424     }
    425 
    426     err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
    427     if (err < 0) {
    428         dolog ("Could not fully initialize DAC\n");
    429         alsa_logerr (err, "Failed to set software threshold to %ld\n",
    430                      threshold);
    431         return;
    432     }
    433 
    434     err = snd_pcm_sw_params (handle, sw_params);
    435     if (err < 0) {
    436         dolog ("Could not fully initialize DAC\n");
    437         alsa_logerr (err, "Failed to set software parameters\n");
    438         return;
    439     }
    440 }
    441 
    442 static int alsa_open(bool in, struct alsa_params_req *req,
    443                      struct alsa_params_obt *obt, snd_pcm_t **handlep,
    444                      Audiodev *dev)
    445 {
    446     AudiodevAlsaOptions *aopts = &dev->u.alsa;
    447     AudiodevAlsaPerDirectionOptions *apdo = in ? aopts->in : aopts->out;
    448     snd_pcm_t *handle;
    449     snd_pcm_hw_params_t *hw_params;
    450     int err;
    451     unsigned int freq, nchannels;
    452     const char *pcm_name = apdo->has_dev ? apdo->dev : "default";
    453     snd_pcm_uframes_t obt_buffer_size;
    454     const char *typ = in ? "ADC" : "DAC";
    455     snd_pcm_format_t obtfmt;
    456 
    457     freq = req->freq;
    458     nchannels = req->nchannels;
    459 
    460     snd_pcm_hw_params_alloca (&hw_params);
    461 
    462     err = snd_pcm_open (
    463         &handle,
    464         pcm_name,
    465         in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
    466         SND_PCM_NONBLOCK
    467         );
    468     if (err < 0) {
    469         alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
    470         return -1;
    471     }
    472 
    473     err = snd_pcm_hw_params_any (handle, hw_params);
    474     if (err < 0) {
    475         alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
    476         goto err;
    477     }
    478 
    479     err = snd_pcm_hw_params_set_access (
    480         handle,
    481         hw_params,
    482         SND_PCM_ACCESS_RW_INTERLEAVED
    483         );
    484     if (err < 0) {
    485         alsa_logerr2 (err, typ, "Failed to set access type\n");
    486         goto err;
    487     }
    488 
    489     err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
    490     if (err < 0) {
    491         alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
    492     }
    493 
    494     err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
    495     if (err < 0) {
    496         alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
    497         goto err;
    498     }
    499 
    500     err = snd_pcm_hw_params_set_channels_near (
    501         handle,
    502         hw_params,
    503         &nchannels
    504         );
    505     if (err < 0) {
    506         alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
    507                       req->nchannels);
    508         goto err;
    509     }
    510 
    511     if (apdo->buffer_length) {
    512         int dir = 0;
    513         unsigned int btime = apdo->buffer_length;
    514 
    515         err = snd_pcm_hw_params_set_buffer_time_near(
    516             handle, hw_params, &btime, &dir);
    517 
    518         if (err < 0) {
    519             alsa_logerr2(err, typ, "Failed to set buffer time to %" PRId32 "\n",
    520                          apdo->buffer_length);
    521             goto err;
    522         }
    523 
    524         if (apdo->has_buffer_length && btime != apdo->buffer_length) {
    525             dolog("Requested buffer time %" PRId32
    526                   " was rejected, using %u\n", apdo->buffer_length, btime);
    527         }
    528     }
    529 
    530     if (apdo->period_length) {
    531         int dir = 0;
    532         unsigned int ptime = apdo->period_length;
    533 
    534         err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, &ptime,
    535                                                      &dir);
    536 
    537         if (err < 0) {
    538             alsa_logerr2(err, typ, "Failed to set period time to %" PRId32 "\n",
    539                          apdo->period_length);
    540             goto err;
    541         }
    542 
    543         if (apdo->has_period_length && ptime != apdo->period_length) {
    544             dolog("Requested period time %" PRId32 " was rejected, using %d\n",
    545                   apdo->period_length, ptime);
    546         }
    547     }
    548 
    549     err = snd_pcm_hw_params (handle, hw_params);
    550     if (err < 0) {
    551         alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
    552         goto err;
    553     }
    554 
    555     err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
    556     if (err < 0) {
    557         alsa_logerr2 (err, typ, "Failed to get buffer size\n");
    558         goto err;
    559     }
    560 
    561     err = snd_pcm_hw_params_get_format (hw_params, &obtfmt);
    562     if (err < 0) {
    563         alsa_logerr2 (err, typ, "Failed to get format\n");
    564         goto err;
    565     }
    566 
    567     if (alsa_to_audfmt (obtfmt, &obt->fmt, &obt->endianness)) {
    568         dolog ("Invalid format was returned %d\n", obtfmt);
    569         goto err;
    570     }
    571 
    572     err = snd_pcm_prepare (handle);
    573     if (err < 0) {
    574         alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
    575         goto err;
    576     }
    577 
    578     if (!in && aopts->has_threshold && aopts->threshold) {
    579         struct audsettings as = { .freq = freq };
    580         alsa_set_threshold(
    581             handle,
    582             audio_buffer_frames(qapi_AudiodevAlsaPerDirectionOptions_base(apdo),
    583                                 &as, aopts->threshold));
    584     }
    585 
    586     obt->nchannels = nchannels;
    587     obt->freq = freq;
    588     obt->samples = obt_buffer_size;
    589 
    590     *handlep = handle;
    591 
    592     if (DEBUG_ALSA || obtfmt != req->fmt ||
    593         obt->nchannels != req->nchannels || obt->freq != req->freq) {
    594         dolog ("Audio parameters for %s\n", typ);
    595         alsa_dump_info(req, obt, obtfmt, apdo);
    596     }
    597 
    598     return 0;
    599 
    600  err:
    601     alsa_anal_close1 (&handle);
    602     return -1;
    603 }
    604 
    605 static size_t alsa_buffer_get_free(HWVoiceOut *hw)
    606 {
    607     ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw;
    608     snd_pcm_sframes_t avail;
    609     size_t alsa_free, generic_free, generic_in_use;
    610 
    611     avail = snd_pcm_avail_update(alsa->handle);
    612     if (avail < 0) {
    613         if (avail == -EPIPE) {
    614             if (!alsa_recover(alsa->handle)) {
    615                 avail = snd_pcm_avail_update(alsa->handle);
    616             }
    617         }
    618         if (avail < 0) {
    619             alsa_logerr(avail,
    620                         "Could not obtain number of available frames\n");
    621             avail = 0;
    622         }
    623     }
    624 
    625     alsa_free = avail * hw->info.bytes_per_frame;
    626     generic_free = audio_generic_buffer_get_free(hw);
    627     generic_in_use = hw->samples * hw->info.bytes_per_frame - generic_free;
    628     if (generic_in_use) {
    629         /*
    630          * This code can only be reached in the unlikely case that
    631          * snd_pcm_avail_update() returned a larger number of frames
    632          * than snd_pcm_writei() could write. Make sure that all
    633          * remaining bytes in the generic buffer can be written.
    634          */
    635         alsa_free = alsa_free > generic_in_use ? alsa_free - generic_in_use : 0;
    636     }
    637 
    638     return alsa_free;
    639 }
    640 
    641 static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
    642 {
    643     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    644     size_t pos = 0;
    645     size_t len_frames = len / hw->info.bytes_per_frame;
    646 
    647     while (len_frames) {
    648         char *src = advance(buf, pos);
    649         snd_pcm_sframes_t written;
    650 
    651         written = snd_pcm_writei(alsa->handle, src, len_frames);
    652 
    653         if (written <= 0) {
    654             switch (written) {
    655             case 0:
    656                 trace_alsa_wrote_zero(len_frames);
    657                 return pos;
    658 
    659             case -EPIPE:
    660                 if (alsa_recover(alsa->handle)) {
    661                     alsa_logerr(written, "Failed to write %zu frames\n",
    662                                 len_frames);
    663                     return pos;
    664                 }
    665                 trace_alsa_xrun_out();
    666                 continue;
    667 
    668             case -ESTRPIPE:
    669                 /*
    670                  * stream is suspended and waiting for an application
    671                  * recovery
    672                  */
    673                 if (alsa_resume(alsa->handle)) {
    674                     alsa_logerr(written, "Failed to write %zu frames\n",
    675                                 len_frames);
    676                     return pos;
    677                 }
    678                 trace_alsa_resume_out();
    679                 continue;
    680 
    681             case -EAGAIN:
    682                 return pos;
    683 
    684             default:
    685                 alsa_logerr(written, "Failed to write %zu frames from %p\n",
    686                             len, src);
    687                 return pos;
    688             }
    689         }
    690 
    691         pos += written * hw->info.bytes_per_frame;
    692         if (written < len_frames) {
    693             break;
    694         }
    695         len_frames -= written;
    696     }
    697 
    698     return pos;
    699 }
    700 
    701 static void alsa_fini_out (HWVoiceOut *hw)
    702 {
    703     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    704 
    705     ldebug ("alsa_fini\n");
    706     alsa_anal_close (&alsa->handle, &alsa->pollhlp);
    707 }
    708 
    709 static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as,
    710                          void *drv_opaque)
    711 {
    712     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    713     struct alsa_params_req req;
    714     struct alsa_params_obt obt;
    715     snd_pcm_t *handle;
    716     struct audsettings obt_as;
    717     Audiodev *dev = drv_opaque;
    718 
    719     req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
    720     req.freq = as->freq;
    721     req.nchannels = as->nchannels;
    722 
    723     if (alsa_open(0, &req, &obt, &handle, dev)) {
    724         return -1;
    725     }
    726 
    727     obt_as.freq = obt.freq;
    728     obt_as.nchannels = obt.nchannels;
    729     obt_as.fmt = obt.fmt;
    730     obt_as.endianness = obt.endianness;
    731 
    732     audio_pcm_init_info (&hw->info, &obt_as);
    733     hw->samples = obt.samples;
    734 
    735     alsa->pollhlp.s = hw->s;
    736     alsa->handle = handle;
    737     alsa->dev = dev;
    738     return 0;
    739 }
    740 
    741 #define VOICE_CTL_PAUSE 0
    742 #define VOICE_CTL_PREPARE 1
    743 #define VOICE_CTL_START 2
    744 
    745 static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl)
    746 {
    747     int err;
    748 
    749     if (ctl == VOICE_CTL_PAUSE) {
    750         err = snd_pcm_drop (handle);
    751         if (err < 0) {
    752             alsa_logerr (err, "Could not stop %s\n", typ);
    753             return -1;
    754         }
    755     } else {
    756         err = snd_pcm_prepare (handle);
    757         if (err < 0) {
    758             alsa_logerr (err, "Could not prepare handle for %s\n", typ);
    759             return -1;
    760         }
    761         if (ctl == VOICE_CTL_START) {
    762             err = snd_pcm_start(handle);
    763             if (err < 0) {
    764                 alsa_logerr (err, "Could not start handle for %s\n", typ);
    765                 return -1;
    766             }
    767         }
    768     }
    769 
    770     return 0;
    771 }
    772 
    773 static void alsa_enable_out(HWVoiceOut *hw, bool enable)
    774 {
    775     ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
    776     AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out;
    777 
    778     if (enable) {
    779         bool poll_mode = apdo->try_poll;
    780 
    781         ldebug("enabling voice\n");
    782         if (poll_mode && alsa_poll_out(hw)) {
    783             poll_mode = 0;
    784         }
    785         hw->poll_mode = poll_mode;
    786         alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE);
    787     } else {
    788         ldebug("disabling voice\n");
    789         if (hw->poll_mode) {
    790             hw->poll_mode = 0;
    791             alsa_fini_poll(&alsa->pollhlp);
    792         }
    793         alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE);
    794     }
    795 }
    796 
    797 static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
    798 {
    799     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
    800     struct alsa_params_req req;
    801     struct alsa_params_obt obt;
    802     snd_pcm_t *handle;
    803     struct audsettings obt_as;
    804     Audiodev *dev = drv_opaque;
    805 
    806     req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
    807     req.freq = as->freq;
    808     req.nchannels = as->nchannels;
    809 
    810     if (alsa_open(1, &req, &obt, &handle, dev)) {
    811         return -1;
    812     }
    813 
    814     obt_as.freq = obt.freq;
    815     obt_as.nchannels = obt.nchannels;
    816     obt_as.fmt = obt.fmt;
    817     obt_as.endianness = obt.endianness;
    818 
    819     audio_pcm_init_info (&hw->info, &obt_as);
    820     hw->samples = obt.samples;
    821 
    822     alsa->pollhlp.s = hw->s;
    823     alsa->handle = handle;
    824     alsa->dev = dev;
    825     return 0;
    826 }
    827 
    828 static void alsa_fini_in (HWVoiceIn *hw)
    829 {
    830     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
    831 
    832     alsa_anal_close (&alsa->handle, &alsa->pollhlp);
    833 }
    834 
    835 static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len)
    836 {
    837     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
    838     size_t pos = 0;
    839 
    840     while (len) {
    841         void *dst = advance(buf, pos);
    842         snd_pcm_sframes_t nread;
    843 
    844         nread = snd_pcm_readi(
    845             alsa->handle, dst, len / hw->info.bytes_per_frame);
    846 
    847         if (nread <= 0) {
    848             switch (nread) {
    849             case 0:
    850                 trace_alsa_read_zero(len);
    851                 return pos;
    852 
    853             case -EPIPE:
    854                 if (alsa_recover(alsa->handle)) {
    855                     alsa_logerr(nread, "Failed to read %zu frames\n", len);
    856                     return pos;
    857                 }
    858                 trace_alsa_xrun_in();
    859                 continue;
    860 
    861             case -EAGAIN:
    862                 return pos;
    863 
    864             default:
    865                 alsa_logerr(nread, "Failed to read %zu frames to %p\n",
    866                             len, dst);
    867                 return pos;
    868             }
    869         }
    870 
    871         pos += nread * hw->info.bytes_per_frame;
    872         len -= nread * hw->info.bytes_per_frame;
    873     }
    874 
    875     return pos;
    876 }
    877 
    878 static void alsa_enable_in(HWVoiceIn *hw, bool enable)
    879 {
    880     ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
    881     AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in;
    882 
    883     if (enable) {
    884         bool poll_mode = apdo->try_poll;
    885 
    886         ldebug("enabling voice\n");
    887         if (poll_mode && alsa_poll_in(hw)) {
    888             poll_mode = 0;
    889         }
    890         hw->poll_mode = poll_mode;
    891 
    892         alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START);
    893     } else {
    894         ldebug ("disabling voice\n");
    895         if (hw->poll_mode) {
    896             hw->poll_mode = 0;
    897             alsa_fini_poll(&alsa->pollhlp);
    898         }
    899         alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE);
    900     }
    901 }
    902 
    903 static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo)
    904 {
    905     if (!apdo->has_try_poll) {
    906         apdo->try_poll = true;
    907         apdo->has_try_poll = true;
    908     }
    909 }
    910 
    911 static void *alsa_audio_init(Audiodev *dev)
    912 {
    913     AudiodevAlsaOptions *aopts;
    914     assert(dev->driver == AUDIODEV_DRIVER_ALSA);
    915 
    916     aopts = &dev->u.alsa;
    917     alsa_init_per_direction(aopts->in);
    918     alsa_init_per_direction(aopts->out);
    919 
    920     /*
    921      * need to define them, as otherwise alsa produces no sound
    922      * doesn't set has_* so alsa_open can identify it wasn't set by the user
    923      */
    924     if (!dev->u.alsa.out->has_period_length) {
    925         /* 1024 frames assuming 44100Hz */
    926         dev->u.alsa.out->period_length = 1024 * 1000000 / 44100;
    927     }
    928     if (!dev->u.alsa.out->has_buffer_length) {
    929         /* 4096 frames assuming 44100Hz */
    930         dev->u.alsa.out->buffer_length = 4096ll * 1000000 / 44100;
    931     }
    932 
    933     /*
    934      * OptsVisitor sets unspecified optional fields to zero, but do not depend
    935      * on it...
    936      */
    937     if (!dev->u.alsa.in->has_period_length) {
    938         dev->u.alsa.in->period_length = 0;
    939     }
    940     if (!dev->u.alsa.in->has_buffer_length) {
    941         dev->u.alsa.in->buffer_length = 0;
    942     }
    943 
    944     return dev;
    945 }
    946 
    947 static void alsa_audio_fini (void *opaque)
    948 {
    949 }
    950 
    951 static struct audio_pcm_ops alsa_pcm_ops = {
    952     .init_out = alsa_init_out,
    953     .fini_out = alsa_fini_out,
    954     .write    = alsa_write,
    955     .buffer_get_free = alsa_buffer_get_free,
    956     .run_buffer_out = audio_generic_run_buffer_out,
    957     .enable_out = alsa_enable_out,
    958 
    959     .init_in  = alsa_init_in,
    960     .fini_in  = alsa_fini_in,
    961     .read     = alsa_read,
    962     .run_buffer_in = audio_generic_run_buffer_in,
    963     .enable_in = alsa_enable_in,
    964 };
    965 
    966 static struct audio_driver alsa_audio_driver = {
    967     .name           = "alsa",
    968     .descr          = "ALSA http://www.alsa-project.org",
    969     .init           = alsa_audio_init,
    970     .fini           = alsa_audio_fini,
    971     .pcm_ops        = &alsa_pcm_ops,
    972     .can_be_default = 1,
    973     .max_voices_out = INT_MAX,
    974     .max_voices_in  = INT_MAX,
    975     .voice_size_out = sizeof (ALSAVoiceOut),
    976     .voice_size_in  = sizeof (ALSAVoiceIn)
    977 };
    978 
    979 static void register_audio_alsa(void)
    980 {
    981     audio_driver_register(&alsa_audio_driver);
    982 }
    983 type_init(register_audio_alsa);