// 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 "gpio-test.h"

#include <memory>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/platform-defs.h>
#include <ddktl/protocol/platform/device.h>
#include <fbl/alloc_checker.h>

namespace gpio_test {

void GpioTest::DdkRelease() {
    done_ = true;
    thrd_join(output_thread_, nullptr);
    thrd_join(interrupt_thread_, nullptr);
    gpios_[GPIO_BUTTON].ReleaseInterrupt();

    delete this;
}

// test thread that cycles all of the GPIOs provided to us
int GpioTest::OutputThread() {
    for (uint32_t i = 0; i < gpio_count_ - 1; i++) {
        if (gpios_[i].ConfigOut(0) != ZX_OK) {
            zxlogf(ERROR, "gpio-test: ConfigOut failed for gpio %u\n", i);
            return -1;
        }
    }

    while (!done_) {
        // Assuming here that the last GPIO is the input button
        // so we don't toggle that one
        for (uint32_t i = 0; i < gpio_count_ - 1; i++) {
            gpios_[i].Write(1);
            sleep(1);
            gpios_[i].Write(0);
            sleep(1);
        }
    }

    return 0;
}

// test thread that cycles runs tests for GPIO interrupts
int GpioTest::InterruptThread() {
    if (gpios_[GPIO_BUTTON].ConfigIn(GPIO_PULL_DOWN) != ZX_OK) {
        zxlogf(ERROR, "%s: gpio_config failed for gpio %u \n", __func__, GPIO_BUTTON);
        return -1;
    }

    if (gpios_[GPIO_BUTTON].GetInterrupt(ZX_INTERRUPT_MODE_EDGE_HIGH, &interrupt_) != ZX_OK) {
        zxlogf(ERROR, "%s: gpio_get_interrupt failed for gpio %u\n", __func__, GPIO_BUTTON);
        return -1;
    }

    while (!done_) {
        zxlogf(INFO, "Waiting for GPIO Test Input Interrupt\n");
        auto status = interrupt_.wait(nullptr);
        if (status != ZX_OK) {
            zxlogf(ERROR, "%s: interrupt wait failed %d\n", __func__, status);
            return -1;
        }
        zxlogf(INFO, "Received GPIO Test Input Interrupt\n");
        uint8_t out;
        gpios_[GPIO_LED].Read(&out);
        gpios_[GPIO_LED].Write(!out);
        sleep(1);
    }

    return 0;
}

zx_status_t GpioTest::Create(void* ctx, zx_device_t* parent) {
    fbl::AllocChecker ac;
    auto dev = std::unique_ptr<GpioTest>(new (&ac) GpioTest(parent));
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    auto status = dev->Init();
    if (status != ZX_OK) {
        return status;
    }

    // devmgr is now in charge of the device.
    __UNUSED auto* dummy = dev.release();
    return ZX_OK;
}

zx_status_t GpioTest::Init() {
    ddk::PDevProtocolClient pdev(parent());
    if (!pdev.is_valid()) {
        return ZX_ERR_NOT_SUPPORTED;
    }

    pdev_device_info_t  info;
    if (pdev.GetDeviceInfo(&info) != ZX_OK) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    gpio_count_ = info.gpio_count;

    fbl::AllocChecker ac;
    gpios_ = fbl::Array(new (&ac) ddk::GpioProtocolClient[info.gpio_count], info.gpio_count);
    if (!ac.check()) {
        return ZX_ERR_NO_MEMORY;
    }

    for (uint32_t i = 0; i < info.gpio_count; i++) {
        auto* gpio = &gpios_[i];
        size_t actual;
        auto status = pdev.GetProtocol(ZX_PROTOCOL_GPIO, i, gpio, sizeof(*gpio), &actual);
        if (status != ZX_OK) {
            return status;
        }
    }

    auto status = DdkAdd("gpio-test", DEVICE_ADD_NON_BINDABLE);
    if (status != ZX_OK) {
        return status;
    }

    thrd_create_with_name(&output_thread_,
                          [](void* arg) -> int {
                               return reinterpret_cast<GpioTest*>(arg)->OutputThread();
                          },
                          this, "gpio-test output");
    thrd_create_with_name(&interrupt_thread_,
                          [](void* arg) -> int {
                               return reinterpret_cast<GpioTest*>(arg)->InterruptThread();
                          },
                          this, "gpio-test interrupt");

    return ZX_OK;
}

static zx_driver_ops_t driver_ops = [](){
    zx_driver_ops_t ops;
    ops.version = DRIVER_OPS_VERSION;
    ops.bind = GpioTest::Create;
    return ops;
}();

} // namespace gpio_test

ZIRCON_DRIVER_BEGIN(gpio_test, gpio_test::driver_ops, "zircon", "0.1", 4)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_GPIO_TEST),
ZIRCON_DRIVER_END(gpio_test)
