/**
 * @file hal_serial.h    
 * @brief   Platform (Hardware/OS) abstraction layer
 * @author dfs 
 * @version 1.0
 * @date 2023-12-14
 * 
 * @copyright Copyright (c) 2023  杭州科技股份有限公司
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-14 <td>1.0     <td>dfs     <td>内容
 * </table>
 */

#ifndef WIN32
#include <stdint.h>
#include <stdbool.h>
#endif // !WIN32


#ifndef SER_HAL_PORT_
#define SER_HAL_PORT_

#ifdef __cplusplus
extern "C" {
#endif

typedef struct sSerialPort* SerialPort;

typedef enum {
    SERIAL_PORT_ERROR_NONE = 0,
    SERIAL_PORT_ERROR_INVALID_ARGUMENT = 1,
    SERIAL_PORT_ERROR_INVALID_BAUDRATE = 2,
    SERIAL_PORT_ERROR_OPEN_FAILED = 3,
    SERIAL_PORT_ERROR_SELECT_FAILED = 4,
    SERIAL_PORT_ERROR_READ_FAILED = 5,
    
    SERIAL_PORT_ERROR_UNKNOWN = 99
} SerialPortError;

/**
 * \brief Create a new SerialPort instance
 *
 * \param interfaceName identifier or name of the serial interface (e.g. "/dev/ttyS1" or "COM4")
 * \param baudRate the baud rate in baud (e.g. 9600)
 * \param dataBits the number of data bits (usually 8)
 * \param parity defines what kind of parity to use ('E' - even parity, 'O' - odd parity, 'N' - no parity)
 * \param stopBits the number of stop buts (usually 1)
 *
 * \return the new SerialPort instance
 */
SerialPort serial_create(const char* interfaceName, int baudRate, uint8_t dataBits, char parity, uint8_t stopBits);

/**
 * \brief Destroy the SerialPort instance and release all resources
 */
void serial_destroy(SerialPort self);

/**
 * \brief Open the serial interface
 *
 * \return true in case of success, false otherwise (use \ref SerialPort_getLastError for a detailed error code)
 */
bool serial_open(SerialPort self);

/**
 * \brief Close (release) the serial interface
 */
void serial_close(SerialPort self);

/**
 * \brief Get the baudrate used by the serial interface
 *
 * \return the baud rate in baud
 */
int serial_getbaudrate(SerialPort self);

/**
 * \brief Set the timeout used for message reception wait
 *
 * \param timeout the timeout value in ms.
 */
void serial_settimeout(SerialPort self, int timeout);

/**
 * \brief Set the timeout used for frame end
 *
 * \param timeout the timeout value in ms.
 */
void serial_set_bytetimeout(SerialPort self, int timeout);


/**
 * \brief Discard all data in the input buffer of the serial interface
 */
void serial_discardinbuffer(SerialPort self);

/*
 *  ---------- Request     Indication ----------
 *  | Client | ---------------------->| Server |
 *  ---------- Confirmation  Response ----------
 */
typedef enum {
    /* Request message on the server side */
    SERIAL_MSG_INDICATION,
    /* Request message on the client side */
    SERIAL_MSG_CONFIRMATION
} msg_type_t;

/**
 * \brief Read bytes from the interface
 *
 *  \param msg the buffer containing the data to write
 * \param want_size number of bytes to write
 * \param msg_type  ref msg_type_t
 * 
 * \return number of read bytes of -1 in case of an error
 * 
 */
int serial_readbytes(SerialPort self, uint8_t *msg, int want_size, int msg_type);

/**
 * \brief Write the number of bytes from the buffer to the serial interface
 *
 * \param buffer the buffer containing the data to write
 * \param startPos start position in the buffer of the data to write
 * \param numberOfBytes number of bytes to write
 *
 * \return number of bytes written, or -1 in case of an error
 */
int serial_write(SerialPort self, uint8_t* buffer, int startPos, int numberOfBytes);

/**
 * \brief Get the error code of the last operation
 */
SerialPortError serial_getlasterror(SerialPort self);

/*! @} */

/*! @} */

#ifdef __cplusplus
}
#endif


#endif /* SER_HAL_PORT_ */
