Listing 1

/*--------------------------------------------
XMODEM.H

Author    Date       Description
-------------------------------------
Jon Ward  22 Apr 90  Initial Revision.
--------------------------------------------*/

#ifndef XMODEM_H
#define XMODEM_H

/*--------------------------------------------
        Xmodem Transfer Errors
--------------------------------------------*/
enum xmodem_errors   
  {
  XERR_OK,  /* No errors */
  
  XERR_XMIT_FUNC,  /* NULL Transmit function pointer */
  XERR_RCVR_FUNC,  /* NULL Receive function pointer */
  
  XERR_RCVR_CANCEL,  /* Receiver cancelled the transfer */
  XERR_SEND_CANCEL,  /* Sender cancelled the transfer */
  XERR_USER CANCEL,  /* User cancelled the transfer */
  
  XERR_FILE_READ,   /* Error reading the file */
  XERR_FILE_WRITE,  /* Error writing the file */
  
  XERR_ACK_TIMEOUT,    /* Timed out waiting for data pack ACK */
  XERR_NAK_TIMEOUT,    /* Timed out waiting for initial NAK */
  XERR_SOH_TIMEOUT,    /* Timed out waiting for SOH */
  XERR_DATA_TIMEOUT,   /* Timed out waiting for data */
  XERR_LAST_ACK_TIMEOUT,/* Timed out waiting for final ACK */
  
  XERR_INVALID_SOH,    /* Invalid char waiting for SOH */
  XERR_INVALID_BLOCK_NUM,/* Block mismatch in packet header */
  XERR_INVALID_CRC,    /* CRC is incorrect */
  XERR_INVALID_CHECKSUM,/* Checksum is incorrect */
  XERR_BLOCK_SEQUENCE, /* Block out of sequence */
  
  XERR_CHAR_ERROR, /* Received character error */
  XERR_OFFLINE,        /* Modem not online */
  
  XERR_BLOCK_NAK,  /* NAK received */
  };
  
#ifdef XMODEM_LIB
/*------------------------------------------------
Number of attempts and timeout for each attempt
to transferr using CRC.
------------------------------------------------*/
#define CRC_RETRY_COUNT        4
#define CRC_TIMEOUT        (3L * MS_PER_SEC)

/*------------------------------------------------
Number of attempts and timeout for each attempt
to Negative Acknowledge a bad packet. This also
includes the initial NAK to get the thing started.
------------------------------------------------*/
#define NAK_RETRY_COUNT        10
#define NAK_TIMEOUT        (10L * MS_PER_SEC)

/*------------------------------------------------
Number of attempts and timeout for each attempt
to Acknowledge a good packet.
------------------------------------------------*/
#define ACK_RETRY_COUNT        10
#define ACK_TIMEOUT        (10L * MS_PER_SEC)

/*------------------------------------------------
Number of consecutive CANs and the timeout between
them.
------------------------------------------------*/
#define CAN_COUNT_ABORT        2

#define CAN_TIMEOUT        (2L * MS_PER_SEC)

/*------------------------------------------------
Timeout between packet data bytes.
------------------------------------------------*/
#define DATA_TIMEOUT       (1L * MS_PER_SEC)

/*------------------------------------------------
Number of false start characters that the sender
can receive before aborting the transmission.
------------------------------------------------*/
#define START_XMIT_RETRY_COUNT 10
#define START_XMIT_TIMEOUT (60L * MS_PER_SEC)

/*------------------------------------------------
Maximum number of attempts to send a single block.
------------------------------------------------*/
#define BLOCK_RETRY_COUNT      10

/*------------------------------------------------
Timeout for block responses.
------------------------------------------------*/
#define BLOCK_RESP_TIMEOUT (10L * MS_PER_SEC)

/*------------------------------------------------
Macro to purge all characters from the receive
buffer. This waits until there are no characters
received for a 1 second period.
------------------------------------------------*/
#define PURGE_RECEIVER(c) \
while ((*(c)) (MS_PER_SEC, NULL) != RECV_TIMEOUT)

#endif /* XMODEM_LIB */

/*------------------------------------------------
Number of milliseconds in a second. I know this
is silly, but it makes the meaning a little more
obvious.
------------------------------------------------*/
#define MS_PER_SEC     1000L

