// 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;

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

type ExposureMode = strict enum : 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(struct {
        enabled bool;
    });

    /// 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(struct {
        dir_path string;
    }) -> (struct {
        s zx.status;
        image_info fuchsia.images.ImageInfo;
    });

    /// 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(struct {
        stream_index uint32;
    }) -> (struct {
        s zx.status;
    });
};

/// 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() -> (resource struct {
        s zx.status;
        byte_count uint64;
        otp_data zx.handle:VMO;
    });

    /// 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() -> (struct {
        s zx.status;
        temp int32;
    });

    // 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(struct {
        mode WhiteBalanceMode;
        temp uint32;
    }) -> ();

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

    /// 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(struct {
        integration_time float32;
        analog_gain float32;
        digital_gain float32;
    }) -> ();

    /// 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(struct {
        mode uint32;
    }) -> ();

    /// 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(struct {
        mode uint16;
    }) -> ();

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