// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <audio-utils/audio-device-stream.h>
#include <audio-utils/audio-input.h>
#include <audio-utils/audio-output.h>
#include <fbl/algorithm.h>
#include <fbl/unique_fd.h>
#include <fuchsia/hardware/audio/c/fidl.h>
#include <limits>
#include <fbl/auto_call.h>
#include <fcntl.h>
#include <inttypes.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>
#include <lib/zx/handle.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/device/audio.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/time.h>
#include <zircon/types.h>

namespace audio {
namespace utils {

static constexpr zx::duration CALL_TIMEOUT = zx::msec(500);
template <typename ReqType, typename RespType>
zx_status_t DoCallImpl(const zx::channel& channel, const ReqType& req, RespType* resp,
                       zx::handle* resp_handle_out, uint32_t* resp_len_out = nullptr) {
  zx_channel_call_args_t args;

  ZX_DEBUG_ASSERT((resp_handle_out == nullptr) || !resp_handle_out->is_valid());

  args.wr_bytes = const_cast<ReqType*>(&req);
  args.wr_num_bytes = sizeof(ReqType);
  args.wr_handles = nullptr;
  args.wr_num_handles = 0;
  args.rd_bytes = resp;
  args.rd_num_bytes = sizeof(RespType);
  args.rd_handles = resp_handle_out ? resp_handle_out->reset_and_get_address() : nullptr;
  args.rd_num_handles = resp_handle_out ? 1 : 0;

  uint32_t bytes, handles;

  zx_status_t status = channel.call(0, zx::deadline_after(CALL_TIMEOUT), &args, &bytes, &handles);
  if (status != ZX_OK) {
    printf("Cmd failure (cmd %04x, res %d)\n", req.hdr.cmd, status);
    return status;
  }

  // If the caller wants to know the size of the response length, let them
  // check to make sure it is consistent with what they expect.  Otherwise,
  // make sure that the number of bytes we got back matches the size of the
  // response structure.
  if (resp_len_out != nullptr) {
    *resp_len_out = bytes;
  } else if (bytes != sizeof(RespType)) {
    printf("Unexpected response size (got %u, expected %zu)\n", bytes, sizeof(RespType));
    return ZX_ERR_INTERNAL;
  }

  return ZX_OK;
}

template <typename ReqType, typename RespType>
zx_status_t DoCall(const zx::channel& channel, const ReqType& req, RespType* resp,
                   zx::handle* resp_handle_out = nullptr) {
  zx_status_t res = DoCallImpl(channel, req, resp, resp_handle_out);
  return (res != ZX_OK) ? res : resp->result;
}

template <typename ReqType, typename RespType>
zx_status_t DoNoFailCall(const zx::channel& channel, const ReqType& req, RespType* resp,
                         zx::handle* resp_handle_out = nullptr) {
  return DoCallImpl(channel, req, resp, resp_handle_out);
}

AudioDeviceStream::AudioDeviceStream(bool input, uint32_t dev_id) : input_(input) {
  snprintf(name_, sizeof(name_), "/dev/class/audio-%s/%03u", input_ ? "input" : "output", dev_id);
}

AudioDeviceStream::AudioDeviceStream(bool input, const char* dev_path) : input_(input) {
  strncpy(name_, dev_path, sizeof(name_) - 1);
  name_[sizeof(name_) - 1] = 0;
}

AudioDeviceStream::~AudioDeviceStream() { Close(); }

zx_status_t AudioDeviceStream::Open() {
  if (stream_ch_ != ZX_HANDLE_INVALID)
    return ZX_ERR_BAD_STATE;

  fbl::unique_fd fd{::open(name(), O_RDONLY)};
  if (!fd.is_valid()) {
    printf("Failed to open \"%s\"\n", name());
    return ZX_ERR_NOT_FOUND;
  }

  fzl::FdioCaller dev(std::move(fd));
  zx_status_t res = fuchsia_hardware_audio_DeviceGetChannel(dev.borrow_channel(),
                                                            stream_ch_.reset_and_get_address());

  if (res != ZX_OK) {
    printf("Failed to obtain channel (res %d)\n", res);
  }

  return res;
}

zx_status_t AudioDeviceStream::GetSupportedFormats(
    fbl::Vector<audio_stream_format_range_t>* out_formats) const {
  constexpr uint32_t MIN_RESP_SIZE = offsetof(audio_stream_cmd_get_formats_resp_t, format_ranges);
  audio_stream_cmd_get_formats_req req;
  audio_stream_cmd_get_formats_resp resp;
  uint32_t rxed;
  zx_status_t res;

  if (out_formats == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }

  req.hdr.cmd = AUDIO_STREAM_CMD_GET_FORMATS;
  req.hdr.transaction_id = 1;
  res = DoCallImpl(stream_ch_, req, &resp, nullptr, &rxed);
  if ((res != ZX_OK) || (rxed < MIN_RESP_SIZE)) {
    printf("Failed to fetch initial suppored format list chunk (res %d, rxed %u)\n", res, rxed);
    return res;
  }

  uint32_t expected_formats = resp.format_range_count;
  if (!expected_formats)
    return ZX_OK;

  out_formats->reset();
  fbl::AllocChecker ac;
  out_formats->reserve(expected_formats, &ac);
  if (!ac.check()) {
    printf("Failed to allocated %u entries for format ranges\n", expected_formats);
    return ZX_ERR_NO_MEMORY;
  }

  zx_txid_t txid = resp.hdr.transaction_id;
  uint32_t processed_formats = 0;
  while (true) {
    if (resp.hdr.cmd != AUDIO_STREAM_CMD_GET_FORMATS) {
      printf(
          "Unexpected response command while fetching formats "
          "(expected 0x%08x, got 0x%08x)\n",
          AUDIO_STREAM_CMD_GET_FORMATS, resp.hdr.cmd);
      return ZX_ERR_INTERNAL;
    }

    if (resp.hdr.transaction_id != txid) {
      printf(
          "Unexpected response transaction id while fetching formats "
          "(expected 0x%08x, got 0x%08x)\n",
          txid, resp.hdr.transaction_id);
      return ZX_ERR_INTERNAL;
    }

    if (resp.first_format_range_ndx != processed_formats) {
      printf("Bad format index while fetching formats (expected %u, got %hu)\n", processed_formats,
             resp.first_format_range_ndx);
      return ZX_ERR_INTERNAL;
    }

    uint32_t todo = fbl::min(static_cast<uint32_t>(expected_formats - processed_formats),
                             AUDIO_STREAM_CMD_GET_FORMATS_MAX_RANGES_PER_RESPONSE);
    size_t min_size = MIN_RESP_SIZE + (todo * sizeof(audio_stream_format_range_t));
    if (rxed < min_size) {
      printf("Short response while fetching formats (%u < %zu)\n", rxed, min_size);
      return ZX_ERR_INTERNAL;
    }

    for (uint16_t i = 0; i < todo; ++i) {
      out_formats->push_back(resp.format_ranges[i]);
    }

    processed_formats += todo;
    if (processed_formats == expected_formats)
      break;

    zx_signals_t pending_sig;
    res = stream_ch_.wait_one(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
                              zx::deadline_after(CALL_TIMEOUT), &pending_sig);
    if (res != ZX_OK) {
      printf("Failed to wait for next response after processing %u/%u formats (res %d)\n",
             processed_formats, expected_formats, res);
      return res;
    }

    res = stream_ch_.read(0u, &resp, nullptr, sizeof(resp), 0, &rxed, nullptr);
    if (res != ZX_OK) {
      printf("Failed to read next response after processing %u/%u formats (res %d)\n",
             processed_formats, expected_formats, res);
      return res;
    }
  }

  return ZX_OK;
}

zx_status_t AudioDeviceStream::GetPlugState(audio_stream_cmd_plug_detect_resp_t* out_state,
                                            bool enable_notify) const {
  ZX_DEBUG_ASSERT(out_state != nullptr);
  audio_stream_cmd_plug_detect_req req;

  req.hdr.cmd = AUDIO_STREAM_CMD_PLUG_DETECT;
  req.hdr.transaction_id = 1;
  req.flags = enable_notify ? AUDIO_PDF_ENABLE_NOTIFICATIONS : AUDIO_PDF_NONE;

  zx_status_t res = DoNoFailCall(stream_ch_, req, out_state);
  if (res != ZX_OK)
    printf("Failed to fetch plug detect information! (res %d)\n", res);

  return res;
}

void AudioDeviceStream::DisablePlugNotifications() {
  audio_stream_cmd_plug_detect_req req;

  req.hdr.cmd = static_cast<audio_cmd_t>(AUDIO_STREAM_CMD_PLUG_DETECT | AUDIO_FLAG_NO_ACK);
  req.hdr.transaction_id = 1;
  req.flags = AUDIO_PDF_DISABLE_NOTIFICATIONS;

  stream_ch_.write(0, &req, sizeof(req), nullptr, 0);
}

zx_status_t AudioDeviceStream::SetMute(bool mute) {
  audio_stream_cmd_set_gain_req req;
  audio_stream_cmd_set_gain_resp resp;

  req.hdr.cmd = AUDIO_STREAM_CMD_SET_GAIN;
  req.hdr.transaction_id = 1;
  req.flags = mute ? static_cast<audio_set_gain_flags_t>(AUDIO_SGF_MUTE_VALID | AUDIO_SGF_MUTE)
                   : AUDIO_SGF_MUTE_VALID;

  zx_status_t res = DoCall(stream_ch_, req, &resp);
  if (res != ZX_OK)
    printf("Failed to %smute stream! (res %d)\n", mute ? "" : "un", res);
  else
    printf("Stream is now %smuted\n", mute ? "" : "un");

  return res;
}

zx_status_t AudioDeviceStream::SetAgc(bool enabled) {
  audio_stream_cmd_set_gain_req req;
  audio_stream_cmd_set_gain_resp resp;

  req.hdr.cmd = AUDIO_STREAM_CMD_SET_GAIN;
  req.hdr.transaction_id = 1;
  req.flags = enabled ? static_cast<audio_set_gain_flags_t>(AUDIO_SGF_AGC_VALID | AUDIO_SGF_AGC)
                      : AUDIO_SGF_AGC_VALID;

  zx_status_t res = DoCall(stream_ch_, req, &resp);
  if (res != ZX_OK)
    printf("Failed to %sable AGC for stream! (res %d)\n", enabled ? "en" : "dis", res);
  else
    printf("Stream AGC is now %sabled\n", enabled ? "en" : "dis");

  return res;
}

zx_status_t AudioDeviceStream::SetGain(float gain) {
  audio_stream_cmd_set_gain_req req;
  audio_stream_cmd_set_gain_resp resp;

  req.hdr.cmd = AUDIO_STREAM_CMD_SET_GAIN;
  req.hdr.transaction_id = 1;
  req.flags = AUDIO_SGF_GAIN_VALID;
  req.gain = gain;

  zx_status_t res = DoCall(stream_ch_, req, &resp);
  if (res != ZX_OK) {
    printf("Failed to set gain to %.2f dB! (res %d)\n", gain, res);
  } else {
    printf("Gain is now %.2f dB.  Stream is %smuted.\n", resp.cur_gain, resp.cur_mute ? "" : "un");
  }

  return res;
}

zx_status_t AudioDeviceStream::GetGain(audio_stream_cmd_get_gain_resp_t* out_gain) const {
  if (out_gain == nullptr)
    return ZX_ERR_INVALID_ARGS;

  audio_stream_cmd_get_gain_req req;
  req.hdr.cmd = AUDIO_STREAM_CMD_GET_GAIN;
  req.hdr.transaction_id = 1;

  return DoNoFailCall(stream_ch_, req, out_gain);
}

zx_status_t AudioDeviceStream::GetUniqueId(audio_stream_cmd_get_unique_id_resp_t* out_id) const {
  if (out_id == nullptr)
    return ZX_ERR_INVALID_ARGS;

  audio_stream_cmd_get_unique_id_req req;
  req.hdr.cmd = AUDIO_STREAM_CMD_GET_UNIQUE_ID;
  req.hdr.transaction_id = 1;

  return DoNoFailCall(stream_ch_, req, out_id);
}

zx_status_t AudioDeviceStream::GetString(audio_stream_string_id_t id,
                                         audio_stream_cmd_get_string_resp_t* out_str) const {
  if (out_str == nullptr)
    return ZX_ERR_INVALID_ARGS;

  audio_stream_cmd_get_string_req req;
  req.hdr.cmd = AUDIO_STREAM_CMD_GET_STRING;
  req.hdr.transaction_id = 1;
  req.id = id;

  return DoNoFailCall(stream_ch_, req, out_str);
}

zx_status_t AudioDeviceStream::PlugMonitor(float duration) {
  const double duration_ns = static_cast<double>(duration) * ZX_SEC(1);
  const zx_time_t deadline = zx_deadline_after(static_cast<zx_duration_t>(duration_ns));
  audio_stream_cmd_plug_detect_resp resp;
  zx_status_t res = GetPlugState(&resp, true);
  if (res != ZX_OK)
    return res;

  zx_time_t last_plug_time = resp.plug_state_time;
  bool last_plug_state = (resp.flags & AUDIO_PDNF_PLUGGED);
  printf("Initial plug state is : %s.\n", last_plug_state ? "plugged" : "unplugged");

  if (resp.flags & AUDIO_PDNF_HARDWIRED) {
    printf("Stream reports that it is hardwired, Monitoring is not possible.\n");
    return ZX_OK;
  }

  auto ReportPlugState = [&last_plug_time, &last_plug_state](bool plug_state, zx_time_t plug_time) {
    printf("Plug State now : %s (%.3lf sec since last change).\n",
           plug_state ? "plugged" : "unplugged",
           static_cast<double>(zx_time_sub_time(plug_time, last_plug_time)) /
               static_cast<double>(ZX_SEC(1)));

    last_plug_state = plug_state;
    last_plug_time = plug_time;
  };

  if (resp.flags & AUDIO_PDNF_CAN_NOTIFY) {
    printf("Stream is capable of async notification.  Monitoring for %.2f seconds\n", duration);

    auto cleanup = fbl::MakeAutoCall([this]() { DisablePlugNotifications(); });
    while (true) {
      zx_signals_t pending;
      res = stream_ch_.wait_one(ZX_CHANNEL_PEER_CLOSED | ZX_CHANNEL_READABLE, zx::time(deadline),
                                &pending);

      if ((res != ZX_OK) || (pending & ZX_CHANNEL_PEER_CLOSED)) {
        if (res != ZX_ERR_TIMED_OUT)
          printf("Error while waiting for plug notification (res %d)\n", res);

        if (pending & ZX_CHANNEL_PEER_CLOSED)
          printf("Peer closed while waiting for plug notification\n");

        break;
      }

      ZX_DEBUG_ASSERT(pending & ZX_CHANNEL_READABLE);

      audio_stream_plug_detect_notify_t state;
      uint32_t bytes_read;
      res = stream_ch_.read(0, &state, nullptr, sizeof(state), 0, &bytes_read, nullptr);
      if (res != ZX_OK) {
        printf("Read failure while waiting for plug notification (res %d)\n", res);
        break;
      }

      if ((bytes_read != sizeof(state)) || (state.hdr.cmd != AUDIO_STREAM_PLUG_DETECT_NOTIFY)) {
        printf(
            "Size/type mismatch while waiting for plug notification.  "
            "Got (%u/%u) Expected (%zu/%u)\n",
            bytes_read, state.hdr.cmd, sizeof(state), AUDIO_STREAM_PLUG_DETECT_NOTIFY);
        break;
      }

      bool plug_state = (state.flags & AUDIO_PDNF_PLUGGED);
      ReportPlugState(plug_state, state.plug_state_time);
    }
  } else {
    printf("Stream is not capable of async notification.  Polling for %.2f seconds\n", duration);

    while (true) {
      zx_time_t now = zx_clock_get_monotonic();
      if (now >= deadline)
        break;

      zx_time_t next_wake = fbl::min(deadline, zx_time_add_duration(now, ZX_MSEC(100u)));

      zx_signals_t sigs;
      zx_status_t res = stream_ch_.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time(next_wake), &sigs);

      if ((res != ZX_OK) && (res != ZX_ERR_TIMED_OUT)) {
        printf("Error waiting on stream channel (res %d)\n", res);
        break;
      }

      if (sigs & ZX_CHANNEL_PEER_CLOSED) {
        printf("Peer closed connection while polling plug state\n");
        break;
      }

      res = GetPlugState(&resp, true);
      if (res != ZX_OK) {
        printf("Failed to poll plug state (res %d)\n", res);
        break;
      }

      bool plug_state = (resp.flags & AUDIO_PDNF_PLUGGED);
      if (plug_state != last_plug_state)
        ReportPlugState(resp.flags, resp.plug_state_time);
    }
  }

