// 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.
@available(added=25)
library fuchsia.hardware.gpio;

using zx;

@available(added=27, removed=28)
const SIGNAL_ACK_INTERRUPT uint32 = 0x01000000; // ZX_USER_SIGNAL_0

/// Whether to drive the GPIO to a high or low voltage, or disable the output buffer.
type BufferMode = strict enum {
    INPUT = 0;
    OUTPUT_LOW = 1;
    OUTPUT_HIGH = 2;
};

type InterruptOptions = flexible bits {
    /// The interrupt wakes up the system if the system is suspended.
    /// Must not be set if system suspend / resume is disabled.
    @available(added=27)
    WAKEABLE = 0x01;

    /// The interrupt returns a monotonic timestamp from synchronous and
    /// asynchronous waits. Otherwise, it returns a boot timestamp from waits.
    @available(added=28)
    TIMESTAMP_MONO = 0x02;
};

type InterruptMode = strict enum {
    EDGE_LOW = 0;
    EDGE_HIGH = 1;
    EDGE_BOTH = 2;
    LEVEL_LOW = 3;
    LEVEL_HIGH = 4;
};

type InterruptConfiguration = table {
    1: mode InterruptMode;
};

/// Common error codes:
/// - `ZX_ERR_NOT_SUPPORTED`: The requested operation is not supported by this controller.
open protocol Gpio {
    /// Reads the current value of a GPIO, returning `true` for a high voltage and `false` for a
    /// low voltage.
    strict Read() -> (struct {
        value bool;
    }) error zx.Status;

    /// Configures the output buffer as per `mode`.
    strict SetBufferMode(struct {
        mode BufferMode;
    }) -> () error zx.Status;

    /// Gets an interrupt object pertaining to a particular GPIO pin. Only one interrupt may
    /// be outstanding per pin, and it must be released by calling `ReleaseInterrupt()` before the
    /// next call to `GetInterrupt()` will succeed.
    ///
    /// Returns `ZX_ERR_ALREADY_EXISTS` if `GetInterrupt()` has already been called without a
    /// subsequent call to `ReleaseInterrupt()`, `ZX_ERR_INVALID_ARGS` if `options` is invalid, or
    /// `ZX_ERR_ACCESS_DENIED` if another client has the interrupt.
    strict GetInterrupt(struct {
        options InterruptOptions;
    }) -> (resource struct {
        interrupt zx.Handle:INTERRUPT;
    }) error zx.Status;

    /// Configures the polarity of an interrupt and whether it is edge- or level-triggered. Only the
    /// client with the interrupt can call `ConfigureInterrupt()`, unless no client has an
    /// interrupt.
    ///
    /// Returns `ZX_ERR_INVALID_ARGS` if no fields are set in `config`, or `ZX_ERR_ACCESS_DENIED` if
    /// another client has the interrupt.
    strict ConfigureInterrupt(struct {
        config InterruptConfiguration;
    }) -> () error zx.Status;

    /// Releases the interrupt, allowing `GetInterrupt()` to be called again or by another
    /// client. A client's interrupt is automatically released when it disconnects from the
    /// server.
    ///
    /// Returns `ZX_ERR_NOT_FOUND` if the interrupt has already been released, or if
    /// `GetInterrupt()` has not been called. Returns `ZX_ERR_ACCESS_DENIED` if another client has
    /// the interrupt.
    strict ReleaseInterrupt() -> () error zx.Status;
};

service Service {
    device client_end:Gpio;
};
