/*
 * Test   : %test_id%
 * Responsible : Samsung
 * HW depended : N
 * Dep reason : Sample code of Loadable driver
 * Level 1 : Secure Kernel
 * Level 2 : Drivers
 * Level 3 : Client
 * Client : tee_test_driver_client
 * TA     : test_TA_driver_client (11111111-0000-0000-636c-69656e747461)
 * TA     : test_TA_driver (11111111-0000-0000-6472-697665727461)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <tee_client_api.h>


TEEC_UUID uuid_client = {
    .timeLow = 0x11111111,
    .timeMid = 0,
    .timeHiAndVersion = 0,
    .clockSeqAndNode = {0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x74, 0x61},
};

TEEC_UUID uuid_driver = {
    .timeLow = 0x11111111,
    .timeMid = 0,
    .timeHiAndVersion = 0,
    .clockSeqAndNode = {0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x74, 0x61},
};

#ifdef DEBUG
#define INFO(fmt, ...) do { printf(fmt, ##__VA_ARGS__); } while(0)
#else
#define INFO(fmt, ...)
#endif
#define ERR(fmt, ...)  do { printf(fmt, ##__VA_ARGS__); } while(0)

enum cmd_drv_client
{
    CMD_OPEN,
    CMD_CLOSE,
    CMD_READ,
    CMD_WRITE,
    CMD_IOCTL,
    CMD_MAX
};

static TEEC_Result tee_test(TEEC_Context *context)
{
    TEEC_Result res;
    TEEC_Operation operation;
    TEEC_Session session_driver;
    TEEC_Session session;
    uint32_t returnOrigin;

    operation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);

    /* Call driver */
    INFO("TEEC_OpenSession (driver)\n");
    res = TEEC_OpenSession(context, &session_driver, &uuid_driver, 0, NULL, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
        ERR("res = 0x%x\n", res);
        return res;
    }

    /* Open test application */
    INFO("TEEC_OpenSession (client)\n");
    res = TEEC_OpenSession(context, &session, &uuid_client, 0, NULL, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
        ERR("res = 0x%x\n", res);
        TEEC_CloseSession(&session_driver);
        return res;
    }

    /* OPEN */
    INFO("TEEC_InvokeCommand: CMD_OPEN\n");
    res = TEEC_InvokeCommand(&session, CMD_OPEN, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
        goto exit;
    }

    /* READ */
    INFO("TEEC_InvokeCommand: CMD_READ\n");
    res = TEEC_InvokeCommand(&session, CMD_READ, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
         goto exit;
    }

    /* WRITE */
    INFO("TEEC_InvokeCommand: CMD_WRITE\n");
    res = TEEC_InvokeCommand(&session, CMD_WRITE, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
        goto exit;
    }

    /* IOCTL */
    INFO("TEEC_InvokeCommand: CMD_IOCTL\n");
    res = TEEC_InvokeCommand(&session, CMD_IOCTL, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
         goto exit;
    }

    /* CLOSE */
    INFO("TEEC_InvokeCommand: CMD_CLOSE\n");
    res = TEEC_InvokeCommand(&session, CMD_CLOSE, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
         goto exit;
    }
exit:
    INFO("TEEC_CloseSession (client)\n");
    TEEC_CloseSession(&session);
    INFO("TEEC_CloseSession (driver)\n");
    TEEC_CloseSession(&session_driver);
    INFO("res = 0x%x\n", res);
    return res;
}

int main(void)
{
    TEEC_Context context;
    TEEC_Result res = -1;

    INFO("TEEC_InitializeContext\n");
    res = TEEC_InitializeContext(NULL, &context);
    if (res != TEEC_SUCCESS) {
        ERR("InitializeContext failed, res = 0x%x\n", res);
        return res;
    }

    res = tee_test(&context);

    INFO("TEEC_FinalizeContext\n");
    TEEC_FinalizeContext(&context);

    return (res != TEEC_SUCCESS);
}