  printf("Monitoring finished.\n");

  return ZX_OK;
}

zx_status_t AudioDeviceStream::SetFormat(uint32_t frames_per_second, uint16_t channels,
                                         audio_sample_format_t sample_format) {
  if ((stream_ch_ == ZX_HANDLE_INVALID) || (rb_ch_ != ZX_HANDLE_INVALID))
    return ZX_ERR_BAD_STATE;

  auto noflag_format =
      static_cast<audio_sample_format_t>((sample_format & ~AUDIO_SAMPLE_FORMAT_FLAG_MASK));

  switch (noflag_format) {
    case AUDIO_SAMPLE_FORMAT_8BIT:
      sample_size_ = 1;
      break;
    case AUDIO_SAMPLE_FORMAT_16BIT:
      sample_size_ = 2;
      break;
    case AUDIO_SAMPLE_FORMAT_24BIT_PACKED:
      sample_size_ = 3;
      break;
    case AUDIO_SAMPLE_FORMAT_20BIT_IN32:
    case AUDIO_SAMPLE_FORMAT_24BIT_IN32:
    case AUDIO_SAMPLE_FORMAT_32BIT:
    case AUDIO_SAMPLE_FORMAT_32BIT_FLOAT:
      sample_size_ = 4;
      break;
    default:
      return ZX_ERR_NOT_SUPPORTED;
  }

  channel_cnt_ = channels;
  frame_sz_ = channels * sample_size_;
  frame_rate_ = frames_per_second;
  sample_format_ = sample_format;

  audio_stream_cmd_set_format_req_t req;
  audio_stream_cmd_set_format_resp_t resp;
  req.hdr.cmd = AUDIO_STREAM_CMD_SET_FORMAT;
  req.hdr.transaction_id = 1;
  req.frames_per_second = frames_per_second;
  req.channels = channels;
  req.sample_format = sample_format;

  zx::handle tmp;
  zx_status_t res = DoCall(stream_ch_, req, &resp, &tmp);
  if (res != ZX_OK) {
    printf("Failed to set format %uHz %hu-Ch fmt 0x%x (res %d)\n", frames_per_second, channels,
           sample_format, res);
  }

  external_delay_nsec_ = resp.external_delay_nsec;

  // TODO(johngro) : Verify the type of this handle before transferring it to
  // our ring buffer channel handle.
  rb_ch_.reset(tmp.release());

  return res;
}

zx_status_t AudioDeviceStream::GetBuffer(uint32_t frames, uint32_t irqs_per_ring) {
  zx_status_t res;

  if (!frames)
    return ZX_ERR_INVALID_ARGS;

  if (!rb_ch_.is_valid() || rb_vmo_.is_valid() || !frame_sz_)
    return ZX_ERR_BAD_STATE;

  // Stash the FIFO depth, in case users need to know it.
  {
    audio_rb_cmd_get_fifo_depth_req_t req;
    audio_rb_cmd_get_fifo_depth_resp_t resp;

    req.hdr.cmd = AUDIO_RB_CMD_GET_FIFO_DEPTH;
    req.hdr.transaction_id = 1;
    res = DoCall(rb_ch_, req, &resp);
    if (res != ZX_OK) {
      printf("Failed to fetch fifo depth (res %d)\n", res);
      return res;
    }

    fifo_depth_ = resp.fifo_depth;
  }

  uint64_t rb_sz;
  {
    // Get a VMO representing the ring buffer we will share with the audio driver.
    audio_rb_cmd_get_buffer_req_t req;
    audio_rb_cmd_get_buffer_resp_t resp;

    req.hdr.cmd = AUDIO_RB_CMD_GET_BUFFER;
    req.hdr.transaction_id = 1;
    req.min_ring_buffer_frames = frames;
    req.notifications_per_ring = irqs_per_ring;

    zx::handle tmp;
    res = DoCall(rb_ch_, req, &resp, &tmp);

    if ((res == ZX_OK) && (resp.result != ZX_OK))
      res = resp.result;

    if (res != ZX_OK) {
      printf("Failed to get driver ring buffer VMO (res %d)\n", res);
      return res;
    }

    rb_sz = static_cast<uint64_t>(resp.num_ring_buffer_frames) * frame_sz_;

    // TODO(johngro) : Verify the type of this handle before transferring it to our VMO handle.
    rb_vmo_.reset(tmp.release());
  }

  // We have the buffer, fetch the underlying size of the VMO (a rounded up
  // multiple of pages) and sanity check it against the effective size the
  // driver reported.
  uint64_t rb_page_sz;
  res = rb_vmo_.get_size(&rb_page_sz);
  if (res != ZX_OK) {
    printf("Failed to fetch ring buffer VMO size (res %d)\n", res);
    return res;
  }

  if ((rb_sz > std::numeric_limits<decltype(rb_sz_)>::max()) || (rb_sz > rb_page_sz)) {
    printf(
        "Bad ring buffer size returned by audio driver! "
        "(kernel size = %lu driver size = %lu)\n",
        rb_page_sz, rb_sz);
    return ZX_ERR_INVALID_ARGS;
  }

  rb_sz_ = static_cast<decltype(rb_sz_)>(rb_sz);

  // Map the VMO into our address space
  // TODO(johngro) : How do I specify the cache policy for this mapping?
  uint32_t flags = input_ ? ZX_VM_PERM_READ : ZX_VM_PERM_READ | ZX_VM_PERM_WRITE;
  res = zx::vmar::root_self()->map(0u, rb_vmo_, 0u, rb_sz_, flags,
                                   reinterpret_cast<uintptr_t*>(&rb_virt_));

  if (res != ZX_OK) {
    printf("Failed to map ring buffer VMO (res %d)\n", res);
    return res;
  }

  // Success!  If this is an output device, zero out the buffer and we are done.
  if (!input_) {
    memset(rb_virt_, 0, rb_sz_);
  }

  return ZX_OK;
}

zx_status_t AudioDeviceStream::StartRingBuffer() {
  if (rb_ch_ == ZX_HANDLE_INVALID)
    return ZX_ERR_BAD_STATE;

  audio_rb_cmd_start_req_t req;
  audio_rb_cmd_start_resp_t resp;

  req.hdr.cmd = AUDIO_RB_CMD_START;
  req.hdr.transaction_id = 1;

  zx_status_t res = DoCall(rb_ch_, req, &resp);

  if (res == ZX_OK) {
    start_time_ = resp.start_time;
  }

  return res;
}

zx_status_t AudioDeviceStream::StopRingBuffer() {
  if (rb_ch_ == ZX_HANDLE_INVALID)
    return ZX_ERR_BAD_STATE;

  start_time_ = 0;

  audio_rb_cmd_stop_req_t req;
  audio_rb_cmd_stop_resp_t resp;

  req.hdr.cmd = AUDIO_RB_CMD_STOP;
  req.hdr.transaction_id = 1;

  return DoCall(rb_ch_, req, &resp);
}

void AudioDeviceStream::ResetRingBuffer() {
  if (rb_virt_ != nullptr) {
    ZX_DEBUG_ASSERT(rb_sz_ != 0);
    zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(rb_virt_), rb_sz_);
  }
  rb_ch_.reset();
  rb_vmo_.reset();
  rb_sz_ = 0;
  rb_virt_ = nullptr;
}

void AudioDeviceStream::Close() {
  ResetRingBuffer();
  stream_ch_.reset();
}

bool AudioDeviceStream::IsChannelConnected(const zx::channel& ch) {
  if (!ch.is_valid())
    return false;

  zx_signals_t junk;
  return ch.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time(), &junk) != ZX_ERR_TIMED_OUT;
}

}  // namespace utils
}  // namespace audio
