* apps/system/zmodem/zm.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
* "The ZMODEM Inter Application File Transfer Protocol", Chuck Forsberg,
* Omen Technology Inc., October 14, 1988
*/
#ifndef __APPS_SYSTEM_XMODEM_ZM_H
#define __APPS_SYSTEM_XMODEM_ZM_H
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <debug.h>
#include <syslog.h>
#include <nuttx/compiler.h>
#include <nuttx/ascii.h>
#include "system/zmodem.h"
* Pre-processor Definitions
****************************************************************************/
* Reference: Paragraph 11.2:
*/
#define CANFDX (1 << 0)
#define CANOVIO (1 << 1)
#define CANBRK (1 << 2)
#define CANCRY (1 << 3)
#define CANLZW (1 << 4)
#define CANFC32 (1 << 5)
#define ESCCTL (1 << 6)
#define ESC8 (1 << 7)
#define TESCCTL (1 << 6)
#define TESC8 (1 << 7)
#define ZCBIN 1
#define ZCNL 2
#define ZCRESUM 3
#define ZMNEWL 1
#define ZMCRC 2
#define ZMAPND 3
#define ZMCLOB 4
#define ZMNEW 5
#define ZMDIFF 6
#define ZMPROT 7
#define ZMCHNG 8
#define ZMMASK 0x1f
#define ZMSKNOLOC (1 << 7)
#define ZTLZW 1
#define ZTRLE 3
#define ZCANVHDR 1
#define ZRWOVR 4
#define ZXSPARS 64
#define ATTNBRK 0xdd
#define ATTNPSE 0xde
#define ZRQINIT 0
#define ZRINIT 1
#define ZSINIT 2
#define ZACK 3
#define ZFILE 4
#define ZSKIP 5
#define ZNAK 6
#define ZABORT 7
#define ZFIN 8
#define ZRPOS 9
#define ZDATA 10
#define ZEOF 11
#define ZFERR 12
#define ZCRC 13
#define ZCHALLENGE 14
#define ZCOMPL 15
#define ZCAN 16
#define ZFREECNT 17
#define ZCOMMAND 18
#define ZSTDERR 19
#define ZDLE ASCII_CAN
#define ZDLEE (ZDLE^0x40)
#define ZPAD '*'
#define ZBIN 'A'
#define ZHEX 'B'
#define ZBIN32 'C'
#define ZBINR32 'D'
#define ZVBIN 'a'
#define ZVHEX 'b'
#define ZVBIN32 'c'
#define ZVBINR32 'd'
#define ZRESC 0x7f
#define ZCRCE 'h'
#define ZCRCG 'i'
#define ZCRCQ 'j'
#define ZCRCW 'k'
#define ZRUB0 'l'
#define ZRUB1 'm'
#define ZME_RQINIT ZRQINIT
#define ZME_RINIT ZRINIT
#define ZME_SINIT ZSINIT
#define ZME_ACK ZACK
#define ZME_FILE ZFILE
#define ZME_SKIP ZSKIP
#define ZME_NAK ZNAK
#define ZME_ABORT ZABORT
#define ZME_FIN ZFIN
#define ZME_RPOS ZRPOS
#define ZME_DATA ZDATA
#define ZME_EOF ZEOF
#define ZME_FERR ZFERR
#define ZME_CRC ZCRC
#define ZME_CHALLENGE ZCHALLENGE
#define ZME_COMPL ZCOMPL
#define ZME_CAN ZCAN
#define ZME_FREECNT ZFREECNT
#define ZME_COMMAND ZCOMMAND
#define ZME_STDERR ZSTDERR
#define ZME_CANCEL 251
#define ZME_OO 252
#define ZME_DATARCVD 253
#define ZME_TIMEOUT 254
#define ZME_ERROR 255
#define ZM_FLAG_CRC32 (1 << 0)
#define ZM_FLAG_CRKOK (1 << 1)
#define ZM_FLAG_EOF (1 << 2)
#define ZM_FLAG_ATSIGN (1 << 3)
#define ZM_FLAG_ESCCTRL (1 << 4)
#define ZM_FLAG_ESC (1 << 5)
#define ZM_FLAG_WAIT (1 << 6)
#define ZM_FLAG_APPEND (1 << 7)
#define ZM_FLAG_TIMEOUT (1 << 8)
#define ZM_FLAG_OO (1 << 9)
*
* < 0 : Transfer terminated due to an error
* = 0 : Transfer still in progress
* > 0 : Transfer completed successfully
*/
#define ZM_XFRDONE 1
* and the maxmimum size 4-byte CRC.
*/
#define ZM_PKTBUFSIZE (CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE + 5)
* to stderr (not syslog). Enabling this kind of debug output if your are
* trying to use the console device I/O for file transfer is obviously a bad
* idea (unless, perhaps, you redirect stdin and stdout).
*
* See also CONFIG_SYSTEM_ZMODEM_DUMPBUFFER.
*/
#ifdef CONFIG_DEBUG_ZMODEM
# define zmprintf(format, ...) syslog(LOG_INFO, format, ##__VA_ARGS__)
# define zmdbg(format, ...) syslog(LOG_INFO, EXTRA_FMT format EXTRA_ARG, ##__VA_ARGS__)
#else
# undef CONFIG_SYSTEM_ZMODEM_DUMPBUFFER
# define zmprintf(x...)
# define zmdbg(x...)
#endif
* Public Types
****************************************************************************/
enum parser_state_e
{
PSTATE_IDLE = 0,
PSTATE_HEADER,
PSTATE_DATA,
};
enum pidle_substate_e
{
PIDLE_ZPAD = 0,
PIDLE_ZDLE,
PIDLE_OO
};
enum pheader_substate_e
{
PHEADER_FORMAT = 0,
PHEADER_PAYLOAD,
PHEADER_LSPAYLOAD,
};
enum pdata_substate_e
{
PDATA_READ = 0,
PDATA_CRC
};
* a state transition.
*/
struct zm_state_s;
typedef int (*action_t)(FAR struct zm_state_s *pzm);
* state. Each row is a row of all reasonable events for this state and long
* the appropriate state transition and transition action.
*/
struct zm_transition_s
{
uint8_t type;
bool bdiscard;
uint8_t next;
action_t action;
};
* information needed by the common Zmodem receive and transmit parsing.
*/
struct zm_state_s
{
int fdin;
int fdout;
* current action. Different state transitions tables are used for Zmodem
* vs. XY modem and for receive and for transmit.
*/
FAR const struct zm_transition_s * const * evtable;
* Notes:
* (1) Only valid during parsing.
*/
uint8_t pstate;
uint8_t psubstate;
uint8_t state;
uint8_t timeout;
uint8_t ncrc;
uint8_t ncan;
uint8_t hdrfmt;
uint8_t hdrndx;
uint8_t hdrdata[9];
uint8_t pkttype;
uint16_t rcvlen;
uint16_t rcvndx;
uint16_t pktlen;
uint16_t flags;
uint16_t nerrors;
timer_t timer;
int remfd;
*
* rcvbuf - Data from the remote peer is receive this buffer
* pktbuf - un-escaped remote peer data is parsed into this buffer
* scratch - Holds data sent to the remote peer. Since the data is this
* buffer is short lived, this buffer may also be used for other
* scratch purposes.
*/
uint8_t rcvbuf[CONFIG_SYSTEM_ZMODEM_RCVBUFSIZE];
uint8_t pktbuf[ZM_PKTBUFSIZE];
uint8_t scratch[CONFIG_SYSTEM_ZMODEM_SNDBUFSIZE];
#ifdef CONFIG_SYSTEM_ZMODEM_SNDFILEBUF
uint8_t filebuf[CONFIG_SYSTEM_ZMODEM_SNDBUFSIZE];
#endif
};
struct zmr_state_s
{
struct zm_state_s cmn;
uint8_t rcaps;
uint8_t scaps;
uint8_t f0;
uint8_t f1;
#if 0
uint8_t f2;
uint8_t f3;
#endif
uint8_t ntimeouts;
uint32_t crc;
FAR const char *pathname;
FAR char *filename;
FAR char *attn;
off_t offset;
off_t filesize;
#ifdef CONFIG_SYSTEM_ZMODEM_TIMESTAMPS
time_t timestamp;
#endif
int outfd;
};
struct zms_state_s
{
struct zm_state_s cmn;
uint8_t dpkttype;
uint8_t fflags[4];
uint16_t rcvmax;
#ifdef CONFIG_SYSTEM_ZMODEM_TIMESTAMPS
uint32_t timestamp;
#endif
#ifdef CONFIG_SYSTEM_ZMODEM_SENDATTN
FAR char *attn;
#endif
FAR const char *filename;
FAR const char *rfilename;
off_t offset;
off_t lastoffs;
off_t zrpos;
off_t filesize;
int infd;
};
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
EXTERN const uint8_t g_zeroes[4];
*
* "If the receiver is receiving data in streaming mode, the Attn sequence
* is executed to interrupt data transmission before the Cancel sequence is
* sent. The Cancel sequence consists of eight CAN characters and ten
* backspace characters. ZMODEM only requires five Cancel characters, the
* other three are "insurance".
*
* "The trailing backspace characters attempt to erase the effects of the
* CAN characters if they are received by a command interpreter.
*/
#define CANISTR_SIZE (8+10)
EXTERN const uint8_t g_canistr[CANISTR_SIZE];
* Public Function Prototypes
****************************************************************************/
* Name: zm_bytobe32
*
* Description:
* Convert a sequence of four bytes into a 32-bit value. The byte
* sequence is assumed to be big-endian.
*
****************************************************************************/
uint32_t zm_bytobe32(FAR const uint8_t *val8);
* Name: zm_bytobe32
*
* Description:
* Convert a 32-bit value in a sequence of four bytes in big-endian byte
* order.
*
****************************************************************************/
void zm_be32toby(uint32_t val32, FAR uint8_t *val8);
* Name: zm_encnibble
*
* Description:
* Encode an 4-bit binary value to a single hex "digit".
*
****************************************************************************/
char zm_encnibble(uint8_t nibble);
* Name: zm_encnibble
*
* Description:
* Decode an 4-bit binary value from a single hex "digit".
*
****************************************************************************/
uint8_t zm_decnibble(char hex);
* Name: zm_puthex8
*
* Description:
* Convert an 8-bit binary value to 2 hex "digits".
*
****************************************************************************/
FAR uint8_t *zm_puthex8(FAR uint8_t *ptr, uint8_t ch);
* Name: zm_read
*
* Description:
* Read a buffer of data from a read-able stream.
*
****************************************************************************/
ssize_t zm_read(int fd, FAR uint8_t *buffer, size_t buflen);
* Name: zm_getc
*
* Description:
* Read a one byte of data from a read-able stream.
*
****************************************************************************/
int zm_getc(int fd);
* Name: zm_write
*
* Description:
* Write a buffer of data to a write-able stream.
*
****************************************************************************/
ssize_t zm_write(int fd, FAR const uint8_t *buffer, size_t buflen);
* Name: zm_remwrite
*
* Description:
* Write a buffer of data to the remote peer.
*
****************************************************************************/
#ifdef CONFIG_SYSTEM_ZMODEM_DUMPBUFFER
ssize_t zm_remwrite(int fd, FAR const uint8_t *buffer, size_t buflen);
#else
# define zm_remwrite(f,b,s) zm_write(f,b,s)
#endif
* Name: zm_writefile
*
* Description:
* Write a buffer of data to file, performing newline conversions as
* necessary.
*
* NOTE: Not re-entrant. CR-LF sequences that span buffer boundaries are
* not guaranteed to be handled correctly.
*
****************************************************************************/
int zm_writefile(int fd, FAR const uint8_t *buffer,
size_t buflen, bool zcnl);
* Name: zm_filecrc
*
* Description:
* Perform CRC32 calculation on a file.
*
* Assumptions:
* The allocated I/O buffer is available to buffer file data.
*
****************************************************************************/
uint32_t zm_filecrc(FAR struct zm_state_s *pzm, FAR const char *filename);
* Name: zm_rawmode
*
* Description:
* Set the terminal to the raw mode
*
****************************************************************************/
void zm_rawmode(int fd);
* Name: zm_flowc
*
* Description:
* Enable hardware Rx/Tx flow control.
*
****************************************************************************/
#ifdef CONFIG_SYSTEM_ZMODEM_FLOWC
void zm_flowc(int fd);
#endif
* Name: zm_putzdle
*
* Description:
* Transfer a value to a buffer performing ZDLE escaping if necessary
*
* Input Parameters:
* pzm - Zmodem session state
* buffer - Buffer in which to add the possibly escaped character
* ch - The raw, unescaped character to be added
*
****************************************************************************/
FAR uint8_t *zm_putzdle(FAR struct zm_state_s *pzm, FAR uint8_t *buffer,
uint8_t ch);
* Name: zm_senddata
*
* Description:
* Send data to the remote peer performing CRC operations as necessary
* (ZBIN or ZBIN32 format assumed, ZCRCW terminator is always used)
*
* Input Parameters:
* pzm - Zmodem session state
* buffer - Buffer of data to be sent
* buflen - The number of bytes in buffer to be sent
*
****************************************************************************/
int zm_senddata(FAR struct zm_state_s *pzm, FAR const uint8_t *buffer,
size_t buflen);
* Name: zm_sendhexhdr
*
* Description:
* Send a ZHEX header to the remote peer performing CRC operations as
* necessary.
*
* Input Parameters:
* pzm - Zmodem session state
* type - Header type {ZRINIT, ZRQINIT, ZDATA, ZACK, ZNAK, ZCRC, ZRPOS,
* ZCOMPL, ZEOF, ZFIN}
* buffer - 4-byte buffer of data to be sent
*
* Assumptions:
* The allocated I/O buffer is available to buffer file data.
*
****************************************************************************/
int zm_sendhexhdr(FAR struct zm_state_s *pzm, int type,
FAR const uint8_t *buffer);
* Name: zm_sendbin16hdr
*
* Description:
* Send a ZBIN header to the remote peer performing CRC operations as
* necessary. Normally called indirectly through zm_sendbinhdr().
*
* Input Parameters:
* pzm - Zmodem session state
* type - Header type {ZSINIT, ZFILE, ZDATA, ZDATA}
* buffer - 4-byte buffer of data to be sent
*
* Assumptions:
* The allocated I/O buffer is available to buffer file data.
*
****************************************************************************/
int zm_sendbin16hdr(FAR struct zm_state_s *pzm, int type,
FAR const uint8_t *buffer);
* Name: zm_sendbin32hdr
*
* Description:
* Send a ZBIN32 header to the remote peer performing CRC operations as
* necessary. Normally called indirectly through zm_sendbinhdr().
*
* Input Parameters:
* pzm - Zmodem session state
* type - Header type {ZSINIT, ZFILE, ZDATA, ZDATA}
* buffer - 4-byte buffer of data to be sent
*
* Assumptions:
* The allocated I/O buffer is available to buffer file data.
*
****************************************************************************/
int zm_sendbin32hdr(FAR struct zm_state_s *pzm, int type,
FAR const uint8_t *buffer);
* Name: zm_sendbinhdr
*
* Description:
* Send a binary header to the remote peer. This is a simple wrapping
* function for zm_sendbin16hdr() and zm_sendbin32hdr(). It decides on
* the correct CRC format and re-directs the call appropriately.
*
* Input Parameters:
* pzm - Zmodem session state
* type - Header type {ZSINIT, ZFILE, ZDATA, ZDATA}
* buffer - 4-byte buffer of data to be sent
*
* Assumptions:
* The allocated I/O buffer is available to buffer file data.
*
****************************************************************************/
int zm_sendbinhdr(FAR struct zm_state_s *pzm, int type,
FAR const uint8_t *buffer);
* Name: zm_datapump
*
* Description:
* Drive the Zmodem state machine by reading data from the remote peer and
* providing that data to the parser. This loop runs until a fatal error
* is detected or until the state machine reports that the transfer has
* completed successfully.
*
****************************************************************************/
int zm_datapump(FAR struct zm_state_s *pzm);
* Name: zm_readstate
*
* Description:
* Enter PSTATE_DATA.
*
****************************************************************************/
void zm_readstate(FAR struct zm_state_s *pzm);
* Name: zm_timeout
*
* Description:
* Called by the watchdog logic if/when a timeout is detected.
*
****************************************************************************/
int zm_timeout(FAR struct zm_state_s *pzm);
* Name: zm_rcvpending
*
* Description:
* Return true if data from the remote receiver is pending. In that case,
* the local sender should stop data streaming operations and process the
* incoming data.
*
****************************************************************************/
#ifdef CONFIG_SYSTEM_ZMODEM_RCVSAMPLE
bool zm_rcvpending(FAR struct zm_state_s *pzm);
#endif
* Name: zm_timerinit
*
* Description:
* Create the POSIX timer used to manage timeouts and attach the SIGALRM
* signal handler to catch the timeout events.
*
****************************************************************************/
int zm_timerinit(FAR struct zm_state_s *pzm);
* Name: zm_timerstart
*
* Description:
* Start, restart, or stop the timer.
*
****************************************************************************/
int zm_timerstart(FAR struct zm_state_s *pzm, unsigned int sec);
* Name: zm_timerstop
*
* Description:
* Stop the timer.
*
****************************************************************************/
#define zm_timerstop(p) zm_timerstart(p,0)
* Name: zm_timerrelease
*
* Description:
* Destroy the timer and and detach the signal handler.
*
****************************************************************************/
int zm_timerrelease(FAR struct zm_state_s *pzm);
* Name: zm_dumpbuffer
*
* Description:
* Dump a buffer of zmodem data.
*
****************************************************************************/
#ifdef CONFIG_SYSTEM_ZMODEM_DUMPBUFFER
# define zm_dumpbuffer(m,b,s) lib_dumpbuffer(m,b,s)
#else
# define zm_dumpbuffer(m,b,s)
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif