apps/system/zmodem:

- fix error "sz_main.o: No such file or directory"
  - support -p <path> 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
This commit is contained in:
Xiang Xiao 2018-08-23 06:33:39 -06:00 committed by Gregory Nutt
parent bee98898f0
commit ddd86d31ca
8 changed files with 40 additions and 173 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 <filename> [-l nnnn] </dev/ttyS0 >/dev/ttyS0
$ sudo sz <filename> [-l nnnn] [-w nnnn] </dev/ttyS0 >/dev/ttyS0
Where <filename> is the file that you want to send. If -l nnnn is not
specified, then there will likely be packet buffer overflow errors.
Where <filename> 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.

View File

@ -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 <device>: Communication device to use. Default: %s\n",
CONFIG_SYSTEM_ZMODEM_DEVNAME);
fprintf(stderr, "\t-p <path>: 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);

View File

@ -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

View File

@ -1,119 +0,0 @@
/****************************************************************************
* apps/system/zmodem/zm_dumpbuffer.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <stdio.h>
#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 */

View File

@ -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.
*/

View File

@ -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
*