/*
 * Copyright (C) 2020, Samsung Electronics Co., Ltd.
 *
 * TUI LL device driver definitions header
 * This copy is for SWD TUI LL components and
 * for NWD and SWD test components
 *
 *
 * There are two other copies of this file in
 * /TuiService/tui_service_jni/jni/tuill_defs.h and
 * /secure-kernel/linux/tui/tuill_defs.h
 */

#pragma once

#ifdef __SECUREOS__
#include <atomic.h>
#endif /* __SECUREOS__ */
#include <pthread.h>
#include <stdbool.h>
#include <sys/epoll.h>
#include <sys/un.h>
#include <tz_cred.h>

#define OS_SWD_SOCKET_NAME  "tuill_swd_server"
#define OS_IWD_SOCKET_NAME  "tuill_iwd_server"
#define TOUCH_DRIVER_NAME   "tuill_touchdrv"
#define DISPLAY_DRIVER_NAME "tuill_dispdrv"
#define OS_DRIVER_NAME      "tuill_osdrv"

#define TUILLD_OSDRV_TA_NAME    "/dev/"OS_DRIVER_NAME
#define TUILLD_DISPDRV_TA_NAME  "/dev/"DISPLAY_DRIVER_NAME
#define TUILLD_TOUCHDRV_TA_NAME "/dev/"TOUCH_DRIVER_NAME

#ifdef TUILL_TESTDRV_ENABLE
#define TEST_DRIVER_NAME       "tuill_testdrv"
#define TUILLD_TESTDRV_TA_NAME "/dev/"TEST_DRIVER_NAME
#endif

#define TUILL_SERVER_TEMPLATE "/service/%s"

#define TUILL_API_VERSION  1

#define MAX_DISPLAY 1

/* --- Internal TUI LL spec types definition --------------------------------- */
/* these three constants weren't defined in TUI LL spec
 * and shouldn't be visible for user, but we need them */
#define TEE_PERIPHERAL_DISPLAY 0xABABABAB
#define TEE_PERIPHERAL_SERVICE 0xABABABAC
#define TEE_PERIPHERAL_TUIHW   0xABABABAD

#define TUILL_INVALID_HANDLE_VALUE (-1)
#define TUILL_OPENED_HANDLE_VALUE    1
#define TUILL_INVALID_32VALUE        0xFFFFFFFF

/* Proprietary peripheral UART */
#ifndef __HIDE_INTERNAL_FUNCTIONS__
#define TEES_PROP_PERIPHERAL_UART 0x80000001
#define TEES_PROP_EVENT_TYPE_TEST_DRV 0x00550004 /* TEST_DRV event */
#endif /* !__HIDE_INTERNAL_FUNCTIONS__ */

/* copied from /secure-kernel/linux/tui/stui_inf.h */
#define STUI_MODE_OFF         0x00
#define STUI_MODE_TUI_SESSION 0x01
#define STUI_MODE_DISPLAY_SEC 0x02
#define STUI_MODE_TOUCH_SEC   0x04
#define STUI_MODE_ALL         (STUI_MODE_TUI_SESSION | STUI_MODE_DISPLAY_SEC | STUI_MODE_TOUCH_SEC)
#define STUI_DISPLAY_INFO_SIZE 10

typedef uint32_t tuill_handle_t;

struct __TEE_EventQueueHandle {
    tuill_handle_t hndl;
};

struct __TEE_EventSourceHandle {
    tuill_handle_t hndl;
};

struct __TEE_PeripheralHandle {
    tuill_handle_t hndl;
};

/* --- Configuration enums definition ---------------------------------------- */
enum tuill_io_socket {
    TUILLDRV_SWD_SOCK,
    TUILLDRV_IWD_SOCK,
    TUILLDRV_SOCK_MAX
};

enum tuill_swd_components {
    /* enum order must be the same as in tuill_drivers */
    TUILL_TOUCH,
    TUILL_DISPLAY,
#if defined(TUILL_TESTDRV_ENABLE)
    TUILL_TEST,
#endif
    TUILL_SWD_MAX,
};

enum tuill_iwd_components {
    TUILL_TUIHW,
    TUILL_SERVICE,
    TUILL_IWD_MAX,
};

