18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU OSS audio driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003-2005 Vassili Karpov (malc)
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stdlib.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/mman.h>
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ioctl.h>
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __OpenBSD__
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <soundcard.h>
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/soundcard.h>
325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
34e90d665cd63a0bc5c3306e1ee3e98ad362546b16David 'Digit' Turner#include "qemu/host-utils.h"
35e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "audio.h"
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define AUDIO_CAP "oss"
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "audio_int.h"
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#if defined OSS_GETVERSION && defined SNDCTL_DSP_POLICY
425d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#define USE_DSP_POLICY
435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#endif
444e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct OSSVoiceOut {
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceOut hw;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *pcm_buf;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
495d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int wpos;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nfrags;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fragsize;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int mmapped;
535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int pending;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} OSSVoiceOut;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct OSSVoiceIn {
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceIn hw;
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void *pcm_buf;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nfrags;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fragsize;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} OSSVoiceIn;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct {
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int try_mmap;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nfrags;
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fragsize;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *devpath_out;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *devpath_in;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int debug;
715d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int exclusive;
725d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int policy;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} conf = {
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    .try_mmap = 0,
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    .nfrags = 4,
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    .fragsize = 4096,
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    .devpath_out = "/dev/dsp",
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    .devpath_in = "/dev/dsp",
795d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .debug = 0,
805d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .exclusive = 0,
815d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .policy = 5
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct oss_params {
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int freq;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audfmt_e fmt;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nchannels;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nfrags;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fragsize;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start (ap, fmt);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_vlog (AUDIO_CAP, fmt, ap);
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end (ap);
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void GCC_FMT_ATTR (3, 4) oss_logerr2 (
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err,
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *typ,
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *fmt,
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ...
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start (ap, fmt);
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_vlog (AUDIO_CAP, fmt, ap);
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end (ap);
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void oss_anal_close (int *fdp)
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int err;
1245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1255d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    qemu_set_fd_handler (*fdp, NULL, NULL, NULL);
1265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    err = close (*fdp);
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *fdp = -1;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1335d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic void oss_helper_poll_out (void *opaque)
1345d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner{
1355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    (void) opaque;
1365d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    audio_run ("oss_poll_out");
1375d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner}
1385d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1395d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic void oss_helper_poll_in (void *opaque)
1405d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner{
1415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    (void) opaque;
1425d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    audio_run ("oss_poll_in");
1435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner}
1445d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1455d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int oss_poll_out (HWVoiceOut *hw)
1465d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner{
1475d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
1485d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1495d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    return qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL);
1505d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner}
1515d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1525d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int oss_poll_in (HWVoiceIn *hw)
1535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner{
1545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
1555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    return qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL);
1575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner}
1585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_write (SWVoiceOut *sw, void *buf, int len)
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_write (sw, buf, len);
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int aud_to_ossfmt (audfmt_e fmt)
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (fmt) {
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S8:
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return AFMT_S8;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U8:
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return AFMT_U8;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_S16:
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return AFMT_S16_LE;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AUD_FMT_U16:
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return AFMT_U16_LE;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Internal logic error: Bad audio format %d\n", fmt);
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_AUDIO
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        abort ();
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return AFMT_U8;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (ossfmt) {
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AFMT_S8:
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        *endianness = 0;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fmt = AUD_FMT_S8;
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AFMT_U8:
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *endianness = 0;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fmt = AUD_FMT_U8;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AFMT_S16_LE:
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *endianness = 0;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fmt = AUD_FMT_S16;
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AFMT_U16_LE:
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *endianness = 0;
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fmt = AUD_FMT_U16;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AFMT_S16_BE:
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *endianness = 1;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fmt = AUD_FMT_S16;
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AFMT_U16_BE:
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *endianness = 1;
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fmt = AUD_FMT_U16;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Unrecognized audio format %d\n", ossfmt);
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined DEBUG_MISMATCHES || defined DEBUG
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void oss_dump_info (struct oss_params *req, struct oss_params *obt)
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("parameter | requested value | obtained value\n");
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("channels  |      %10d |     %10d\n",
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           req->nchannels, obt->nchannels);
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("nfrags    |      %10d |     %10d\n", req->nfrags, obt->nfrags);
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("fragsize  |      %10d |     %10d\n",
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           req->fragsize, obt->fragsize);
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#ifdef USE_DSP_POLICY
2445d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int oss_get_version (int fd, int *version, const char *typ)
2455d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner{
2465d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    if (ioctl (fd, OSS_GETVERSION, &version)) {
2475d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2485d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        /*
2495d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         * Looks like atm (20100109) FreeBSD knows OSS_GETVERSION
2505d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         * since 7.x, but currently only on the mixer device (or in
2515d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         * the Linuxolator), and in the native version that part of
2525d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         * the code is in fact never reached so the ioctl fails anyway.
2535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         * Until this is fixed, just check the errno and if its what
2545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         * FreeBSD's sound drivers return atm assume they are new enough.
2555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner         */
2565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (errno == EINVAL) {
2575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            *version = 0x040000;
2585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            return 0;
2595d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
2605d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#endif
2615d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        oss_logerr2 (errno, typ, "Failed to get OSS version\n");
2625d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        return -1;
2635d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    }
2645d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    return 0;
2655d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner}
2665d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#endif
2675d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_open (int in, struct oss_params *req,
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     struct oss_params *obt, int *pfd)
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
2725d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int oflags = conf.exclusive ? O_EXCL : 0;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_buf_info abinfo;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fmt, freq, nchannels;
2755d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int setfragment = 1;
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *dspname = in ? conf.devpath_in : conf.devpath_out;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *typ = in ? "ADC" : "DAC";
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2795d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    /* Kludge needed to have working mmap on Linux */
2805d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    oflags |= conf.try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
2815d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
2825d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    fd = open (dspname, oflags | O_NONBLOCK);
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (-1 == fd) {
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    freq = req->freq;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    nchannels = req->nchannels;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fmt = req->fmt;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     req->nchannels);
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err;
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl (fd, SNDCTL_DSP_NONBLOCK, NULL)) {
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err;
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3135d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#ifdef USE_DSP_POLICY
3145d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    if (conf.policy >= 0) {
3155d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int version;
3165d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
3175d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (!oss_get_version (fd, &version, typ)) {
3185d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (conf.debug) {
3195d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                dolog ("OSS version = %#x\n", version);
3205d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
3215d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
3225d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (version >= 0x040000) {
3235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                int policy = conf.policy;
3245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
3255d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                    oss_logerr2 (errno, typ,
3265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                                 "Failed to set timing policy to %d\n",
3275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                                 conf.policy);
3285d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                    goto err;
3295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                }
3305d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                setfragment = 0;
3315d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
3325d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
3335d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    }
3345d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#endif
3355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
3365d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    if (setfragment) {
3375d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int mmmmssss = (req->nfrags << 16) | ctz32 (req->fragsize);
3385d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
3395d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
3405d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                         req->nfrags, req->fragsize);
3415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            goto err;
3425d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) {
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_logerr2 (errno, typ, "Failed to get buffer length\n");
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err;
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!abinfo.fragstotal || !abinfo.fragsize) {
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        AUD_log (AUDIO_CAP, "Returned bogus buffer information(%d, %d) for %s\n",
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                 abinfo.fragstotal, abinfo.fragsize, typ);
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto err;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt->fmt = fmt;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt->nchannels = nchannels;
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt->freq = freq;
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt->nfrags = abinfo.fragstotal;
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt->fragsize = abinfo.fragsize;
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pfd = fd;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_MISMATCHES
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((req->fmt != obt->fmt) ||
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (req->nchannels != obt->nchannels) ||
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (req->freq != obt->freq) ||
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (req->fragsize != obt->fragsize) ||
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (req->nfrags != obt->nfrags)) {
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Audio parameters mismatch\n");
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_dump_info (req, obt);
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss_dump_info (req, obt);
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project err:
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss_anal_close (&fd);
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3845d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic void oss_write_pending (OSSVoiceOut *oss)
3855d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner{
3865d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    HWVoiceOut *hw = &oss->hw;
3875d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
3885d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    if (oss->mmapped) {
3895d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        return;
3905d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    }
3915d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
3925d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    while (oss->pending) {
3935d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int samples_written;
3945d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        ssize_t bytes_written;
3955d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int samples_till_end = hw->samples - oss->wpos;
3965d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int samples_to_write = audio_MIN (oss->pending, samples_till_end);
3975d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int bytes_to_write = samples_to_write << hw->info.shift;
3985d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift);
3995d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
4005d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        bytes_written = write (oss->fd, pcm, bytes_to_write);
4015d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (bytes_written < 0) {
4025d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (errno != EAGAIN) {
4035d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                oss_logerr (errno, "failed to write %d bytes\n",
4045d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                            bytes_to_write);
4055d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
4065d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            break;
4075d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
4085d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
4095d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (bytes_written & hw->info.align) {
4105d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            dolog ("misaligned write asked for %d, but got %zd\n",
4115d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                   bytes_to_write, bytes_written);
4125d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            return;
4135d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
4145d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
4155d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        samples_written = bytes_written >> hw->info.shift;
4165d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        oss->pending -= samples_written;
4175d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        oss->wpos = (oss->wpos + samples_written) % hw->samples;
4185d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (bytes_written - bytes_to_write) {
4195d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            break;
4205d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
4215d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    }
4225d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner}
4235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
4245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int oss_run_out (HWVoiceOut *hw, int live)
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
4275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int err, decr;
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct audio_buf_info abinfo;
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct count_info cntinfo;
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bufsize;
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bufsize = hw->samples << hw->info.shift;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (oss->mmapped) {
4355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        int bytes, pos;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (err < 0) {
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        pos = hw->rpos << hw->info.shift;
4445d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize);
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        decr = audio_MIN (bytes >> hw->info.shift, live);
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (err < 0) {
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (abinfo.bytes > bufsize) {
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (conf.debug) {
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
4575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                       "please report your OS/audio hw to av1474@comtv.ru\n",
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       abinfo.bytes, bufsize);
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            abinfo.bytes = bufsize;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (abinfo.bytes < 0) {
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (conf.debug) {
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       abinfo.bytes, bufsize);
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!decr) {
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4775d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending);
4785d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    oss->pending += decr;
4795d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    oss_write_pending (oss);
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void oss_fini_out (HWVoiceOut *hw)
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ldebug ("oss_fini\n");
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss_anal_close (&oss->fd);
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (oss->pcm_buf) {
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (oss->mmapped) {
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (err) {
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            oss->pcm_buf, hw->samples << hw->info.shift);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
501aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner            g_free (oss->pcm_buf);
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss->pcm_buf = NULL;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct oss_params req, obt;
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int endianness;
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audfmt_e effective_fmt;
5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings obt_as;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->fd = -1;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.fmt = aud_to_ossfmt (as->fmt);
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.freq = as->freq;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.nchannels = as->nchannels;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.fragsize = conf.fragsize;
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.nfrags = conf.nfrags;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (oss_open (0, &req, &obt, &fd)) {
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_anal_close (&fd);
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.freq = obt.freq;
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.nchannels = obt.nchannels;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.fmt = effective_fmt;
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.endianness = endianness;
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&hw->info, &obt_as);
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->nfrags = obt.nfrags;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->fragsize = obt.fragsize;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (obt.nfrags * obt.fragsize & hw->info.align) {
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n",
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               obt.nfrags * obt.fragsize, hw->info.align + 1);
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->mmapped = 0;
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (conf.try_mmap) {
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss->pcm_buf = mmap (
5545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            NULL,
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hw->samples << hw->info.shift,
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROT_READ | PROT_WRITE,
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            MAP_SHARED,
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fd,
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            0
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            );
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (oss->pcm_buf == MAP_FAILED) {
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            oss_logerr (errno, "Failed to map %d bytes of DAC\n",
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        hw->samples << hw->info.shift);
5645d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
5655d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        else {
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int err;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int trig = 0;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else {
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                trig = PCM_ENABLE_OUTPUT;
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    oss_logerr (
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        errno,
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        );
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else {
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    oss->mmapped = 1;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!oss->mmapped) {
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (err) {
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                oss->pcm_buf, hw->samples << hw->info.shift);
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!oss->mmapped) {
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss->pcm_buf = audio_calloc (
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            AUDIO_FUNC,
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hw->samples,
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            1 << hw->info.shift
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            );
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!oss->pcm_buf) {
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog (
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                "Could not allocate DAC buffer (%d samples, each %d bytes)\n",
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                hw->samples,
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                1 << hw->info.shift
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                );
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            oss_anal_close (&fd);
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->fd = fd;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int trig;
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceOut *oss = (OSSVoiceOut *) hw;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cmd) {
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_ENABLE:
6225d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        {
6235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            va_list ap;
6245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            int poll_mode;
6255d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            va_start (ap, cmd);
6275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            poll_mode = va_arg (ap, int);
6285d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            va_end (ap);
6295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6305d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            ldebug ("enabling voice\n");
6315d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (poll_mode && oss_poll_out (hw)) {
6325d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                poll_mode = 0;
6335d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
6345d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            hw->poll_mode = poll_mode;
6355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6365d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (!oss->mmapped) {
6375d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                return 0;
6385d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
6395d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6405d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
6415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            trig = PCM_ENABLE_OUTPUT;
6425d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
6435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                oss_logerr (
6445d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                    errno,
6455d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                    "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
6465d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                    );
6475d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                return -1;
6485d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_DISABLE:
6535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (hw->poll_mode) {
6545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
6555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            hw->poll_mode = 0;
6565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
6575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (!oss->mmapped) {
6595d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            return 0;
6605d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
6615d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ldebug ("disabling voice\n");
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        trig = 0;
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct oss_params req, obt;
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int endianness;
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audfmt_e effective_fmt;
6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct audsettings obt_as;
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->fd = -1;
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.fmt = aud_to_ossfmt (as->fmt);
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.freq = as->freq;
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.nchannels = as->nchannels;
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.fragsize = conf.fragsize;
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    req.nfrags = conf.nfrags;
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (oss_open (1, &req, &obt, &fd)) {
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_anal_close (&fd);
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.freq = obt.freq;
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.nchannels = obt.nchannels;
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.fmt = effective_fmt;
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    obt_as.endianness = endianness;
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    audio_pcm_init_info (&hw->info, &obt_as);
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->nfrags = obt.nfrags;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->fragsize = obt.fragsize;
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (obt.nfrags * obt.fragsize & hw->info.align) {
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n",
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               obt.nfrags * obt.fragsize, hw->info.align + 1);
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!oss->pcm_buf) {
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               hw->samples, 1 << hw->info.shift);
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss_anal_close (&fd);
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss->fd = fd;
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void oss_fini_in (HWVoiceIn *hw)
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    oss_anal_close (&oss->fd);
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (oss->pcm_buf) {
734aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free (oss->pcm_buf);
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        oss->pcm_buf = NULL;
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_run_in (HWVoiceIn *hw)
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int hwshift = hw->info.shift;
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int live = audio_pcm_hw_get_live_in (hw);
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int dead = hw->samples - live;
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size_t read_samples = 0;
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct {
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int add;
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int len;
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } bufs[2] = {
7515d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        { .add = hw->wpos, .len = 0 },
7525d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        { .add = 0,        .len = 0 }
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    };
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dead) {
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (hw->wpos + dead > hw->samples) {
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bufs[0].len = (hw->samples - hw->wpos) << hwshift;
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bufs[0].len = dead << hwshift;
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < 2; ++i) {
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ssize_t nread;
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bufs[i].len) {
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nread = read (oss->fd, p, bufs[i].len);
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (nread > 0) {
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (nread & hw->info.align) {
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    dolog ("warning: Misaligned read %zd (requested %d), "
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           "alignment %d\n", nread, bufs[i].add << hwshift,
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           hw->info.align + 1);
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                read_samples += nread >> hwshift;
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &nominal_volume);
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (bufs[i].len - nread) {
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (nread == -1) {
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (errno) {
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case EINTR:
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case EAGAIN:
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default:
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        oss_logerr (
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            errno,
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            "Failed to read %d bytes of audio (to %p)\n",
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            bufs[i].len, p
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            );
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->wpos = (hw->wpos + read_samples) % hw->samples;
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return read_samples;
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_read (SWVoiceIn *sw, void *buf, int size)
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_read (sw, buf, size);
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8165d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    OSSVoiceIn *oss = (OSSVoiceIn *) hw;
8175d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
8185d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    switch (cmd) {
8195d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    case VOICE_ENABLE:
8205d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        {
8215d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            va_list ap;
8225d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            int poll_mode;
8235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
8245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            va_start (ap, cmd);
8255d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            poll_mode = va_arg (ap, int);
8265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            va_end (ap);
8275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
8285d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            if (poll_mode && oss_poll_in (hw)) {
8295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner                poll_mode = 0;
8305d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            }
8315d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            hw->poll_mode = poll_mode;
8325d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
8335d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        break;
8345d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
8355d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    case VOICE_DISABLE:
8365d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        if (hw->poll_mode) {
8375d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            hw->poll_mode = 0;
8385d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner            qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
8395d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        }
8405d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        break;
8415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    }
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void *oss_audio_init (void)
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return &conf;
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void oss_audio_fini (void *opaque)
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    (void) opaque;
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct audio_option oss_options[] = {
8565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "FRAGSIZE",
8585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
8595d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.fragsize,
8605d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Fragment size in bytes"
8615d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8625d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8635d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "NFRAGS",
8645d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
8655d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.nfrags,
8665d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Number of fragments"
8675d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8685d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8695d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "MMAP",
8705d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_BOOL,
8715d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.try_mmap,
8725d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Try using memory mapped access"
8735d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8745d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8755d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "DAC_DEV",
8765d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_STR,
8775d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.devpath_out,
8785d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Path to DAC device"
8795d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8805d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8815d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "ADC_DEV",
8825d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_STR,
8835d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.devpath_in,
8845d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Path to ADC device"
8855d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8865d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8875d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "EXCLUSIVE",
8885d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_BOOL,
8895d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.exclusive,
8905d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Open device in exclusive mode (vmix wont work)"
8915d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8925d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#ifdef USE_DSP_POLICY
8935d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
8945d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "POLICY",
8955d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
8965d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.policy,
8975d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Set the timing policy of the device, -1 to use fragment mode",
8985d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
8995d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#endif
9005d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9015d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "DEBUG",
9025d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_BOOL,
9035d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.debug,
9045d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Turn on some debugging messages"
9055d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9065d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { /* End of list */ }
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct audio_pcm_ops oss_pcm_ops = {
9105d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init_out = oss_init_out,
9115d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini_out = oss_fini_out,
9125d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .run_out  = oss_run_out,
9135d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .write    = oss_write,
9145d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .ctl_out  = oss_ctl_out,
9155d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
9165d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init_in  = oss_init_in,
9175d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini_in  = oss_fini_in,
9185d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .run_in   = oss_run_in,
9195d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .read     = oss_read,
9205d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .ctl_in   = oss_ctl_in
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct audio_driver oss_audio_driver = {
9245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .name           = "oss",
9255d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .descr          = "OSS http://www.opensound.com",
9265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .options        = oss_options,
9275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init           = oss_audio_init,
9285d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini           = oss_audio_fini,
9295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .pcm_ops        = &oss_pcm_ops,
9305d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .can_be_default = 1,
9315d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .max_voices_out = INT_MAX,
9325d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .max_voices_in  = INT_MAX,
9335d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .voice_size_out = sizeof (OSSVoiceOut),
9345d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .voice_size_in  = sizeof (OSSVoiceIn)
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
936