// Copyright 2023 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.
@available(added=18)
library fuchsia.hardware.trippoint;

using fuchsia.hardware.temperature;
using zx;

@available(added=18)
type TripDeviceMetadata = struct {
    /// Critical temperature in degrees Celsius.
    critical_temp_celsius float32;
};

/// Denotes the type of a particular trip point.
@available(added=18)
type TripPointType = flexible enum : uint16 {
    /// This type of trip point is denoted by a critical temperature at which
    /// the trip point triggers and a direction. Once the trip point fires it is
    /// no longer configured and must be rearmed before it can fire again.
    ONESHOT_TEMP_ABOVE = 1;
    ONESHOT_TEMP_BELOW = 2;
};

/// A union that defines all the possible types of trip points.
@available(added=18)
type TripPointValue = flexible union {
    /// This is a special reserved type of trip point that can be used by
    /// clients to clear previously configured trip point.
    1: cleared_trip_point ClearedTripPoint;

    2: oneshot_temp_above_trip_point OneshotTempAboveTripPoint;
    3: oneshot_temp_below_trip_point OneshotTempBelowTripPoint;
};

@available(added=18)
type TripPointResult = struct {
    /// The temperature measured by the sensor. NaN if a measurement was not
    /// performed.
    measured_temperature_celsius float32;

    /// The index of the trip point that was configured.
    index uint32;
};


// A special reserved type used to clear configured trip points.
@available(added=18)
type ClearedTripPoint = struct {};

/// See the comment in TripPointType for more information.
@available(added=18)
type OneshotTempAboveTripPoint = struct {
    /// The temperature at which the trip point activates.
    critical_temperature_celsius float32;
};

@available(added=18)
type OneshotTempBelowTripPoint = struct {
    /// The temperature at which the trip point activates.
    critical_temperature_celsius float32;
};


@available(added=18)
type TripPointDescriptor = struct {
    /// The type of this trip point as defined by the hardware.
    type TripPointType;

    /// The index of the trip point being configured. Trip points are always
    /// numbered 0 to N-1 where N is the number of available hardware trip
    /// points.
    index uint32;

    /// If unset the type of this configuration will be `cleared_trip_point`
    /// otherwise it will be a TripPointValue that corresponds to the type
    /// defined by `type`.
    configuration TripPointValue;
};

/// The server should enforce that only one client may be connected and
/// configuring trip points at any given time.
/// If a second client attempts to configure trip points while a client is
/// already connected, the server should return ZX_ERR_ALREADY_BOUND to indicate
/// that it is busy.
/// The server _may_ allow multiple clients to access the
//// fuchsia.hardware.temperature protocol.
@available(added=18)
open protocol TripPoint {
    /// Returns N descriptors. Each descriptor describes one trip point
    /// supported by the hardware.
    flexible GetTripPointDescriptors() -> (struct {
        descriptors vector<TripPointDescriptor>:MAX;
    }) error zx.Status;

    /// Configure 0 or more hardware trip points.
    flexible SetTripPoints(struct {
        /// The type of this configuration must correspond to the type of the
        /// trip point returned by GetTripPointDescriptors. The type of the
        /// configuration field must either be `ClearedTripPoint` if the trip
        /// point is being cleared or it must correspond to the type defined by
        /// `GetTripPointDescriptors`. If these arguments do not match
        /// `ZX_ERR_INVALID_ARGS` is returned.
        /// If the index field is larger than the number of descriptors returned
        /// by GetTripPointDescriptors then `ZX_ERR_OUT_OF_RANGE` is returned.
        /// Configuring a trip point that is already configured will cause the
        /// previous configuration to be overwritten and any pending trip
        /// interrupts to be cleared.
        descriptors vector<TripPointDescriptor>:MAX;
    }) -> () error zx.Status;

    /// Hanging get API that returns when any configured trip point has been
    /// crossed.
    /// Returns ZX_ERR_BAD_STATE if no trip points have been configured or if
    /// all configured trip points are cleared by a call to SetTripPoints.
    flexible WaitForAnyTripPoint() -> (struct {
        result TripPointResult;
    }) error zx.Status;

    compose fuchsia.hardware.temperature.Device;
};

service TripPointService {
    trippoint client_end:TripPoint;
};
