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

/// This interface provides access to factory-only functionality in the ISP driver.
@discoverable
closed 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.
    strict 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).
    strict 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.
    strict SetAWBMode(struct {
        mode WhiteBalanceMode;
        temp uint32;
    }) -> ();

    /// Enables or disables the ISP's Auto Exposure feature.
    ///
    /// + request `mode` An AE mode.
    strict 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
    strict 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
    strict 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
    strict SetTestPatternMode(struct {
        mode uint16;
    }) -> ();

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