// 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 <fcntl.h>
#include <fuchsia/hardware/audio/llcpp/fidl.h>
#include <inttypes.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/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>

#include <algorithm>
#include <limits>

#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/auto_call.h>
#include <fbl/unique_fd.h>

namespace audio {
namespace utils {

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::time(ZX_TIME_INFINITE), &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(StreamDirection direction, uint32_t dev_id)
    : direction_(direction) {
  snprintf(name_, sizeof(name_), "/dev/class/audio-%s/%03u",
           direction == StreamDirection::kInput ? "input" : "output", dev_id);
}

AudioDeviceStream::AudioDeviceStream(StreamDirection direction, const char* dev_path)
    : direction_(direction) {
  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;

  zx::channel local, remote;
  auto res = zx::channel::create(0, &local, &remote);
  if (res != ZX_OK) {
    printf("Failed to create channel (res %d)\n", res);
  }
  res = fdio_service_connect(name(), remote.release());
  using Device = ::llcpp::fuchsia::hardware::audio::Device;
  Device::SyncClient client_wrap(std::move(local));
  Device::ResultOf::GetChannel channel_wrap = client_wrap.GetChannel();
  stream_ch_ = std::move(channel_wrap->channel.channel());

  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 = std::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::time(ZX_TIME_INFINITE), &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::GetClockDomain(
    audio_stream_cmd_get_clock_domain_resp_t* out_domain) const {
  if (out_domain == nullptr)
    return ZX_ERR_INVALID_ARGS;

  audio_stream_cmd_get_clock_domain_req req;
  req.hdr.cmd = AUDIO_STREAM_CMD_GET_CLOCK_DOMAIN;
  req.hdr.transaction_id = 1;

  return DoNoFailCall(stream_ch_, req, out_domain);
}

zx_status_t AudioDeviceStream::PlugMonitor(float duration, PlugMonitorCallback* monitor) {
  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, &monitor](
                             bool plug_state, zx_time_t plug_time) -> bool {
    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 (monitor) {
      return (*monitor)(plug_state, plug_time);
    }
    return true;  // Continue monitoring.
  };

  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);
      if (!ReportPlugState(plug_state, state.plug_state_time)) {
        printf("Monitoring finished after callback reported.\n");
        return ZX_OK;
      }
    }
  } 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 = std::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) {
        if (!ReportPlugState(resp.flags, resp.plug_state_time)) {
          printf("Monitoring finished after callback reported.\n");
          return ZX_OK;
        }
      }
    }
  }

  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(flags, 0u, rb_vmo_, 0u, rb_sz_,
                                   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
