// Copyright 2019 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-light.h"

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>

#include <memory>

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

namespace gpio_light {

void GpioLight::GetNumLights(GetNumLightsCompleter::Sync& completer) {
  completer.Reply(gpio_count_);
}

void GpioLight::GetNumLightGroups(GetNumLightGroupsCompleter::Sync& completer) {
  completer.Reply(0);
}

void GpioLight::GetInfo(uint32_t index, GetInfoCompleter::Sync& completer) {
  if (index >= gpio_count_) {
    completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::INVALID_INDEX);
    return;
  }

  char name[20];
  if (names_.size() > 0) {
    snprintf(name, sizeof(name), "%s\n", names_.data() + index * kNameLength);
  } else {
    // Return "gpio-X" if no metadata was provided.
    snprintf(name, sizeof(name), "gpio-%u\n", index);
  }

  completer.ReplySuccess({
      .name = ::fidl::StringView(name, strlen(name)),
      .capability = ::llcpp::fuchsia::hardware::light::Capability::SIMPLE,
  });
}

void GpioLight::GetCurrentSimpleValue(uint32_t index,
                                      GetCurrentSimpleValueCompleter::Sync& completer) {
  if (index >= gpio_count_) {
    completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::INVALID_INDEX);
    return;
  }

  uint8_t value;
  if (gpios_[index].Read(&value) != ZX_OK) {
    completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::FAILED);
  } else {
    completer.ReplySuccess(value);
  }
}

void GpioLight::SetSimpleValue(uint32_t index, bool value,
                               SetSimpleValueCompleter::Sync& completer) {
  if (index >= gpio_count_) {
    completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::INVALID_INDEX);
    return;
  }

  if (gpios_[index].Write(value) != ZX_OK) {
    completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::FAILED);
  } else {
    completer.ReplySuccess();
  }
}

void GpioLight::GetCurrentBrightnessValue(uint32_t index,
                                          GetCurrentBrightnessValueCompleter::Sync& completer) {
  completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::NOT_SUPPORTED);
}

void GpioLight::SetBrightnessValue(uint32_t index, double value,
                                   SetBrightnessValueCompleter::Sync& completer) {
  completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::NOT_SUPPORTED);
}

void GpioLight::GetCurrentRgbValue(uint32_t index, GetCurrentRgbValueCompleter::Sync& completer) {
  completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::NOT_SUPPORTED);
}

void GpioLight::SetRgbValue(uint32_t index, llcpp::fuchsia::hardware::light::Rgb value,
                            SetRgbValueCompleter::Sync& completer) {
  completer.ReplyError(::llcpp::fuchsia::hardware::light::LightError::NOT_SUPPORTED);
}

zx_status_t GpioLight::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  DdkTransaction transaction(txn);
  llcpp::fuchsia::hardware::light::Light::Dispatch(this, msg, &transaction);
  return transaction.Status();
}

void GpioLight::DdkRelease() { delete this; }

zx_status_t GpioLight::Create(void* ctx, zx_device_t* parent) {
  fbl::AllocChecker ac;
  auto dev = std::unique_ptr<GpioLight>(new (&ac) GpioLight(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 GpioLight::Init() {
  ddk::CompositeProtocolClient composite(parent_);
  if (!composite.is_valid()) {
    zxlogf(ERROR, "GpioLight: Could not get composite protocol");
    return ZX_ERR_NOT_SUPPORTED;
  }

  auto fragment_count = composite.GetFragmentCount();
  if (fragment_count <= 0) {
    return ZX_ERR_INTERNAL;
  }
  // fragment 0 is platform device, only used for passing metadata.
  gpio_count_ = fragment_count - 1;

  size_t metadata_size;
  size_t expected = gpio_count_ * kNameLength;
  auto status = device_get_metadata_size(parent(), DEVICE_METADATA_NAME, &metadata_size);
  if (status == ZX_OK) {
    if (expected != metadata_size) {
      zxlogf(ERROR, "%s: expected metadata size %zu, got %zu", __func__, expected, metadata_size);
      status = ZX_ERR_INTERNAL;
    }
  }
  if (status == ZX_OK) {
    fbl::AllocChecker ac;
    names_.reset(new (&ac) char[metadata_size], metadata_size);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }

    status = device_get_metadata(parent(), DEVICE_METADATA_NAME, names_.data(), metadata_size,
                                 &expected);
    if (status != ZX_OK) {
      return status;
    }
  }

  composite_device_fragment_t fragments[fragment_count];
  size_t actual;
  composite.GetFragmentsNew(fragments, fragment_count, &actual);
  if (actual != fragment_count) {
    return ZX_ERR_INTERNAL;
  }

  fbl::AllocChecker ac;
  auto* gpios = new (&ac) ddk::GpioProtocolClient[gpio_count_];
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  gpios_.reset(gpios, gpio_count_);

  for (uint32_t i = 0; i < gpio_count_; i++) {
    auto* gpio = &gpios_[i];
    auto status = device_get_protocol(fragments[i + 1].device, ZX_PROTOCOL_GPIO, gpio);
    if (status != ZX_OK) {
      return status;
    }
    status = gpio->ConfigOut(0);
    if (status != ZX_OK) {
      zxlogf(ERROR, "gpio-light: ConfigOut failed for gpio %u", i);
      return status;
    }
  }

  return DdkAdd("gpio-light", DEVICE_ADD_NON_BINDABLE);
}

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

}  // namespace gpio_light

ZIRCON_DRIVER_BEGIN(gpio_light, gpio_light::driver_ops, "zircon", "0.1", 4)
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
    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_LIGHT), ZIRCON_DRIVER_END(gpio_light)
