// Copyright 2020 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.factory.camera;

using fuchsia.images;
using zx;

enum WhiteBalanceMode : uint8 {
    AUTO = 0;
    MANUAL = 1;
};

enum ExposureMode : uint8 {
    AUTO = 0;
    FULL_MANUAL = 1;
    MANUAL_GAIN = 2;
    MANUAL_EXPOSURE_TIME = 3;
};

/// This interface provides access to factory-only functionality in the ISP driver.
[Discoverable]
protocol Controller {
    /// Instructs the controller to switch its stream format based on the ISP's output.
    /// + request `on` The ISP's streaming mode:
    ///                 `True` 16-bit portable grey map format.
    ///                 `False` 10-bit RGB format.
    IsIspBypassModeEnabled(bool enabled);

    /// Instructs the device to capture a frame from the stream, and write it to disk.
    ///
    /// + request `amount` The number of frames to capture.
    /// + request `dir_path` Specifies where to write the captured frames.
    /// - response `s` The operation's status code:
    ///                 `ZX_OK` if the operation succeeded.
    ///                 `ZX_ERR_UNAVAILABLE` if there are no active streams to capture from.
    ///                 `ZX_ERR_NOT_DIR` if the specified `dir_path` does not exist or is
    ///                                  not a directory.
    /// - response `image_info` A struct outlining the image's properties, e.g.
    ///                         width/height, pixel format, etc.
    CaptureFrames(string dir_path)
        -> (zx.status s, fuchsia.images.ImageInfo image_info);

    /// Displays a single stream the DUT's screen.
    ///
    /// + request `stream_index` The index of the stream in the DUT's
    ///                          `fuchsia.camera3.Device.Configuration` vector.
    /// - response `s` The operation's status code:
    ///                 `ZX_OK` if the operation succeeded.
    ///                 `ZX_ERR_UNAVAILABLE` if there are no active streams to display from.
    ///                 `ZX_ERR_NOT_SUPPORTED` if the DUT does not have a screen.
    DisplayToScreen(uint32 stream_index) -> (zx.status s);
};

/// This interface provides access to factory-only functionality in the ISP driver.
[Discoverable]
protocol Isp {
    // Getters

    /// Retrieves the data stored in the camera module's One-Time Programmable Memory.
    ///
    /// - response `s` The operation's status code:
    ///                 `ZX_OK` if the operation succeeded.
    ///                 `ZX_ERR_IO` if the camera module is not initialized or is otherwise
    ///                             unavailable.
    ///                 `ZX_ERR_NOT_SUPPORTED` if the camera module does not have an OTP.
    /// - response `otp_data` A handle to a VMO containing the requested OTP data.
    GetOtpData() -> (zx.status s, uint64 byte_count, zx.handle:VMO otp_data);

    /// Retrieves the sensor's temperature.
    ///
    /// - response `s` The operation's status code:
    ///                 `ZX_OK` if the operation succeeded.
    ///                 `ZX_ERR_IO` if the sensor is not initialized or is otherwise unavailable.
    ///                 `ZX_ERR_NOT_SUPPORTED` if the sensor does not support this feature.
    /// - response `temp` The sensor's operating temperature (in degrees Celsius).
    GetSensorTemperature() -> (zx.status s, int32 temp);

    // Setters

    /// Enables or disables the ISP's Auto White Balance (AWB) feature.
    ///
    /// + request `mode` An AWB mode.
    /// + request `temp` The white balance temperature to use (in degrees Kelvin).
    ///                  Has no effect if the mode is not set to MANUAL.
    SetAWBMode(WhiteBalanceMode mode, uint32 temp) -> ();

    /// Enables or disables the ISP's Auto Exposure feature.
    ///
    /// + request `mode` An AE mode.
    SetAEMode(ExposureMode mode) -> ();

    /// Sets the parameters for the sensor's manual exposure settings.
    ///
    /// + request `integration_time` The sensor's integration time parameter.
    ///                              Has no effect if the AE mode is not set to FULL_MANUAL or
    ///                              MANUAL_EXPOSURE_TIME.
    /// + request `analog_gain` The sensor's analog gain parameter.
    ///                         Has no effect if the AE mode is not set to FULL_MANUAL or
    ///                         MANUAL_GAIN.
    /// + request `digital_gain` The sensor's digital gain parameter.
    ///                          Has no effect if the AE mode is not set to FULL_MANUAL or
    ///                          MANUAL_GAIN.
    ///
    /// * See [`camera-sensor.banjo`] for more information on these params:
    ///     //sdk/banjo/fuchsia.hardware.camera.sensor/camera-sensor.banjo
    SetExposure(float32 integration_time, float32 analog_gain, float32 digital_gain)
        -> ();

    /// Selects the sensor mode.
    ///
    /// + request `mode` The index of one of the predefined sensor modes (fps, resolution,
    ///                  etc).
    ///
    /// * See [`camera-sensor.banjo`] for more information on this param:
    ///     //sdk/banjo/fuchsia.hardware.camera.sensor/camera-sensor.banjo
    SetSensorMode(uint32 mode) -> ();

    /// Selects the sensor test pattern mode.
    ///
    /// + request `mode` One of the predefined sensor test pattern modes.
    ///
    /// * See [`camera-sensor.banjo`] for more information on this param:
    ///     //sdk/banjo/fuchsia.hardware.camera.sensor/camera-sensor.banjo
    SetTestPatternMode(uint16 mode) -> ();

    /// Sets the bypass mode.
    ///
    /// + request `on` True to enable 19:4 (16-bit) bypass mode, outputting raw sensor bits
    SetBypassMode(bool on) -> ();
};
