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

#include "driver_ctx.h"

#include "amlogic-video.h"
#include "macros.h"

#include <ddk/driver.h>

#include <stdarg.h>
#include <stdio.h>

#include "tests/test_support.h"

namespace {

extern "C" {
zx_status_t amlogic_video_init(void** out_ctx);
zx_status_t amlogic_video_bind(void* ctx, zx_device_t* parent);
}

extern zx_status_t amlogic_video_init(void** out_ctx) {
  DriverCtx* driver_ctx = new DriverCtx();
  *out_ctx = reinterpret_cast<void*>(driver_ctx);
  return ZX_OK;
}

// ctx is the driver ctx (not device ctx)
zx_status_t amlogic_video_bind(void* ctx, zx_device_t* parent) {
  // These calls don't do anything on a production build.
  TestSupport::set_parent_device(parent);
  TestSupport::RunAllTests();

  DriverCtx* driver = reinterpret_cast<DriverCtx*>(ctx);
  std::unique_ptr<DeviceCtx> device = std::make_unique<DeviceCtx>(driver);

  AmlogicVideo* video = device->video();

  zx_status_t status = video->InitRegisters(parent);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed to initialize registers");
    return status;
  }

  status = video->InitDecoder();
  if (status != ZX_OK) {
    DECODE_ERROR("Failed to initialize decoder");
    return status;
  }

  status = device->Bind(parent);
  if (status != ZX_OK) {
    DECODE_ERROR("Failed to bind device");
    return status;
  }

  // The pointer to DeviceCtx is add_device() ctx now, so intentionally don't
  // destruct the DeviceCtx instance.
  //
  // At least for now, the DeviceCtx stays allocated for the life of the
  // devhost process.
  device.release();
  zxlogf(INFO, "[amlogic_video_bind] bound\n");
  return ZX_OK;
}

}  // namespace

DriverCtx::DriverCtx() {
  // We use kAsyncLoopConfigNoAttachToThread here, because we don't really want
  // to be setting the default async_t for the thread that creates the
  // DriverCtx.  We'll plumb async_t(s) explicitly instead.
  shared_fidl_loop_ =
      std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToThread);
  shared_fidl_loop_->StartThread("shared_fidl_thread", &shared_fidl_thread_);
}

DriverCtx::~DriverCtx() {
  assert(shared_fidl_loop_);
  shared_fidl_loop_->Quit();
  shared_fidl_loop_->JoinThreads();
  shared_fidl_loop_->Shutdown();
}

// TODO(dustingreen): Do format, printf, log, maybe some epitaphs.
void DriverCtx::FatalError(const char* format, ...) {
  // Let's not have a buffer on the stack, not because it couldn't be done
  // safely, but because we'd potentially run into stack size vs. message length
  // tradeoffs, stack expansion granularity fun, or whatever else.

  va_list args;
  va_start(args, format);
  size_t buffer_bytes = vsnprintf(nullptr, 0, format, args) + 1;
  va_end(args);

  // ~buffer never actually runs since this method never returns
  std::unique_ptr<char[]> buffer(new char[buffer_bytes]);

  va_start(args, format);
  size_t buffer_bytes_2 =
      vsnprintf(buffer.get(), buffer_bytes, format, args) + 1;
  (void)buffer_bytes_2;
  // sanity check; should match so go ahead and assert that it does.
  assert(buffer_bytes == buffer_bytes_2);
  va_end(args);

  DECODE_ERROR("DriverCtx::FatalError(): %s\n", buffer.get());

  // TODO(dustingreen): Send string in buffer via channel epitaphs, when
  // possible. The channel activity/failing server-side generally will race with
  // trying to send epitaph - probably requires enlisting shared_fidl_thread()
  // from here - probably a timeout here would be a good idea if so.

  // This should provide more stack dump than exit(-1) would give.
  ZX_ASSERT_MSG(false, "DriverCtx::FatalError() is fatal.");
}

// Run to_run on given dispatcher, in order.
void DriverCtx::PostSerial(async_dispatcher_t* dispatcher,
                           fit::closure to_run) {
  zx_status_t post_result = async::PostTask(dispatcher, std::move(to_run));
  if (post_result != ZX_OK) {
    FatalError("async::PostTask() failed - result: %d", post_result);
  }
}

// Run to_run_on_shared_fidl_thread on shared_fidl_thread().
void DriverCtx::PostToSharedFidl(fit::closure to_run_on_shared_fidl_thread) {
  // Switch the implementation here to fit::function when possible.
  PostSerial(shared_fidl_loop()->dispatcher(),
             std::move(to_run_on_shared_fidl_thread));
}
