src/media/audio/drivers/virtual_audio/virtual_audio_stream.cc
// Upon success, drivers should return a valid VMO with appropriate permissions (READ | MAP |
// TRANSFER for inputs, WRITE as well for outputs) as well as reporting the total number of usable
// frames in the ring.
//
// Format must already be set: a ring buffer channel (over which this command arrived) is provided
// as the return value from a successful SetFormat call.
Upon success, drivers should return a valid VMO with appropriate permissions (READ | MAP |
TRANSFER for inputs, WRITE as well for outputs) as well as reporting the total number of usable
frames in the ring.

Format must already be set: a ring buffer channel (over which this command arrived) is provided
as the return value from a successful SetFormat call.
Upon success drivers should return a valid VMO with appropriate permissions ( READ | MAP | TRANSFER for inputs WRITE as well for outputs ) as well as reporting the total number of usable frames in the ring . Format must already be set : a ring buffer channel ( over which this command arrived ) is provided as the return value from a successful SetFormat call .
zx_status_t VirtualAudioStream::GetBuffer(const audio::audio_proto::RingBufGetBufferReq& req,
                                          uint32_t* out_num_rb_frames, zx::vmo* out_buffer) {
  if (req.notifications_per_ring > req.min_ring_buffer_frames) {
    zxlogf(ERROR, "req.notifications_per_ring too big");
    return ZX_ERR_OUT_OF_RANGE;
  }
  if (req.min_ring_buffer_frames > max_buffer_frames_) {
    zxlogf(ERROR, "req.min_ring_buffer_frames too big");
    return ZX_ERR_OUT_OF_RANGE;
  }
  num_ring_buffer_frames_ = std::max(
      min_buffer_frames_,
      fbl::round_up<uint32_t, uint32_t>(req.min_ring_buffer_frames, modulo_buffer_frames_));
  uint32_t ring_buffer_size =
      fbl::round_up<size_t, size_t>(num_ring_buffer_frames_ * frame_size_, ZX_PAGE_SIZE);
  if (ring_buffer_mapper_.start() != nullptr) {
    ring_buffer_mapper_.Unmap();
  }
  zx_status_t status = ring_buffer_mapper_.CreateAndMap(
      ring_buffer_size, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, nullptr, &ring_buffer_vmo_,
      ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP | ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s failed to create ring buffer vmo - %d", __func__, status);
    return status;
  }
  status = ring_buffer_vmo_.duplicate(
      ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP, out_buffer);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s failed to duplicate VMO handle for out param - %d", __func__, status);
    return status;
  }
  notifications_per_ring_ = req.notifications_per_ring;
  if (notifications_per_ring_ == 0) {
    notification_period_ = zx::duration(0);
  } else {
    notification_period_ = zx::duration((zx::sec(1) * num_ring_buffer_frames_) /
                                        (frame_rate_ * notifications_per_ring_));
  }
  if (using_alt_notifications_) {
    if (alt_notifications_per_ring_ == 0) {
      alt_notification_period_ = zx::duration(0);
    } else {
      alt_notification_period_ = zx::duration((zx::sec(1) * num_ring_buffer_frames_) /
                                              (frame_rate_ * alt_notifications_per_ring_));
    }
  }
  *out_num_rb_frames = num_ring_buffer_frames_;
  zx::vmo duplicate_vmo;
  status = ring_buffer_vmo_.duplicate(
      ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP, &duplicate_vmo);
  if (status != ZX_OK) {
    zxlogf(ERROR, "%s failed to duplicate VMO handle for notification - %d", __func__, status);
    return status;
  }
  parent_->NotifyBufferCreated(std::move(duplicate_vmo), num_ring_buffer_frames_,
                               notifications_per_ring_);
  return ZX_OK;
}
zx_status_t VirtualAudioStream :: GetBuffer ( const audio :: audio_proto :: RingBufGetBufferReq & req , uint32_t * out_num_rb_frames , zx :: vmo * out_buffer ) { if ( req . notifications_per_ring > req . min_ring_buffer_frames ) { zxlogf ( ERROR , " " ) ; return ZX_ERR_OUT_OF_RANGE ; } if ( req . min_ring_buffer_frames > max_buffer_frames_ ) { zxlogf ( ERROR , " " ) ; return ZX_ERR_OUT_OF_RANGE ; } num_ring_buffer_frames_ = std :: max ( min_buffer_frames_ , fbl :: round_up < uint32_t , uint32_t > ( req . min_ring_buffer_frames , modulo_buffer_frames_ ) ) ; uint32_t ring_buffer_size = fbl :: round_up < size_t , size_t > ( num_ring_buffer_frames_ * frame_size_ , ZX_PAGE_SIZE ) ; if ( ring_buffer_mapper_ . start ( ) != nullptr ) { ring_buffer_mapper_ . Unmap ( ) ; } zx_status_t status = ring_buffer_mapper_ . CreateAndMap ( ring_buffer_size , ZX_VM_PERM_READ | ZX_VM_PERM_WRITE , nullptr , & ring_buffer_vmo_ , ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP | ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER ) ; if ( status != ZX_OK ) { zxlogf ( ERROR , " " , __func__ , status ) ; return status ; } status = ring_buffer_vmo_ . duplicate ( ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP , out_buffer ) ; if ( status != ZX_OK ) { zxlogf ( ERROR , " " , __func__ , status ) ; return status ; } notifications_per_ring_ = req . notifications_per_ring ; if ( notifications_per_ring_ == 0 ) { notification_period_ = zx :: duration ( 0 ) ; } else { notification_period_ = zx :: duration ( ( zx :: sec ( 1 ) * num_ring_buffer_frames_ ) / ( frame_rate_ * notifications_per_ring_ ) ) ; } if ( using_alt_notifications_ ) { if ( alt_notifications_per_ring_ == 0 ) { alt_notification_period_ = zx :: duration ( 0 ) ; } else { alt_notification_period_ = zx :: duration ( ( zx :: sec ( 1 ) * num_ring_buffer_frames_ ) / ( frame_rate_ * alt_notifications_per_ring_ ) ) ; } } * out_num_rb_frames = num_ring_buffer_frames_ ; zx :: vmo duplicate_vmo ; status = ring_buffer_vmo_ . duplicate ( ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP , & duplicate_vmo ) ; if ( status != ZX_OK ) { zxlogf ( ERROR , " " , __func__ , status ) ; return status ; } parent_ -> NotifyBufferCreated ( std :: move ( duplicate_vmo ) , num_ring_buffer_frames_ , notifications_per_ring_ ) ; return ZX_OK ; }
Upon success, drivers should return a valid VMO with appropriate permissions (READ | MAP |
TRANSFER for inputs, WRITE as well for outputs) as well as reporting the total number of usable
frames in the ring.
Upon success drivers should return a valid VMO with appropriate permissions ( READ | MAP | TRANSFER for inputs WRITE as well for outputs ) as well as reporting the total number of usable frames in the ring .