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

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

@for_deprecated_c_bindings
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;
};

@for_deprecated_c_bindings
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;
};

@for_deprecated_c_bindings
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;
};

@for_deprecated_c_bindings
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;
};

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

@for_deprecated_c_bindings
protocol Device {
    /// Resets the device to firmware loader mode.
    SetModeFwloader() -> (struct {
        s zx.status;
    });

    /// Performs a data loopback on the bulk endpoint of the test device.
    /// Returns `ZX_OK` if the loopback succeeded.
    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.
    IsochLoopback(struct {
        params IsochTestParams;
    }) -> (struct {
        s zx.status;
        result IsochResult;
    });

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