// Copyright 2018 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.hardware.usb.tester;

using zx;

const MAX_SG_SEGMENTS uint32 = 256;
const MAX_PACKETS uint64 = 256;

type DataPatternType = strict enum : uint8 {
    CONSTANT = 1;
    RANDOM = 2;
};

type BulkTestParams = struct {
    /// The type of data to transfer.
    data_pattern DataPatternType;
    /// Total number of bytes to transfer.
    len uint64;
};

type PacketOptions = struct {
    /// Whether to request a callback for the transfer.
    set_cb bool;
    /// Whether we want the transfer to fail with an error.
    set_error bool;
    /// Whether to expect a callback for the transfer.
    expect_cb bool;
};

type IsochTestParams = struct {
    /// The type of data to transfer.
    data_pattern DataPatternType;
    /// The number of packets to send.
    num_packets uint64;
    /// Number of bytes in each packet.
    packet_size uint16;

    /// Optional array of additional options for the OUT packets.
    // TODO(jocelyndang): A vector would break the current requirement for a simple C binding.
    packet_opts array<PacketOptions, MAX_PACKETS>;
    /// Number of entries in `packet_opts`. This can be less than `num_packets`,
    /// in which case defaults will be chosen for the remaining packets.
    /// Any entries provided after `num_packets` will be ignored.
    packet_opts_len uint64;
};

type SgEntry = struct {
    /// Number of bytes in the scatter gather entry.
    length uint64;
    /// Offset in bytes from the start of the data buffer.
    offset uint64;
};

type SgList = struct {
    // A vector would break the current requirement for a simple C binding.
    entries array<SgEntry, MAX_SG_SEGMENTS>;
    /// Number of entries in the scatter gather list.
    len uint64;
};

type IsochResult = struct {
    /// Number of packets loopbacked successfully.
    num_passed uint64;
    /// Number of packets transferred to each EP.
    num_packets uint64;
};

closed protocol Device {
    /// Resets the device to firmware loader mode.
    strict SetModeFwloader() -> (struct {
        s zx.Status;
    });

    /// Performs a data loopback on the bulk endpoint of the test device.
    /// Returns `ZX_OK` if the loopback succeeded.
    strict BulkLoopback(struct {
        params BulkTestParams;
        out_ep_sg box<SgList>;
        in_ep_sg box<SgList>;
    }) -> (struct {
        s zx.Status;
    });

    /// Performs a data loopback on the isochronous endpoint of the test device.
    /// Returns `ZX_OK` if no fatal error occurred during the loopback, and also returns the result
    /// of the transfers. Isochronous transfers are not guaranteed to all succeed.
    strict IsochLoopback(struct {
        params IsochTestParams;
    }) -> (struct {
        s zx.Status;
        result IsochResult;
    });

    /// Returns the test firmware version in the form major_version.minor_version.
    strict GetVersion() -> (struct {
        major_version uint8;
        minor_version uint8;
    });
};