enum tuill_drivers {
    /* used as TEE_PeripheralId */
    TUILL_OS_DRV, //TODO: move this item to the end of enum
    /* enum order must be the same as in tuill_swd_components */
    TUILL_TOUCH_DRV,
    TUILL_DISPLAY_DRV,
#if defined(TUILL_TESTDRV_ENABLE)
    TUILL_TEST_DRV,
#endif
    TUILL_DRV_MAX,
};

/* --- IOCTL structures definition  ------------------------------------------ */
enum TUILL_DRV_IOCTL {
    TUILLDRV_IOCTL_NOP,
    TUILLDRV_IOCTL_SEND_EVENT,
    TUILLDRV_IOCTL_REBOOT,
    TUILLDRV_IOCTL_BLIT_DISPLAY_SURFACE,
    TUILLDRV_IOCTL_MAX = UINT8_MAX /* terminator, please do not add new statuses after this line */
};

struct tuilldrv_setsock_data {
    int32_t ret_code;
    char sock_name[UNIX_PATH_MAX];
} __attribute__((packed, aligned(4)));

struct tuilldrv_touch_data {
    uint32_t display;
    uint32_t action;
    uint32_t finger;
    uint32_t pressure;
    uint32_t x;
    uint32_t y;
} __attribute__((packed, aligned(4)));

struct tuilldrv_tee_data {
    uint32_t event;
} __attribute__((packed, aligned(4)));

struct tuilldrv_send_event_data {
    uint32_t peripheral_id;
    uint32_t event_type;
    int32_t  ret_code;
    uint32_t timeout_ms;
    union {
        struct tuilldrv_touch_data touch;
        struct tuilldrv_tee_data tee;
    } u;
} __attribute__((packed, aligned(4)));

struct tuilldrv_error_data {
    uint32_t do_err_flag;
    uint32_t do_err_step;
    uint32_t undo_err_flag;
    uint32_t undo_err_step;
} __attribute__((packed, aligned(4)));

/* --- Socket commands and structures definition ----------------------------- */
/* must match enum TUIInternalCommand in TUICmdWrapper.java */
enum tuill_internal_commands {
    TUILL_ICMD_PING,
    /* peripheral API */
    TUILL_ICMD_GET_PERIPHERAL_LIST,
    TUILL_ICMD_CLOSE_PERIPHERAL, /* used for TEE_Peripheral_Close and TEE_Peripheral_CloseMultiple */
    TUILL_ICMD_OPEN_PERIPHERAL,  /* used for TEE_Peripheral_Open and TEE_Peripheral_OpenMultiple */
    /* event API */
    TUILL_ICMD_ADD_SOURCES,
    TUILL_ICMD_CANCEL_SOURCES,
    TUILL_ICMD_CLOSE_CLIENT_QUEUE,
    TUILL_ICMD_DROP_SOURCES,
    TUILL_ICMD_LIST_SOURCES,
    TUILL_ICMD_OPEN_CLIENT_QUEUE,
    TUILL_ICMD_WAIT_EVENT,
    /* tui API */
    TUILL_ICMD_GET_DISPLAY_INFO,
    TUILL_ICMD_TUI_INIT_SESSION_LOW,
    TUILL_ICMD_TUI_CLOSE_SESSION,
    TUILL_ICMD_BLIT_DISPLAY_SURFACE,
    /* internal API */
    TUILL_ICMD_SET_DRV_STATE,
    TUILL_ICMD_TOUCH_EVENT,
    TUILL_ICMD_OPEN_DRIVER,
    TUILL_ICMD_CLOSE_DRIVER,
    TUILL_ICMD_REBOOT_PHONE,
    TUILL_ICMD_CANCEL_TUI,
    TUILL_ICMD_DRIVER_CLOSED,

#ifdef BUILD_TYPE_debug
    /* os_drv debug commands */
    TUILL_ICMD_SEND_EVENT,
    TUILL_ICMD_REBOOT,
    TUILL_ICMD_SEND_ERRDATA,
    TUILL_ICMD_TEST_DRV_EVENT,
#endif /* BUILD_TYPE_debug */

    TUILL_ICMD_MAX,
};

