#include <stddef.h>

#include "driver_ipc.h"
#include "platform_driver_api.h"
#include "driver_log.h"

#include "qsee_env.h"
#include "object.h"
#include "serialize.h"

static const void *g_in_buffer = NULL;
static size_t g_in_buffer_size = 0;

static void *g_out_buffer = NULL;
static size_t g_out_buffer_size = 0;

PaTzResult PlatformCallDriver(uint32_t id_driver, uint32_t ioctl_cmd,
                              void *params, uint32_t size_params) {
  Object o;
  PaTzResult result = PA_TZ_GENERAL_ERROR;

  do {
    int32_t err = qsee_open(DRIVER_ID, &o);
    if (err) {
      LOG_E("qsee_open() failed.\n");
      LOG_D("Received error: %d.", err);
      break;
    }

    ObjectArg args[5];
    DrvClientBuffers client_buffers = {(DrvClientAddress)g_in_buffer,
				       (DrvClientAddress)g_out_buffer};

    args[0].bi = (ObjectBufIn){params, size_params};
    args[1].bi = (ObjectBufIn){g_in_buffer, g_in_buffer_size};
    args[2].bi = (ObjectBufIn){&client_buffers, sizeof(client_buffers)};
    args[3].b = (ObjectBuf){params, kSerializedDataMaxSize};
    args[4].b = (ObjectBuf){g_out_buffer, g_out_buffer_size};


    err = Object_invoke(o, 0, args, ObjectCounts_pack(3, 2, 0, 0));
    if (!Object_isOK(err)) {
      LOG_E("Object_invoke() is failed.\n");
      LOG_D("Received error: %d.", err);
      break;
    }

    g_in_buffer = g_out_buffer = NULL;
    g_in_buffer_size = g_out_buffer_size = 0;

    result = PA_TZ_SUCCESS;
  } while (0);

  if (!Object_isNull(o)) {
    Object_invoke(o, Object_OP_release, 0, 0);
  }

  return result;
}

void PlatformRegisterTrustletOutputBuffer(void *data, size_t size) {
  g_out_buffer = data;
  g_out_buffer_size = size;
}

void PlatformRegisterTrustletInputBuffer(const void *data, size_t size) {
  g_in_buffer = data;
  g_in_buffer_size = size;
}
