/*

  Zerocat Chipflasher --- Flash free firmware, kick the Management Engine.

  Copyright (C) 2016  kai <kmx@posteo.net>
  Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2025  Kai Mertens <kmx@posteo.net>

  This file is part of Zerocat Chipflasher.

  Zerocat Chipflasher is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by the
  Free Software Foundation, either version 3 of the License, or (at your
  option) any later version.

  Zerocat Chipflasher is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License
  along with Zerocat Chipflasher.
  If not, see <http://www.gnu.org/licenses/>.


***/


# ifndef __CONNECT_H__
#   define __CONNECT_H__


//  Diagnostic Compiler Switches
//  ============================


//  Includes
//  ========


#   include "../../firmware1/src/libcommon/serial-codes.h"    //include serial control codes
#   include "ANSI-color-escape-sequences.h"
#   include <ctype.h>


//  Macros
//  ======


#   define PROJECT_HEADER       "Zerocat Chipflasher "VERSION""

#   define HEADER_PROGRAM       \
  "Zerocat Chipflasher --- Flash free firmware to BIOS chips, kick the Management Engine.\n"

#   define HEADER_LICENSE       \
  "\nCopyright (C) 2015–2025  Authors of Zerocat Chipflasher"                           \
  "\nThis program comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law."   \
  "\nThis is free software, and you are welcome to redistribute it under certain"       \
  "\nconditions. See git://zerocat.org/zerocat/projects/chipflasher.git for details."   \
  "\n"

#   define HEADER_CONNECT       PROJECT_HEADER      ": `connect', coded in C"

#   define MSG_TOP                         FG_CYAN
#   define MSG_START                       FG_DEFAULT
#   define MSG_OK                          FG_LIGHTGREEN
#   define MSG_WARN                        FG_MAGENTA
#   define MSG_ERROR                       FG_RED
#   define MSG_STOP                        FG_DARKGRAY
#   define MSG_RESET                       RESET_ALL
#   define WRITE_BUF_STDOUT__MSG_START     WRITESTR_BUF_STDOUT(FG_DEFAULT)
#   define WRITE_BUF_STDOUT__MSG_STOP      WRITESTR_BUF_STDOUT(FG_DARKGRAY)
#   define WRITE_BUF_STDOUT__DATA_BIN      WRITESTR_BUF_STDOUT(FG_YELLOW)
#   define WRITE_BUF_STDOUT__DATA_HEX      WRITESTR_BUF_STDOUT(FG_LIGHTGRAY)

#   define SIZE_PORT            6
#   define PORT_DEFAULT         0
#   define SIZE_RATE            8
#   define RATE_DEFAULT         5
#   define RESET_DURATION       500000

//  Payload Case for FILE_TO_CATCH and Display:
#   define LOWER_CASE          0
#   define UPPER_CASE          1
#   define CASE_MODE           UPPER_CASE

// File to be used for write-to-chip operations.
#   define FILE_TO_SEND       "file2chip.txt"

// File to be used for write-to-disk operations.
#   define FILE_TO_CATCH      "chip2file.txt"

// Digital 1, -5V on serial line.
#   define MARK               0x00

// Digital 0, +5V on serial line.
#   define SPACE              0x01

#   undef  MAX
#   define MAX(x,y)           ((x) > (y) ? (x) : (y))

/*
  FIXME:

  We need a graceful shutdown of the firmware, too!

*/
#   define EXITFAIL(msg)                                      \
  {                                                           \
    fprintf(stderr, "\r%s\r\n", MSG_ERROR);                   \
    perror(msg);                                              \
    fprintf(stderr, "\r%s\r\n", MSG_RESET);                   \
    if(fdtty > -1)                                            \
      close(fdtty);                                           \
    if(fdrd > -1)                                             \
      close(fdrd);                                            \
    if(fdwr > -1)                                             \
      close(fdwr);                                            \
    exit(EXIT_FAILURE);                                       \
  }

#   define WRITE_BUF_STDOUT(c)                                \
  {                                                           \
    if(pwr_stdout == SIZE_BUF_STDOUT) {                       \
      EXITFAIL("polling(): stdout buffer overflow");          \
    }                                                         \
    else {                                                    \
      *(buf_stdout + pwr_stdout++) = c;                       \
    }                                                         \
  }