/* TUI LL posix error codes extention */
enum tuill_error_codes {
    TUILLE_OLD_VERSION             = 2001,
    TUILLE_UNSUPPORTED_VERSION     = TUILLE_OLD_VERSION,
    TUILLE_ACCESS_DENIED,
    TUILLE_CANCEL,
    TUILLE_EXCESS_DATA,
    TUILLE_BAD_FORMAT,
    TUILLE_BAD_PARAMETERS,
    TUILLE_BAD_STATE,
    TUILLE_ITEM_NOT_FOUND,
    TUILLE_OUT_OF_MEMORY,
    TUILLE_NO_DATA,
    TUILLE_BUSY,
    TUILLE_COMMUNICATION,
    TUILLE_SHORT_BUFFER,
    TUILLE_EXTERNAL_CANCEL,
    TUILLE_TIMEOUT,
    TUILLE_GENERIC,
    TUILLE_OVERFLOW,
};

#define RESPONSE_FLAG     0x80000000
#define INJECT_ERR_FLAG   0x40000000 /* for debugging, injects error code */
#define MAKE_TIMEOUT_FLAG 0x20000000 /* for debugging, makes timeout error */

/* we need to return this data if we opened display */
struct FB_Data {
    uint32_t width;
    uint32_t height;
    uint64_t fb_physical;
    uint64_t fb_virtual;
    uint64_t fb_size;
    uint64_t wb_physical;
    uint64_t wb_virtual;
    uint64_t wb_size;
    uint64_t disp_physical;
    uint64_t disp_size;
    uint32_t touch_type;
    uint64_t lcd_info[STUI_DISPLAY_INFO_SIZE];
} __attribute__((packed, aligned(4)));

struct open_peripheral_cmd {
    uint32_t num;
    uint32_t peripheral_id[TUILL_DRV_MAX];
    uint32_t flags;
    struct FB_Data fb;
} __attribute__((packed, aligned(4)));

struct open_peripheral_rsp {
    struct FB_Data fb;
} __attribute__((packed, aligned(4)));

