// Copyright 2018 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.

library fuchsia.virtualization.hardware;

using fuchsia.io;
using fuchsia.ui.gfx;
using fuchsia.ui.input;
using fuchsia.virtualization;
using fuchsia.hardware.ethernet;
using fuchsia.scenic.allocation;
using fuchsia.sysmem;
using zx;

// The following EVENT_* constants indicate which user signal is associated with an event.
// The value 0 is `ZX_USER_SIGNAL_0`, 1 is `ZX_USER_SIGNAL_1` etc.

/// Set a flag to inspect queues on the next interrupt.
const uint32 EVENT_SET_QUEUE = 0;
/// Set a flag to inspect configs on the next interrupt.
const uint32 EVENT_SET_CONFIG = 1;
/// If a flag is set, send an interrupt to the device.
const uint32 EVENT_SET_INTERRUPT = 2;

/// Contains the details of a device trap.
struct Trap {
    /// The address of the device trap. This must be page-aligned.
    zx.gpaddr addr;

    /// The size of the device trap. This must be a multiple of the page size.
    uint64 size;
};

/// Contains the basic information required to start execution of a device.
resource struct StartInfo {
    /// The trap associated with a device. It is up to the device to set this
    /// trap during device setup.
    Trap trap;

    /// The guest associated with a device. This handle should be used to setup
    /// device traps, and then be released before device operation begins.
    zx.handle:GUEST? guest;

    /// The event associated with a device interrupt. This is how the device will
    /// notify the guest of events it should process.
    ///
    /// The meaning of the different signals that can be raised on the event are
    /// documented by the EVENT_* constants above.
    zx.handle:EVENT event;

    /// The VMO used to represent guest physical memory.
    zx.handle:VMO vmo;
};

protocol VirtioDevice {
    /// Configure a `queue` for the device. This specifies the `size` and the
    /// guest physical addresses of the queue: `desc`, `avail`, and `used`.
    ConfigureQueue(uint16 queue, uint16 size, zx.gpaddr desc, zx.gpaddr avail,
                   zx.gpaddr used) -> ();

    /// Notify a `queue` for the device. Primarily used for black-box testing.
    NotifyQueue(uint16 queue);

    /// Ready a device. This provides the set of `negotiated_features` that the
    /// driver and device have agreed upon.
    Ready(uint32 negotiated_features) -> ();
};

[Discoverable]
protocol VirtioBalloon {
    compose VirtioDevice;

    /// Start the balloon device.
    Start(StartInfo start_info) -> ();

    /// Get memory statistics from the balloon device.
    GetMemStats() -> (zx.status status,
                      vector<fuchsia.virtualization.MemStat>? mem_stats);
};

[Discoverable]
protocol VirtioBlock {
    compose VirtioDevice;

    /// Start the block device.
    Start(StartInfo start_info,
          string:fuchsia.virtualization.MAX_BLOCK_DEVICE_ID id,
          fuchsia.virtualization.BlockMode mode, fuchsia.virtualization.BlockFormat format,
          fuchsia.io.File file) -> (uint64 size);
};

[Discoverable]
protocol VirtioConsole {
    compose VirtioDevice;

    /// Start the console device. This uses `socket` to handle input and output.
    Start(StartInfo start_info, zx.handle:SOCKET socket) -> ();
};

/// Provides a way for VirtioInput to listen to keyboard events.
[Discoverable]
protocol KeyboardListener {
    /// Called when a view receives keyboard events.
    OnKeyboardEvent(fuchsia.ui.input.KeyboardEvent event);
};

/// Provides a way for VirtioInput to listen to pointer events.
[Discoverable]
protocol PointerListener {
    /// Called when a view's size changes.
    OnSizeChanged(fuchsia.ui.gfx.vec3 size);

    /// Called when a view receives pointer events.
    OnPointerEvent(fuchsia.ui.input.PointerEvent event);
};

[Discoverable]
protocol VirtioGpu {
    compose VirtioDevice;

    /// Start the GPU device.
    Start(StartInfo start_info, KeyboardListener? keyboard_listener,
          PointerListener? pointer_listener) -> ();

    /// Called when a device's configuration is changed.
    -> OnConfigChanged();
};

[Discoverable]
protocol VirtioInput {
    compose VirtioDevice;

    /// Start the input device.
    Start(StartInfo start_info) -> ();
};

[Discoverable]
protocol VirtioMagma {
    compose VirtioDevice;

    /// Start the magma device.
    Start(StartInfo start_info,
          zx.handle:VMAR vmar,
          VirtioWaylandImporter? wayland_importer) -> (zx.status status);
};

[Discoverable]
protocol VirtioNet {
    compose VirtioDevice;

    /// Start the net device.
    Start(StartInfo start_info, fuchsia.hardware.ethernet.MacAddress mac_address,
          bool enable_bridge) -> ();
};

[Discoverable]
protocol VirtioRng {
    compose VirtioDevice;

    /// Start the RNG device.
    Start(StartInfo start_info) -> ();
};

/// Sufficient to contain the opaque image info.
const uint32 VIRTIO_WAYLAND_MAX_IMAGE_INFO_SIZE = 128;

/// VirtioImages are shared with VirtioMagma, enabling guest clients to allocate
/// GBM and Vulkan compatible images and share them with Sommelier as dma-bufs.
/// An image corresponds to a single buffer collection, and also contains some
/// opaque image info needed by VirtioMagma.
resource struct VirtioImage {
    zx.handle:VMO vmo;
    zx.handle:EVENTPAIR? token;
    bytes:VIRTIO_WAYLAND_MAX_IMAGE_INFO_SIZE info;
};

const uint32 VIRTIO_WAYLAND_INVALID_VFD_ID = 0;

// Provides an interface to import images into the wayland device.
protocol VirtioWaylandImporter {
    ImportImage(VirtioImage image) -> (uint32 vfd_id);
    ExportImage(uint32 vfd_id) -> (zx.status status, VirtioImage? image);
};

[Discoverable]
protocol VirtioWayland {
    compose VirtioDevice;

    /// Start the wayland device.
    Start(StartInfo start_info,
          zx.handle:VMAR vmar,
          fuchsia.virtualization.WaylandDispatcher dispatcher,
          fuchsia.sysmem.Allocator sysmem_allocator,
          fuchsia.scenic.allocation.Allocator scenic_allocator) -> ();

    // Get the VMO importer for this wayland device.
    GetImporter(request<VirtioWaylandImporter> importer);
};