#   define WRITESTR_BUF_STDOUT(s)                             \
  {                                                           \
    int i = 0;                                                \
    int n = sizeof(s);                                        \
    do {                                                      \
      if(pwr_stdout == SIZE_BUF_STDOUT)                       \
        EXITFAIL("polling(): stdout buffer overflow");        \
      *(buf_stdout + pwr_stdout++) = *(s + i++);              \
    } while(--n);                                             \
  }

#   define WRITE_BUF_FILE(c)                                  \
  {                                                           \
    if(pwr_file == SIZE_BUF_FILE) {                           \
      EXITFAIL("polling(): file buffer overflow");            \
    }                                                         \
    else                                                      \
      *(buf_file + pwr_file++) = c;                           \
  }



// Timeout settings for pselect.
// The timeout should be bigger than repetitive SPI power-up time!
//
#   define TIMEOUT_SEC          0           //pselect timeout setting, full seconds
#   define TIMEOUT_NSEC         750000000   //pselect timout setting, nanoseconds

#   define USEC_BYTE_SREC       165         // Grant controller’s parse loop some time to process byte
#   define USEC_BYTE_HEXD       125         // Grant controller’s parse loop some time to process byte

#   define SIZE_BUF_RDTTY       (512 << 3)
#   define SIZE_BUF_STDOUT      (512 << 6)  // We have non-blocking access, thus a big buffer is required
#   define SIZE_BUF_FILE        (512 << 3)
#   define FLUSH_NO_INPUT       0
#   define FLUSH_WITH_INPUT     1


//  Types
//  =====


enum CONNECT_SCANNER_t {
  SCANNER_OFF = -2,
  SCANNER_INI,
  SCAN_START,
  SCAN_S = SCAN_START,
  SCAN_STYPE,
  SCAN_RECLEN_MSB,
  SCAN_RECLEN_LSB
};

enum CONNECT_FILESTEP_t {
  START_FILE_READOUT = 0,
  BYTE_PREVIEW,
  CHECK_STX,
  CHECK_CRNL,
  SEND_BYTE,
  SEND_CLIM,
  SEND_ETX_OR_CAN,
  WAIT_CHAR,
  RECEIVE_ACK,
  RECEIVE_NAK,
  RECEIVE_CAN,
  SEND_EOT,
  FLUSH_BUFFERS,
  CLOSE_TX
};

// Struct that characterizes a Motorola-S data line.
struct CONNECT_LINESREC_t {
  int sizeofaddr;             //number of address bytes, i.e. 2, 3 or 4
  int reclen;                 //record length
  int ndata;                  //number of data bytes (binary or represented by character pair)
  int pos_addrlsb;            //line offset of last address byte
  int payload;                //FIXME: What is this??
  int size;                   //size of the line, i.e. number of buffer bytes
  unsigned char checksum;     //calculated checksum
  unsigned char chksum_rx;    //checksum that has been received
};

// Struct that characterizes a Hex-Dump data line.
struct CONNECT_LINEHEXD_t {
  char is_info;               //is comment line
  char is_print;              //is printable character
  char is_first;              //is first character of line
};


//  Prototypes
//  ==========


void time_elapsed (
  struct timespec *ts_start,
  struct timespec *ts_stop
);

int lineinfo (
  char linetype,
  int * piline,
  char c,
  struct CONNECT_LINEHEXD_t * plineHEXD,
  struct CONNECT_LINESREC_t * plineSREC,
  int hexmode
);

char bin2hexdigit (
  unsigned char vbin,
  unsigned char mode
);

signed char SREC_addrlen (
  char SREC_type
);

int get_DTR (
  int fdtty
);

void set_DTR (
  int fdtty,
  int level
);

void set_RTS (
  int fdtty,
  int level
);

void greeting (
  const char *port,
  const char *rate
);

void goodbye (
  void
);

int connect (
  char * dev,
  const speed_t baudrate,
  unsigned int bps
);

void restore_stdout (
  void
);

char polling (
  int fdtty
);

void errout (
  enum ERRCODE_t errcode
);

void headline (
  char c,
  char * pstr
);

void lock_tty (
  int fdtty
);

void unlock_tty (
  int fdtty
);

# endif
/* __CONNECT_H__ */