struct close_peripheral_cmd {
    uint32_t num;
    uint32_t peripheral_id[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

typedef struct open_peripheral_cmd open_drivers_cmd_t;
typedef struct open_peripheral_rsp open_drivers_rsp_t;
typedef struct close_peripheral_cmd close_drivers_cmd_t;

#define TEE_MAX_EVENT_PAYLOAD_SIZE 32
#define TEE_MAX_EVENT_NUMBER       4

typedef struct {
    uint32_t eventType;
    uint64_t timestamp;
    tuill_handle_t event_handle;
    uint8_t payload[TEE_MAX_EVENT_PAYLOAD_SIZE];
} __TEE_Event_V1;

typedef struct {
    uint32_t version;
    uint32_t peripheral_id;
    union {
        __TEE_Event_V1 v1;
    } u;
} __TEE_Event;

/* event commands start */
struct add_sources_cmd {
    tuill_handle_t queue_handle;
    uint32_t num_sources;
    tuill_handle_t sources[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct cancel_sources_cmd {
    tuill_handle_t queue_handle;
    uint32_t num_sources;
    tuill_handle_t sources[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct close_queue_cmd {
    tuill_handle_t queue_handle;
} __attribute__((packed, aligned(4)));

struct drop_sources_cmd {
    tuill_handle_t queue_handle;
    uint32_t num_sources;
    tuill_handle_t sources[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct list_sources_cmd {
    tuill_handle_t queue_handle;
    uint32_t num_sources;
} __attribute__((packed, aligned(4)));

struct list_sources_rsp {
    uint32_t num_sources;
    tuill_handle_t sources[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct open_queue_cmd {
    uint32_t timeout_ms;
    uint32_t num_sources;
    tuill_handle_t sources[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct open_queue_rsp {
    tuill_handle_t queue_handle;
} __attribute__((packed, aligned(4)));

struct wait_event_cmd {
    tuill_handle_t queue_handle;
    uint32_t num_events;
    uint32_t timeout_ms;
} __attribute__((packed, aligned(4)));

struct wait_event_rsp {
    uint32_t num_events;
    uint32_t dropped;
    __TEE_Event events[TEE_MAX_EVENT_NUMBER];
} __attribute__((packed, aligned(4)));

struct touch_event_cmd {
    uint32_t display;
    uint32_t action;
    uint32_t finger;
    uint32_t pressure;
    uint32_t x;
    uint32_t y;
} __attribute__((packed, aligned(4)));

struct os_event_cmd {
    uint32_t peripheral_id;
    uint32_t event_type;
    uint32_t event;
} __attribute__((packed, aligned(4)));

/* event commands end */

struct set_drv_info_cmd {
    uint32_t drv_tui_mode;
    uint32_t index; /* from tuill_iwd_components */
} __attribute__((packed, aligned(4)));

struct get_display_info_cmd {
    uint32_t version;
    uint32_t displayNumber;
} __attribute__((packed, aligned(4)));

struct get_display_info_rsp {
    uint32_t physical_width;
    uint32_t physical_height;
    uint32_t pixel_width;
    uint32_t pixel_height;
    uint32_t bit_depth;
    uint32_t flags;
    uint32_t num_periph;
    uint32_t associated_peripherals[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct peripheral_info {
    uint32_t type;
    uint32_t id;
} __attribute__((packed, aligned(4)));

struct get_peripheral_list_rsp {
    uint32_t num;
    struct peripheral_info list[TUILL_DRV_MAX];
} __attribute__((packed, aligned(4)));

struct init_tui_session_cmd {
    uint32_t flags;
    uint32_t timeout_ms;
    uint32_t peripheral_id[TUILL_DRV_MAX];
    uint32_t num;
} __attribute__((packed, aligned(4)));

struct cancel_tui_cmd {
    uint32_t event;
} __attribute__((packed, aligned(4)));

struct blit_display_surface_cmd {
    uint32_t displayNumber;
} __attribute__((packed, aligned(4)));

struct tuill_internal_command {
    uint32_t cmd;
    int32_t  ret_code;
    uint32_t version;
    uint32_t task_state; /* duplicates field in struct task_ctx */
    uint32_t task_id;    /* duplicates field in struct task_ctx */
    union {
        /* event commands start */
        struct add_sources_cmd add_sources_cmd;
        struct cancel_sources_cmd cancel_sources_cmd;
        struct close_queue_cmd close_queue_cmd;
        struct drop_sources_cmd drop_sources_cmd;
        struct list_sources_cmd list_sources_cmd;
        struct list_sources_rsp list_sources_rsp;
        struct open_queue_cmd open_queue_cmd;
        struct open_queue_rsp open_queue_rsp;
        struct wait_event_cmd wait_event_cmd;
        struct wait_event_rsp wait_event_rsp;
        struct touch_event_cmd touch_event_cmd;
        struct os_event_cmd os_event_cmd;
        /* event commands end */
        /* peripheral commands start */
        struct get_peripheral_list_rsp get_peripheral_list_rsp;
        struct open_peripheral_cmd open_peripheral_cmd;
        struct open_peripheral_rsp open_peripheral_rsp;
        struct close_peripheral_cmd close_peripheral_cmd;
        /* peripheral commands end */
        /* tui commands start */
        struct get_display_info_cmd get_display_info_cmd;
        struct get_display_info_rsp get_display_info_rsp;
        struct init_tui_session_cmd init_tui_session_cmd;
        struct blit_display_surface_cmd blit_display_surface_cmd;
        /* tui commands end */
        /* other commands start */
        struct set_drv_info_cmd set_drv_info_cmd;
        open_drivers_cmd_t open_drivers_cmd;
        open_drivers_rsp_t open_drivers_rsp;
        close_drivers_cmd_t close_drivers_cmd;
        struct cancel_tui_cmd cancel_tui_cmd;
        /* other commands end */
#ifdef BUILD_TYPE_debug
        struct tuilldrv_send_event_data send_event_cmd;
        struct tuilldrv_error_data error_data_cmd;
#endif /* BUILD_TYPE_debug */
    };
} __attribute__((packed, aligned(4)));

/* --- Engine structures definition ------------------------------------------ */

struct tuill_buffer {
    int32_t data_len;
    char data[sizeof(struct tuill_internal_command)];
} __attribute__((packed, aligned(4)));

struct tuill_callbacks {
    int32_t (*process_input)(int32_t fd,
                             struct tuill_buffer *data);
    void (*process_hangup)(int32_t fd);
    void (*process_handhake)(int32_t fd);
};

enum tuill_socket_type {
    TUILLDRV_CLIENT_SWD_DRV,
    TUILLDRV_CLIENT_SWD_CLIENT,
    TUILLDRV_CLIENT_IWD_CLIENT,
};

struct tuill_socket_params {
    int32_t sfd; /* socket fd */
    int32_t efd; /* epoll fd */
};

/* common drv information */
struct tuill_drv_ctx {
    uint32_t index;           /* in drv_arr */
    uint32_t peripheral_type; /* GP enum values */
    uint32_t peripheral_id;   /* internal enum values */
    uint32_t tuill_state;     /* TEE_PERIPHERAL_STATE_FLAGS */
};

#ifdef __SECUREOS__
struct tuill_thread {
    pthread_t tid;
    atomic_t run;
    atomic_t wake_up;
    atomic_t finished;
    pthread_cond_t cond;
    pthread_mutex_t mutex;
};
#endif /* __SECUREOS__ */
/* ----- server side contexts for connected entities ------- */
struct tuill_drv_entity_ctx {
    struct tuill_drv_ctx drv_ctx; /* shows that driver is connected to system */
};

/* used to indicate opened state for drivers */
struct tuill_opened {
    /* TODO: change tui from bool to enum closed/opened/canceled */
    /* return TEE_ERROR_EXTERNAL_CANCEL for TUI related commands if tui==canceled */
    bool tui;  /* tui mode is on or off */
    bool interrupted; /* message about this driver interrupt was received */
    tuill_handle_t peripheral_hndl; /* indicates session opening */
    uint32_t peripheral_type;
    uint32_t peripheral_id;
};

enum task_type {
    TASK_NONE,
    TASK_OPEN,
    TASK_CLOSE,
    TASK_DISPLAYINFO,
    TASK_CLOSE_NWD
};

enum task_cmd_state {
    TASK_CMD_VOID,
    TASK_CMD_NEEDED,
    TASK_CMD_SENT,
    TASK_CMD_DONE,
    TASK_CMD_ERROR,
    TASK_CMD_UNDO_SENT,
    TASK_CMD_UNDONE,
};

enum task_state {
    TASK_STATE_VOID,
    TASK_STATE_DOING,
    TASK_STATE_UNDOING,
};

struct task_step_state {
    uint32_t state; /* command state */
    uint32_t num;   /* command step num */
};

struct task_ctx {
    uint32_t task_cmd;
    uint32_t task_state;
    uint32_t task_id;
    uint32_t task_timer_id; /* id for command executing timer */
    struct tuill_buffer do_cmd;   /* this command is sent to all entities num_of_steps times */
    struct tuill_buffer undo_cmd; /* this command is sent to all entities num_of_steps times */
    uint32_t num_of_steps;   /* total steps */
    uint32_t step_cnt;       /* current step counter */
    uint32_t type;           /* TASK_NONE means that the task is free
                              * other values mean that the task is processed */
    struct task_step_state swd_state[TUILL_SWD_MAX]; /* shows that the driver was processed, used for undo */
    struct task_step_state iwd_state[TUILL_IWD_MAX]; /* shows that the driver was processed, used for undo */
};

struct tuill_client_entity_ctx {
    void *queue_ctx;
    uint32_t tui_timeout_ms; /* timeout for tui session */
    uint32_t tui_timer_id;   /* id for tui session timer */
    bool timer_expired;
    struct tuill_opened opened[TUILL_DRV_MAX];
    struct task_ctx task;
};

struct tuill_iwd_entity_ctx {
    uint32_t index; /* from tuill_iwd_components */
    uint32_t tui_mode;
};
/* --------------------------------------------------------- */

/* ---- Client side data types ---------------------------- */
struct tuill_client_context {
    /* socket data */
    char *server_name;
    struct tuill_socket_params sock;
    /* listening thread */
    bool run_fl;
    pthread_t tid;
    struct tuill_callbacks cb;
};
