mirror of
https://github.com/romychs/ESPKit.git
synced 2025-04-18 01:52:41 +03:00
559 lines
10 KiB
NASM
559 lines
10 KiB
NASM
; ======================================================
|
|
; WTFTP client for trivial file transfer protocol
|
|
; for Sprinter-WiFi ISA Card
|
|
; By Roman Boykov. Copyright (c) 2024
|
|
; https://github.com/romychs
|
|
; License: BSD 3-Clause
|
|
; ======================================================
|
|
|
|
; Set to 1 to turn debug ON with DeZog VSCode plugin
|
|
; Set to 0 to compile .EXE
|
|
DEFINE DEBUG
|
|
|
|
; Set to 1 to output TRACE messages
|
|
DEFINE TRACE
|
|
|
|
|
|
WM_DOWNLOAD EQU 0
|
|
WM_UPLOAD EQU 1
|
|
|
|
|
|
; Version of EXE file, 1 for DSS 1.70+
|
|
EXE_VERSION EQU 1
|
|
|
|
; Timeout to wait ESP response
|
|
DEFAULT_TIMEOUT EQU 2000
|
|
|
|
DEVICE NOSLOT64K
|
|
|
|
IFDEF DEBUG
|
|
INCLUDE "dss.asm"
|
|
DB 0
|
|
ALIGN 16384, 0
|
|
DS 0x80, 0
|
|
ENDIF
|
|
|
|
INCLUDE "macro.inc"
|
|
INCLUDE "dss.inc"
|
|
;INCLUDE "sprinter.inc"
|
|
|
|
MODULE MAIN
|
|
|
|
ORG 0x8080
|
|
; ------------------------------------------------------
|
|
EXE_HEADER
|
|
DB "EXE"
|
|
DB EXE_VERSION ; EXE Version
|
|
DW 0x0080 ; Code offset
|
|
DW 0
|
|
DW 0 ; Primary loader size
|
|
DW 0 ; Reserved
|
|
DW 0
|
|
DW 0
|
|
DW START ; Loading Address
|
|
DW START ; Entry Point
|
|
DW STACK_TOP ; Stack address
|
|
DS 106, 0 ; Reserved
|
|
|
|
ORG 0x8100
|
|
@STACK_TOP
|
|
|
|
; ------------------------------------------------------
|
|
START
|
|
|
|
IFDEF DEBUG
|
|
LD IX,CMD_LINE_TFTP_U
|
|
LD SP, STACK_TOP
|
|
ENDIF
|
|
|
|
PRINTLN MSG_START
|
|
|
|
CALL PARSE_CMD_LINE
|
|
|
|
CALL DISPLAY_MODE
|
|
|
|
CALL OPEN_LOCAL_FILE
|
|
|
|
IF_UPLOAD_GO DO_UPLOAD
|
|
CALL @TFTP.BUILD_RRQ_PACKET
|
|
JP DONE
|
|
|
|
DO_UPLOAD
|
|
CALL @TFTP.BUILD_WRQ_PACKET
|
|
|
|
DONE
|
|
CALL CLOSE_LOCAL_FILE
|
|
|
|
;IFDEF DEBUG
|
|
LD BC, DSS_EXIT
|
|
RST DSS
|
|
|
|
;ENDIF
|
|
|
|
CALL ISA.ISA_RESET
|
|
|
|
CALL @WCOMMON.INIT_VMODE
|
|
|
|
PRINTLN MSG_START
|
|
|
|
CALL @WCOMMON.FIND_SWF
|
|
|
|
PRINTLN WCOMMON.MSG_UART_INIT
|
|
CALL @WIFI.UART_INIT
|
|
|
|
PRINTLN WCOMMON.MSG_ESP_RESET
|
|
CALL @WIFI.ESP_RESET
|
|
|
|
CALL @WCOMMON.INIT_ESP
|
|
|
|
PRINTLN MSG_HLP
|
|
|
|
CALL @WIFI.UART_EMPTY_RS
|
|
|
|
MAIN_LOOP
|
|
|
|
; ------------------------------------------------------
|
|
; Do Some
|
|
; ------------------------------------------------------
|
|
|
|
OK_EXIT
|
|
LD B,0
|
|
JP WCOMMON.EXIT
|
|
|
|
; ------------------------------------------------------
|
|
; Parse command line parameters
|
|
; IX - points to cmd line
|
|
; ------------------------------------------------------
|
|
PARSE_CMD_LINE
|
|
PUSH IX
|
|
POP HL ; HL -> CMD Line
|
|
LD A,(HL) ; CMD Line length
|
|
OR A
|
|
JR Z, OUT_USAGE_MSG
|
|
INC HL ; skip length byte
|
|
CALL @UTIL.LTRIM ; skip leading non-printable characters
|
|
|
|
|
|
; check first parameter for tftp url pattern
|
|
LD DE,TFTF_START ; check parameter to start from 'tftp://'
|
|
CALL @UTIL.STARTSWITH
|
|
JR NZ,.PLC_UPLOAD
|
|
|
|
; Work Mode "Download"
|
|
|
|
; handle parameter URL
|
|
CALL GET_SRV_PARAMS
|
|
CALL @UTIL.LTRIM ; skip spaces between parameters
|
|
|
|
; handle lfn
|
|
CALL GET_LFN
|
|
JP COPY_LFN
|
|
;CALL COPY_LFN
|
|
;RET
|
|
|
|
.PLC_UPLOAD
|
|
; Work mode "Upload"
|
|
LD A, WM_UPLOAD
|
|
LD (WORK_MODE),A
|
|
|
|
CALL GET_LFN
|
|
CALL @UTIL.LTRIM
|
|
|
|
LD DE,TFTF_START
|
|
CALL @UTIL.STARTSWITH
|
|
JR NZ,OUT_USAGE_MSG
|
|
|
|
JP GET_SRV_PARAMS
|
|
;CALL GET_SRV_PARAMS
|
|
;RET
|
|
|
|
; ------------------------------------------------------
|
|
OUT_ERR_CMD_MSG
|
|
PRINTLN MSG_ERR_CMD
|
|
|
|
; ------------------------------------------------------
|
|
OUT_USAGE_MSG
|
|
PRINTLN MSG_HLP
|
|
JP OK_EXIT
|
|
|
|
; ------------------------------------------------------
|
|
; Move srv name and port number from (HL) to (DE)
|
|
; ------------------------------------------------------
|
|
GET_SRV_PARAMS
|
|
PUSH BC,DE
|
|
|
|
LD DE,0x0007
|
|
ADD HL,DE
|
|
|
|
LD DE,SRV_NAME
|
|
.GSN_NEXT
|
|
LD A,(HL)
|
|
OR A ; end of url?
|
|
JR Z,.GSN_END
|
|
CP '/' ; end of server name?
|
|
JR Z,.GSN_END
|
|
CP ':' ; end of server name and has port?
|
|
JR Z,.GSN_PORT
|
|
LD (DE), A ; move and get next
|
|
INC HL
|
|
INC DE
|
|
JR .GSN_NEXT
|
|
; has port number
|
|
.GSN_PORT
|
|
LD DE,SRV_PORT
|
|
LD B,6
|
|
.GSNP_NXT
|
|
INC HL
|
|
LD A,(HL)
|
|
CP A,'/' ; end slash
|
|
JR Z,.GSN_EN
|
|
CP A,'0'
|
|
JP M,.GSN_EPN
|
|
CP A,0x3A ; >'9'?
|
|
JP P,.GSN_EPN
|
|
LD (DE),A
|
|
INC DE
|
|
DJNZ .GSNP_NXT
|
|
; too long number
|
|
|
|
|
|
.GSN_EPN
|
|
PRINTLN MSG_ERR_PORT
|
|
JP OUT_USAGE_MSG
|
|
|
|
.GSN_EN
|
|
LD DE,SRV_PORT
|
|
LD A,(DE)
|
|
OR A ; ':/' - no port number specified
|
|
JR Z,.GSN_EPN
|
|
PUSH HL
|
|
CALL @UTIL.ATOU
|
|
LD (SRV_PORT),HL
|
|
POP HL
|
|
|
|
.GSN_END
|
|
; get file name from url
|
|
LD DE,REM_FILE
|
|
LD B,127
|
|
.GDNF_NXT
|
|
INC HL
|
|
LD A,(HL)
|
|
CP 0x21
|
|
JP M,.GDNF_END
|
|
LD (DE),A
|
|
INC DE
|
|
DEC B
|
|
JR NZ,.GDNF_NXT
|
|
JR .GDNF_ERR ; file name too long
|
|
; check file name is not empty
|
|
.GDNF_END
|
|
LD DE,REM_FILE
|
|
LD A,(DE)
|
|
OR A
|
|
JR NZ,.GSN_RET
|
|
; out error about invalid file name
|
|
.GDNF_ERR
|
|
PRINTLN MSG_ERR_RFN
|
|
JP OUT_USAGE_MSG
|
|
.GSN_RET
|
|
POP DE,BC
|
|
RET
|
|
|
|
; ------------------------------------------------------
|
|
; Get local file name from command line
|
|
; Inp: HL -> command line
|
|
; ------------------------------------------------------
|
|
GET_LFN
|
|
PUSH BC,DE
|
|
LD DE,LOC_FILE
|
|
|
|
.GLF_NXT
|
|
LD A,(HL)
|
|
OR A
|
|
JR Z,.GLF_END
|
|
CP ' '
|
|
JR Z,.GLF_END
|
|
CP 0x21
|
|
JP M,.GLF_IFN
|
|
CP '*'
|
|
JP Z,.GLF_IFN
|
|
CP ':'
|
|
CALL .GLF_HAVE_PATH
|
|
CP "\\"
|
|
CALL .GLF_HAVE_PATH
|
|
|
|
LD (DE),A
|
|
INC HL
|
|
INC DE
|
|
JR .GLF_NXT
|
|
|
|
.GLF_END
|
|
POP DE,BC
|
|
RET
|
|
|
|
; set flag to not add current dir
|
|
.GLF_HAVE_PATH
|
|
JR NZ, .GLF_NHP
|
|
LD IY,HAVE_PATH
|
|
INC (IY+0)
|
|
.GLF_NHP
|
|
RET
|
|
|
|
; Illegal file name
|
|
.GLF_IFN
|
|
PRINTLN MSG_ERR_LFN
|
|
JP OUT_USAGE_MSG
|
|
|
|
; ------------------------------------------------------
|
|
; Check local file name for empty and fill it from
|
|
; remote file name
|
|
; ------------------------------------------------------
|
|
COPY_LFN
|
|
LD HL,LOC_FILE
|
|
LD A, (HL)
|
|
OR A
|
|
RET NZ ; ok, it is not empty
|
|
CALL UTIL.GET_CUR_DIR
|
|
//LD DE,HL
|
|
LD IX,HAVE_PATH
|
|
INC (IX+0)
|
|
|
|
LD DE,REM_FILE
|
|
LD B,12 ; limit filename length nnnnnnnn.exe
|
|
.CLFN_NXT
|
|
LD A,(DE)
|
|
LD (HL),A
|
|
OR A
|
|
RET Z
|
|
INC HL
|
|
INC DE
|
|
DJNZ .CLFN_NXT
|
|
|
|
; ------------------------------------------------------
|
|
; Open local file for upload or download
|
|
; RO - for upload
|
|
; WR - for download
|
|
; ------------------------------------------------------
|
|
OPEN_LOCAL_FILE
|
|
LD HL,LOC_FILE
|
|
LD A,(HAVE_PATH)
|
|
OR A
|
|
JR NZ,.OLF_SKP_CP
|
|
|
|
LD HL, TMP_BUFF
|
|
CALL UTIL.GET_CUR_DIR
|
|
LD DE,LOC_FILE
|
|
LD B,128
|
|
.OLF_NXT
|
|
LD A, (DE)
|
|
LD (HL),A
|
|
OR A
|
|
JR Z, .OLF_EFN
|
|
INC HL
|
|
INC DE
|
|
DJNZ .OLF_NXT
|
|
.OLF_EFN
|
|
LD HL, TMP_BUFF
|
|
|
|
; HL - points to file path name
|
|
.OLF_SKP_CP
|
|
IF_UPLOAD_GO .OLF_UPL
|
|
|
|
; create new file for write
|
|
PUSH HL, HL
|
|
PRINT MSG_LFN_CR
|
|
POP HL
|
|
CALL PRINT_FILENAME
|
|
POP HL
|
|
|
|
XOR A
|
|
PUSH HL
|
|
LD C,DSS_CREATE_FILE
|
|
RST DSS
|
|
POP HL
|
|
JR NC,.OLF_END
|
|
CP 0x07 ; file exists?
|
|
JP NZ,DSS_ERROR.EPRINT ; print error and exit
|
|
PUSH HL
|
|
PRINTLN MSG_OF_EXISTS
|
|
POP HL
|
|
LD A,FM_WRITE
|
|
JR .OLF_FOW
|
|
|
|
; open existing file for read
|
|
.OLF_UPL
|
|
PUSH HL, HL
|
|
PRINT MSG_LFN_OP
|
|
POP HL
|
|
CALL PRINT_FILENAME
|
|
POP HL
|
|
LD A,FM_READ
|
|
.OLF_FOW
|
|
LD C,DSS_OPEN_FILE
|
|
RST DSS
|
|
CALL DSS_ERROR.CHECK
|
|
.OLF_END
|
|
LD (LOC_FH),A
|
|
|
|
TRACELN MSG_LFN_OPEN
|
|
|
|
RET
|
|
|
|
PRINT_FILENAME
|
|
DSS_EXEC DSS_PCHARS
|
|
PRINTLN WCOMMON.LINE_END
|
|
RET
|
|
|
|
|
|
MSG_OF_EXISTS
|
|
DB "Output file already exists!",0
|
|
|
|
IFDEF TRACE
|
|
MSG_LFN_CR
|
|
DB "Create file: ",0
|
|
MSG_LFN_OP
|
|
DB "Open file: ",0
|
|
MSG_LFN_OPEN
|
|
DB "File successfully accessed.",0
|
|
ENDIF
|
|
|
|
|
|
; ------------------------------------------------------
|
|
; Closes loacal file if it open
|
|
; ------------------------------------------------------
|
|
CLOSE_LOCAL_FILE
|
|
LD A,(LOC_FH)
|
|
OR A
|
|
RET Z
|
|
DSS_EXEC DSS_CLOSE_FILE
|
|
JP DSS_ERROR.CHECK
|
|
;CALL DSS_ERROR.CHECK
|
|
;RET
|
|
|
|
; ------------------------------------------------------
|
|
; Display current working mode
|
|
; ------------------------------------------------------
|
|
DISPLAY_MODE
|
|
IF_UPLOAD_GO .DM_UPLOAD
|
|
; Download
|
|
PRINT MSG_MODE_D
|
|
PRINT REM_FILE
|
|
PRINT MSG_MODE_D_S
|
|
PRINT SRV_NAME
|
|
PRINT MSG_MODE_D_T
|
|
PRINTLN LOC_FILE
|
|
RET
|
|
; Upload
|
|
.DM_UPLOAD
|
|
PRINT MSG_MODE_U
|
|
PRINT LOC_FILE
|
|
PRINT MSG_MODE_U_S
|
|
PRINT SRV_NAME
|
|
PRINT MSG_MODE_U_T
|
|
PRINTLN REM_FILE
|
|
RET
|
|
|
|
; ------------------------------------------------------
|
|
; Custom messages
|
|
; ------------------------------------------------------
|
|
|
|
MSG_START
|
|
DB "TFTP client for Sprinter-WiFi by Sprinter Team. v1.0 beta1, ", __DATE__, "\r\n",0
|
|
|
|
MSG_ERR_CMD
|
|
DB "Invalid command line parameters!\r\n",0
|
|
|
|
MSG_HLP
|
|
DB "\r\nUse:\r\n wtftp.exe tftp://server[:port]/filename filename - to download from server;\r\n"
|
|
DB " wtftp.exe filename tftp://server[:port]/filename - to upload to server.\r\n",0
|
|
|
|
MSG_TX_ERROR
|
|
DB "Transmitter not ready",0
|
|
|
|
MSG_RX_ERROR
|
|
DB "Receiver error LSR: 0x"
|
|
MSG_LSR_VALUE
|
|
DB "xx",0
|
|
|
|
MSG_MANY_RX_ERROR
|
|
DB "Too many receiver errors!",0
|
|
|
|
MSG_ERR_PORT
|
|
DB "Invalid UDP port in URL, will be number 1..65535",0
|
|
|
|
MSG_ERR_RFN
|
|
DB "Remote file name not specified in URL, or too long!",0
|
|
|
|
MSG_ERR_LFN
|
|
DB "Invalid local file name!",0
|
|
|
|
MSG_MODE_D
|
|
DB "Download file ",0
|
|
MSG_MODE_D_S
|
|
DB " from server ",0
|
|
MSG_MODE_D_T
|
|
DB " to file ",0
|
|
|
|
MSG_MODE_U
|
|
DB "Upload file ",0
|
|
MSG_MODE_U_S
|
|
DB " to server ",0
|
|
MSG_MODE_U_T
|
|
DB " to file ",0
|
|
|
|
; ------------------------------------------------------
|
|
; Variables
|
|
; ------------------------------------------------------
|
|
|
|
; Start of tftf URL
|
|
TFTF_START
|
|
DB "tftp://",0
|
|
|
|
|
|
; Work Mode
|
|
WORK_MODE
|
|
DB WM_DOWNLOAD
|
|
|
|
; Name/IP of the tftp server
|
|
SRV_NAME
|
|
DS 128,0
|
|
CMDLINE
|
|
; UDP port of the tftp server
|
|
SRV_PORT
|
|
DB 69,0,0,0,0,0 ; udp port number 0..65535
|
|
|
|
; Name of the remote file
|
|
REM_FILE
|
|
DS 128,0
|
|
|
|
; Name of the local file
|
|
LOC_FILE
|
|
DS 128,0
|
|
|
|
; Local file handlewtftp.asm(343)
|
|
LOC_FH
|
|
DW 0
|
|
|
|
; Non zero, if local file name contains path
|
|
HAVE_PATH
|
|
DB 0
|
|
|
|
TMP_BUFF EQU WIFI.RS_BUFF + RS_BUFF_SIZE
|
|
|
|
ENDMODULE
|
|
; ------------------------------------------------------
|
|
; Includes
|
|
; ------------------------------------------------------
|
|
|
|
INCLUDE "wcommon.asm"
|
|
INCLUDE "dss_error.asm"
|
|
;INCLUDE "util.asm"
|
|
INCLUDE "isa.asm"
|
|
INCLUDE "tftp.asm"
|
|
INCLUDE "esplib.asm"
|
|
|
|
|
|
|
|
|
|
END MAIN.START
|