From ddd86d31ca3a4a8ba38184f6b7378a69e4017df6 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Thu, 23 Aug 2018 06:33:39 -0600 Subject: [PATCH] apps/system/zmodem: - fix error "sz_main.o: No such file or directory" - support -p for rz to change the folder for the recevied file - switch debug output from printf to syslog - send the next packet for ZME_ACK in ZMS_SENDING to avoid rz on the host side stuck - make send work reliable even without hardware flow control --- include/system/zmodem.h | 5 +- system/zmodem/Makefile | 5 +- system/zmodem/README.txt | 20 +++--- system/zmodem/rz_main.c | 11 +++- system/zmodem/zm.h | 7 +- system/zmodem/zm_dumpbuffer.c | 119 ---------------------------------- system/zmodem/zm_receive.c | 13 ++-- system/zmodem/zm_send.c | 33 +--------- 8 files changed, 40 insertions(+), 173 deletions(-) delete mode 100644 system/zmodem/zm_dumpbuffer.c diff --git a/include/system/zmodem.h b/include/system/zmodem.h index fe236a778..1fd51fbf8 100644 --- a/include/system/zmodem.h +++ b/include/system/zmodem.h @@ -250,14 +250,15 @@ ZMRHANDLE zmr_initialize(int remfd); * Receive file(s) sent from the remote peer. * * Input Parameters: - * handle - The handler created by zmr_initialize(). + * handle - The handler created by zmr_initialize(). + * pathname - The name of the local path to hold the file * * Returned Value: * Zero on success; a negated errno value on failure. * ****************************************************************************/ -int zmr_receive(ZMRHANDLE handle); +int zmr_receive(ZMRHANDLE handle, FAR const char *pathname); /**************************************************************************** * Name: zmr_release diff --git a/system/zmodem/Makefile b/system/zmodem/Makefile index 99bb7bb60..547cb8864 100644 --- a/system/zmodem/Makefile +++ b/system/zmodem/Makefile @@ -56,7 +56,7 @@ STACKSIZE = $(CONFIG_SYSTEM_ZMODEM_STACKSIZE) ASRCS = CSRCS = zm_send.c zm_receive.c zm_state.c zm_proto.c zm_watchdog.c -CSRCS += zm_utils.c zm_dumpbuffer.c +CSRCS += zm_utils.c SZ_MAINSRC = sz_main.c RZ_MAINSRC = rz_main.c @@ -64,12 +64,13 @@ AOBJS = $(ASRCS:.S=$(OBJEXT)) COBJS = $(CSRCS:.c=$(OBJEXT)) SZ_MAINOBJ = $(SZ_MAINSRC:.c=$(OBJEXT)) RZ_MAINOBJ = $(RZ_MAINSRC:.c=$(OBJEXT)) +MAINOBJ = $(SZ_MAINOBJ) $(RZ_MAINOBJ) SRCS = $(ASRCS) $(CSRCS) $(SZ_MAINSRC) $(RZ_MAINSRC) OBJS = $(AOBJS) $(COBJS) ifneq ($(CONFIG_BUILD_KERNEL),y) - OBJS += $(SZ_MAINOBJ) $(RZ_MAINOBJ) + OBJS += $(MAINOBJ) endif ifeq ($(CONFIG_WINDOWS_NATIVE),y) diff --git a/system/zmodem/README.txt b/system/zmodem/README.txt index 228d2e8bc..b626acbef 100755 --- a/system/zmodem/README.txt +++ b/system/zmodem/README.txt @@ -162,10 +162,10 @@ Using NuttX ZModem with a Linux Host Then use the sz command on Linux to send the file to the target: - $ sudo sz [-l nnnn] /dev/ttyS0 + $ sudo sz [-l nnnn] [-w nnnn] /dev/ttyS0 - Where is the file that you want to send. If -l nnnn is not - specified, then there will likely be packet buffer overflow errors. + Where is the file that you want to send. If -l nnnn and -w nnnn + is not specified, then there will likely be packet buffer overflow errors. nnnn should be set to a value less than or equal to CONFIG_SYSTEM_ZMODEM_PKTBUFSIZE @@ -173,11 +173,11 @@ Using NuttX ZModem with a Linux Host "sandbox" via CONFIG_SYSTEM_ZMODEM_MOUNTPOINT. You can add the sz -v option multiple times, each increases the level - of debug output. If you want to capture the Linux rz output, then - re-direct stderr to a log file by adding 2>az.log to the end of the - rz command. + of debug output. If you want to capture the Linux sz output, then + re-direct stderr to a log file by adding 2>sz.log to the end of the + sz command. - If you don't have the az command on your Linux box, the package to + If you don't have the sz command on your Linux box, the package to install rzsz (or possibily lrzsz). Building the ZModem Tools to Run Under Linux @@ -214,7 +214,7 @@ Status have been able to send large and small files with the target sz command. I have been able to receive small files, but there are problems receiving large files using the Linux sz command: The - Linux SZ does not obey the buffering limits and continues to send + Linux sz does not obey the buffering limits and continues to send data while rz is writing the previously received data to the file and the serial driver's RX buffer is overrun by a few bytes while the write is in progress. As a result, when it reads the next @@ -265,3 +265,7 @@ Status olimex-stm32-p407/zmodem configuration with target-to-host transfers was verified. Again, there are issues remaining if I tried the NuttX rz utility running on Linux. + + 2018-6-26: + with -w nnnn option, the host-to-target transfer can work reliably + without hardware flow control. diff --git a/system/zmodem/rz_main.c b/system/zmodem/rz_main.c index 38b889eaf..eab946de5 100644 --- a/system/zmodem/rz_main.c +++ b/system/zmodem/rz_main.c @@ -64,6 +64,8 @@ static void show_usage(FAR const char *progname, int errcode) fprintf(stderr, "\nWhere OPTIONS include the following:\n"); fprintf(stderr, "\t-d : Communication device to use. Default: %s\n", CONFIG_SYSTEM_ZMODEM_DEVNAME); + fprintf(stderr, "\t-p : Folder to hold the received file. Default: %s\n", + CONFIG_SYSTEM_ZMODEM_MOUNTPOINT); fprintf(stderr, "\t-h: Show this text and exit\n"); exit(errcode); } @@ -80,6 +82,7 @@ int rz_main(int argc, FAR char **argv) { ZMRHANDLE handle; FAR const char *devname = CONFIG_SYSTEM_ZMODEM_DEVNAME; + FAR const char *pathname = CONFIG_SYSTEM_ZMODEM_MOUNTPOINT; int exitcode = EXIT_FAILURE; int option; int ret; @@ -87,7 +90,7 @@ int rz_main(int argc, FAR char **argv) /* Parse input parameters */ - while ((option = getopt(argc, argv, ":d:h")) != ERROR) + while ((option = getopt(argc, argv, ":d:hp:")) != ERROR) { switch (option) { @@ -99,6 +102,10 @@ int rz_main(int argc, FAR char **argv) show_usage(argv[0], EXIT_SUCCESS); break; + case 'p': + pathname = optarg; + break; + case ':': fprintf(stderr, "ERROR: Missing required argument\n"); show_usage(argv[0], EXIT_FAILURE); @@ -146,7 +153,7 @@ int rz_main(int argc, FAR char **argv) /* And begin reception of files */ - ret = zmr_receive(handle); + ret = zmr_receive(handle, pathname); if (ret < 0) { fprintf(stderr, "ERROR: File reception failed: %d\n", ret); diff --git a/system/zmodem/zm.h b/system/zmodem/zm.h index 0c309c79e..2537bd93a 100644 --- a/system/zmodem/zm.h +++ b/system/zmodem/zm.h @@ -229,8 +229,8 @@ */ #ifdef CONFIG_DEBUG_ZMODEM -# define zmprintf(format, ...) fprintf(stderr, format, ##__VA_ARGS__) -# define zmdbg(format, ...) fprintf(stderr, EXTRA_FMT format EXTRA_ARG, ##__VA_ARGS__) +# 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 # ifdef CONFIG_CPP_HAVE_VARARGS @@ -379,6 +379,7 @@ struct zmr_state_s #endif uint8_t ntimeouts; /* Number of timeouts */ uint32_t crc; /* Remove file CRC */ + FAR const char *pathname; /* Local pathname */ FAR char *filename; /* Local filename */ FAR char *attn; /* Attention string received from remote peer */ off_t offset; /* Current file offset */ @@ -804,7 +805,7 @@ int zm_timerrelease(FAR struct zm_state_s *pzm); ****************************************************************************/ #ifdef CONFIG_SYSTEM_ZMODEM_DUMPBUFFER -void zm_dumpbuffer(FAR const char *msg, FAR const void *buffer, size_t buflen); +# define zm_dumpbuffer(m,b,s) lib_dumpbuffer(m,b,s) #else # define zm_dumpbuffer(m,b,s) #endif diff --git a/system/zmodem/zm_dumpbuffer.c b/system/zmodem/zm_dumpbuffer.c deleted file mode 100644 index d26f5f659..000000000 --- a/system/zmodem/zm_dumpbuffer.c +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** - * apps/system/zmodem/zm_dumpbuffer.c - * - * Copyright (C) 2013 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include - -#include "zm.h" - -#ifdef CONFIG_SYSTEM_ZMODEM_DUMPBUFFER - -/**************************************************************************** - * Pre-processor definitions - ****************************************************************************/ - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: zm_dumpbuffer - * - * Description: - * Dump a buffer of zmodem data. - * - ****************************************************************************/ - -void zm_dumpbuffer(FAR const char *msg, FAR const void *buffer, size_t buflen) -{ - FAR const uint8_t *ptr = (FAR const uint8_t *)buffer; - size_t i; - int j, k; - - zmprintf("%s [%p]:\n", msg, ptr); - for (i = 0; i < buflen; i += 32) - { - zmprintf("%04x: ", i); - for (j = 0; j < 32; j++) - { - k = i + j; - - if (j == 16) - { - zmprintf(" "); - } - - if (k < buflen) - { - zmprintf("%02x", ptr[k]); - } - else - { - zmprintf(" "); - } - } - - zmprintf(" "); - for (j = 0; j < 32; j++) - { - k = i + j; - - if (j == 16) - { - zmprintf(" "); - } - - if (k < buflen) - { - if (ptr[k] >= 0x20 && ptr[k] < 0x7f) - { - zmprintf("%c", ptr[k]); - } - else - { - zmprintf("."); - } - } - } - zmprintf("\n"); - } -} - -#endif /* CONFIG_SYSTEM_ZMODEM_DUMPBUFFER */ diff --git a/system/zmodem/zm_receive.c b/system/zmodem/zm_receive.c index ebd79428c..7ad0a24e3 100644 --- a/system/zmodem/zm_receive.c +++ b/system/zmodem/zm_receive.c @@ -381,7 +381,7 @@ static int zmr_startto(FAR struct zm_state_s *pzm) zmdbg("ZMR_STATE %d: %d timeouts waiting for ZSINIT or ZFILE\n", pzm->state, pzmr->ntimeouts); - if (pzmr->ntimeouts > 4) + if (pzmr->ntimeouts < 4) { /* Send ZRINIT again */ @@ -1144,8 +1144,7 @@ static int zmr_parsefilename(FAR struct zmr_state_s *pzmr, /* Extend the relative path to the file storage directory */ - asprintf(&pzmr->filename, "%s/%s", CONFIG_SYSTEM_ZMODEM_MOUNTPOINT, - namptr); + asprintf(&pzmr->filename, "%s/%s", pzmr->pathname, namptr); if (!pzmr->filename) { zmdbg("ERROR: Failed to allocate full path %s/%s\n", @@ -1616,6 +1615,7 @@ ZMRHANDLE zmr_initialize(int remfd) pzm->pstate = PSTATE_IDLE; pzm->psubstate = PIDLE_ZPAD; pzm->remfd = remfd; + pzmr->rcaps = CANFC32 | CANFDX; pzmr->outfd = -1; /* Create a timer to handle timeout events */ @@ -1645,17 +1645,20 @@ ZMRHANDLE zmr_initialize(int remfd) * Receive file(s) sent from the remote peer. * * Input Parameters: - * handle - The handler created by zmr_initialize(). + * handle - The handler created by zmr_initialize(). + * pathname - The name of the local path to hold the file * * Returned Value: * Zero on success; a negated errno value on failure. * ****************************************************************************/ -int zmr_receive(ZMRHANDLE handle) +int zmr_receive(ZMRHANDLE handle, FAR const char *pathname) { FAR struct zmr_state_s *pzmr = (FAR struct zmr_state_s*)handle; + pzmr->pathname = pathname; + /* The first thing that should happen is to receive ZRQINIT from the * remote sender. This could take while so use a long timeout. */ diff --git a/system/zmodem/zm_send.c b/system/zmodem/zm_send.c index 68106f6fb..b1f27f22d 100644 --- a/system/zmodem/zm_send.c +++ b/system/zmodem/zm_send.c @@ -148,7 +148,6 @@ static int zms_fileskip(FAR struct zm_state_s *pzm); static int zms_sendfiledata(FAR struct zm_state_s *pzm); static int zms_sendpacket(FAR struct zm_state_s *pzm); static int zms_filecrc(FAR struct zm_state_s *pzm); -static int zms_sendack(FAR struct zm_state_s *pzm); static int zms_sendwaitack(FAR struct zm_state_s *pzm); static int zms_sendnak(FAR struct zm_state_s *pzm); static int zms_sendrpos(FAR struct zm_state_s *pzm); @@ -258,7 +257,7 @@ static const struct zm_transition_s g_zms_crcwait[] = static const struct zm_transition_s g_zmr_sending[] = { {ZME_SINIT, false, ZMS_START, zms_attention}, - {ZME_ACK, false, ZMS_SENDING, zms_sendack}, + {ZME_ACK, false, ZMS_SENDING, zms_sendpacket}, {ZME_RPOS, true, ZMS_SENDING, zms_sendrpos}, {ZME_SKIP, true, ZMS_FILEWAIT, zms_fileskip}, {ZME_NAK, true, ZMS_SENDING, zms_sendnak}, @@ -422,7 +421,6 @@ static int zms_zrinit(FAR struct zm_state_s *pzm) /* Set flags associated with the capabilities */ - rcaps &= ~(ZM_FLAG_CRC32 | ZM_FLAG_ESCCTRL); if ((rcaps & CANFC32) != 0) { pzm->flags |= ZM_FLAG_CRC32; @@ -1152,35 +1150,6 @@ static int zms_filecrc(FAR struct zm_state_s *pzm) return zm_sendhexhdr(pzm, ZCRC, by); } -/**************************************************************************** - * Name: zms_sendack - * - * Description: - * An ACK arrived while transmitting data. Update last known receiver - * offset, and try to send more data. - * - ****************************************************************************/ - -static int zms_sendack(FAR struct zm_state_s *pzm) -{ - FAR struct zms_state_s *pzms = (FAR struct zms_state_s *)pzm; - off_t offset; - - /* Paragraph 11.4 ZACK. Acknowledgment to a ZSINIT , ..., ZCRCQ or - * ZCRCW data subpacket. ZP0 to ZP3 contain file offset. - */ - - offset = zm_bytobe32(pzm->hdrdata + 1); - - if (offset > pzms->lastoffs) - { - pzms->lastoffs = offset; - } - - zmdbg("ZMS_STATE %d: offset: %ld\n", pzm->state, (unsigned long)pzms->offset); - return OK; -} - /**************************************************************************** * Name: zms_sendwaitack *