/*------------------------------------------------
Block sizes for normal and for 1K XMODEM
transfers.
------------------------------------------------*/
#define XMODEM_BLOCK_SIZE 128
#define XMODEM_1K_BLOCK_SIZE   1024

/*------------------------------------------------
Values returned by the receive character serial
interface function.
------------------------------------------------*/
#define RECV_TIMEOUT -1 /* receiver timed-out */

/*------------------------------------------------
Error bits stored in the receiv character error
flag.
------------------------------------------------*/
#define RE_OVERRUN_  0x01   /* receiver overrun error */
#define RE_PARITY_  0x02    /* receiver parity error */
#define RE_FRAMING_  0x04  /* receiver framing error */

/*------------------------------------------------
Values returned by the transmit character serial
interface function.
------------------------------------------------*/
#define XMIT_OK        0   /* character enqued for transmission */
#define XMIT_OFFLINE   -1  /* modem offline */

/*-----------------------------------------------
     ASCII values used by XMODEM
-----------------------------------------------*/
#define SOH        1
#define STX        2
#define EOT        4
#define ACK        6
#define BACKSPACE  8
#define NAK        21
#define CAN        24

#define CPMEOF     26

/*-----------------------------------------------
XMODEM block description structure. This is only
used internally by the send and receive routines
and should not be visible outside of these.
-----------------------------------------------*/
#ifdef XMODEM_LIB
struct xmodem_block_st
  {
  long total_block_count;  /* total blocks transferred */
  long total_byte_count;   /* total bytes transferred */
  
  unsigned char start_char;  /* block starting character */
  unsigned char block_num; /* transmission block number */
  unsigned char not_block_num; /* one's complement block number */
  char buffer [XMODEM_1K_BLOCK_SIZE + 1];  /* data buffer */
  int buflen;          /* buffer length (128 or 1024) */
  unsigned char checksum;  /* data checksum */
  unsigned int crc;        /* data CRC-16 */
  
  unsigned int crc_used: 1;    /* 0=Checksum 1=CRC-16 */
  };

typedef struct xmodem_block_st xblock;
#endif /* XMODEM_LIB */

/*-----------------------------------------------
XMODEM function pointer structure.
-----------------------------------------------*/
#ifdef XMODEM_LIB
struct xmodem_func_st
  {
  int (*transmit) (    /* xmit function */
    char);
  
  int (*receive) (  /* recv function */
    long,
    unsigned int *);
  
  void (*dispstat) (   /* display function */
    long,
    long,
    const char *);
  
  int (*check_abort) (void);  /* manual abort function */
  };

typedef struct xmodem_func_st xfunc;
#endif /* XMODEM_LIB */


/*-----------------------------------------------
         XMODEMR.C
-----------------------------------------------*/
int xmodem_recv (
  FILE *f,                 /* file to write to */
  int (*transmit) (char),          /* xmit function */
  int (*receive) (long, unsigned int *),   /* recv function */
  void (*dispstat) (long, long, const char *), /* display function */
  int (*check_abort) (void));          /* manual abort function */

#ifdef XMODEM_LIB
int xm_perror (
  int error,               /* error number */
  xfunc *xmf);             /* xmodem external functions */

void xm_no_disp_func (
  long a,
  long b,
  const char *buf);

int xm_no_abort_func (void);
#endif /* XMODEM_LIB */




/*-----------------------------------------------
         XMODEMS.C
-----------------------------------------------*/
int xmodem_send (
  int block_size,              /* maximum block size */
  FILE *f,                 /* file to write to */
  int (*transmit) (char),         /* xmit function */
  int (*receive) (long, unsigned int *),  /* recv function */
  void (*dispstat) (long, long, const char *), /* display function */
  int (*check_abort) (void));           /* manual abort function */

#ifdef XMODEM_LIB
unsigned int xm_update_CRC (
  unsigned int crc,       /* current CRC */
  unsigned int c);    /* character to add to CRC */

void xm_send_cancel (
  int (*transmit) (char)); /* transmit function */
#endif /* XMODEM_LIB */

#endif     /* XMODEM_H */