// Copyright 2017 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.

#include "platform-proxy.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/clk.h>
#include <ddk/protocol/platform-bus.h>
#include <ddk/protocol/platform-device.h>
#include <ddk/protocol/usb-mode-switch.h>

#include "platform-proxy-device.h"
#include "platform-proxy-host.h"

// The implementation of the platform bus protocol in this file is for use by
// drivers that exist in a proxy devhost and communicate with the platform bus
// over an RPC channel.
//
// More information can be found at the top of platform-device.c.

namespace platform_bus {

zx_status_t PlatformProxy::Rpc(uint32_t device_id, rpc_req_header_t* req, uint32_t req_length,
                               rpc_rsp_header_t* resp, uint32_t resp_length,
                               zx_handle_t* in_handles, uint32_t in_handle_count,
                               zx_handle_t* out_handles, uint32_t out_handle_count,
                               uint32_t* out_actual) {
    uint32_t resp_size, handle_count;

    // We require the client to pass us the device_id and we set here as a precaution
    // against the code above forgetting to set it.
    req->device_id = device_id;

    zx_channel_call_args_t args = {
        .wr_bytes = req,
        .wr_handles = in_handles,
        .rd_bytes = resp,
        .rd_handles = out_handles,
        .wr_num_bytes = req_length,
        .wr_num_handles = in_handle_count,
        .rd_num_bytes = resp_length,
        .rd_num_handles = out_handle_count,
    };
    auto status = rpc_channel_.call(0, zx::time::infinite(), &args, &resp_size, &handle_count);
    if (status != ZX_OK) {
        return status;
    } else if (resp_size < sizeof(*resp)) {
        zxlogf(ERROR, "PlatformProxy::Rpc resp_size too short: %u\n", resp_size);
        status = ZX_ERR_INTERNAL;
        goto fail;
    } else if (handle_count != out_handle_count) {
        zxlogf(ERROR, "PlatformProxy::Rpc handle count %u expected %u\n", handle_count,
               out_handle_count);
        status = ZX_ERR_INTERNAL;
        goto fail;
    }

    status = resp->status;
    if (out_actual) {
        *out_actual = resp_size;
    }

fail:
    if (status != ZX_OK) {
        for (uint32_t i = 0; i < handle_count; i++) {
            zx_handle_close(out_handles[i]);
        }
    }
    return status;
}

zx_status_t PlatformProxy::LoadProtocols(zx_device_t* parent) {
    // Get list of extra protocols to proxy.
    rpc_pdev_req_t req = {};
    struct {
        rpc_pdev_rsp_t pdev;
        uint32_t protocols[PROXY_MAX_PROTOCOLS];
    } resp = {};
    req.header.protocol = ZX_PROTOCOL_PLATFORM_DEV;
    req.header.op = PDEV_GET_PROTOCOLS;

    auto status = Rpc(ROOT_DEVICE_ID, &req.header, sizeof(req), &resp.pdev.header, sizeof(resp));
    if (status != ZX_OK) {
        return status;
    }

    uint32_t protocol_count = resp.pdev.protocol_count;
    for (uint32_t i = 0; i < protocol_count; i++) {
        printf("PROTOCOL %08x\n", resp.protocols[i]);
        status = ProxyHost::Create(resp.protocols[i], parent, fbl::RefPtr<PlatformProxy>(this));
    }

    return ZX_OK;
}

zx_status_t PlatformProxy::Create(zx_device_t* parent, zx_handle_t rpc_channel) {
    fbl::AllocChecker ac;

    auto proxy = fbl::MakeRefCountedChecked<PlatformProxy>(&ac, parent, rpc_channel);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    return ProxyDevice::Create(parent, ROOT_DEVICE_ID, proxy, nullptr);
}

} // namespace platform_bus

zx_status_t platform_proxy_create(void* ctx, zx_device_t* parent, const char* name,
                                  const char* args, zx_handle_t rpc_channel) {
    return platform_bus::PlatformProxy::Create(parent, rpc_channel);
}
