/*
 * Copyright (C) MOXA Inc. All rights reserved.
 * Authors:
 *     2024  Wilson YS Huang  <wilsonys.huang@moxa.com>
 * This software is distributed under the terms of the MOXA SOFTWARE NOTICE.
 * See the file LICENSE for details.
 */

#ifndef _MCU_H_
#define _MCU_H_

#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/poll.h>
#include <termios.h>
#include <unistd.h>

#include <common.h>

typedef enum {
    ERR_CODE_OK = 0,
    ERR_CODE_COMMAND_NOT_SUPPORT,
    ERR_CODE_COMMAND_ILLEGAL_MCU_PKT,
    ERR_CODE_COMMAND_NACK_MCU_PKT,
    ERR_CODE_COMMAND_UNEXPECTED_RESP,
    ERR_CODE_MCU_NOT_AVAILABLE,
    ERR_CODE_UNKNOWN
} mcu_error_code;

#define MX_MCU_DAEMON_UNIX_SOCK_PATH "/var/run/mx-mcud.sock"

#define MX_MCU_CMD_SIZE 3
#define MX_MCU_CMD      0x07   // Command Packet
#define MX_MCU_ACK      0x06   // Acknowledge Packet
#define MX_MCU_NACK     0x15   // Negative ACK Packet
// 0x15 0x07 0xFF 0x52 0x45 0x00 0x4D 0x15 0xFF 0x52 0x45 0x4C 0x00 0x08
// 0x15 0xFF 0x52 0x45 0x07 0x00 0x4D 0x15 0xFF 0x52 0x45 0x4C 0x00 0x08
#define MX_MCU_ADDR_BROADCAST 0xFF

#define MX_MCU_VERSION_CMD             "\x53\x57\x49"
#define MX_MCU_RELAY_MODE_CMD          "\x52\x45\x4C"
#define MX_MCU_WDT_RESET_MODE_CMD      "\x57\x52\x53"
#define MX_MCU_WDT_RELAY_MODE_CMD      "\x57\x52\x4C"
#define MX_MCU_POWEROFF_RELAY_MODE_CMD "\x50\x52\x4C"
#define MX_MCU_APP_WDT_RELAY_MODE_CMD  "\x41\x57\x4C"
#define MX_MCU_APP_WDT_RESET_MODE_CMD  "\x41\x57\x52"
#define MX_MCU_APP_WDT_TIMEOUT_CMD     "\x41\x57\x54"
#define MX_MCU_APP_TICK_CMD            MX_MCU_APP_WDT_TIMEOUT_CMD
#define MX_MCU_FW_UPGRADE_CMD          "\x53\x46\x55"
#define MX_MCU_FW_MODEL_NAME_CMD       "\x54\x59\x50"
#define MX_MCU_BRIGHTNESS_CMD          "\x42\x4C\x49"
#define MX_MCU_SYSTEM_STATUE_CMD       "\x53\x59\x3F"
#define MX_MCU_PANEL_TOUCH_CTRL_CMD    "\x50\x54\x43"
#define MX_MCU_SHOW_OSD_CMD            "\x4F\x53\x44"

#define FEAT_MCU_VERSION                BIT(0)
#define FEAT_MCU_RELAY_MODE             BIT(1)
#define FEAT_MCU_WDT_RESET_MODE         BIT(2)
#define FEAT_MCU_WDT_RELAY_MODE         BIT(3)
#define FEAT_MCU_POWEROFF_RELAY_MODE    BIT(4)
#define FEAT_MCU_APP_WDT_RELAY_MODE     BIT(5)
#define FEAT_MCU_APP_WDT_RESET_MODE_CMD BIT(6)
#define FEAT_MCU_APP_WDT_TIMEOUT_CMD    BIT(7)
#define FEAT_MCU_FW_UPGRADE_CMD         BIT(8)
#define FEAT_MCU_MODEL_NAME_CMD         BIT(9)
#define FEAT_MCU_BRIGHTNESS_CMD         BIT(10)
#define FEAT_MCU_SYSTEM_STATUE_CMD      BIT(11)
#define FEAT_MCU_PANEL_TOUCH_CTRL_CMD   BIT(12)
#define FEAT_MCU_SHOW_OSD_CMD           BIT(13)

#define DELAY_SEND_PKT 300

/* MCU firmware binary header */
#define MCU_BIN_HEADER_BASE         0x2000
#define MCU_BIN_WRITE_BASE          MCU_BIN_HEADER_BASE
#define MCU_BIN_HEADER_INDEX_OFFSET 0x04
#define MCU_BIN_HEADER_0            0x48
#define MCU_BIN_HEADER_1            0x80
#define MCU_BIN_HEADER_2            0x47
#define MCU_BIN_HEADER_3            0x04
#define MCU_BIN_PACKET_MAX          128

typedef struct {
    uint8_t attn;
    uint8_t addr;
    uint8_t command[3];
    uint8_t data_sz;
    uint8_t hdr_chk;
    uint8_t data[];
} __attribute__((packed)) mcu_packet;

typedef void (*resp_callback)(mcu_error_code code, uint8_t *resp_data, size_t resp_data_sz, void *arg);

bool is_mcu_command_support(uint8_t *command, uint32_t features);
bool mcu_hal_init(const char *tty_name);
void mcu_hal_request(uint8_t *command, uint8_t *data, size_t data_sz, resp_callback callback, void *callback_arg);

#endif