From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
To: Robert Jarzmik <robert.jarzmik@free.fr>
Cc: barebox@lists.infradead.org
Subject: Re: [PATCH v2 1/2] commands: change Y-Modem implementation
Date: Sun, 4 Nov 2012 19:36:59 +0100 [thread overview]
Message-ID: <20121104183659.GC29599@game.jcrosoft.org> (raw)
In-Reply-To: <1352051724-16253-1-git-send-email-robert.jarzmik@free.fr>
On 18:55 Sun 04 Nov , Robert Jarzmik wrote:
> The current Y-Modem implementation has some limitations:
> - Y-Modem/G protocol is not supported
> - Multiple files (aka. batch) transfers are not supported
> - Transfer speed over fast lines (USB console) is slow
> - Code is not trivial to maintain (personnal opinion)
>
> This implementation tries to address all these points by
> introducing loady2 command.
>
> The effects are :
> - transfer speed for Y-Modem over USB jumps from 2kBytes/s
> to 180kBytes/s
> - transfer speed for Y-Modem/G jumps to 200kBytes/s
> - multiple file transfers are possible
>
> This command was tested on a USB console and UART 9600bps
> serial line :
> - NAKs (and retransmissions) were tested for faulty
> serial lines
> - multiple file transfers were tested
> - Y-Modem, Y-Modem/G and X-Modem transfers were tested
>
> Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
>
> ---
> Since V1:
> - add input fifo for small fifo hardwares
> Add a FIFO so that each getc will empty the hardware
> FIFO. This is very similar to the generic console code,
> except that the getc won't block each time for 100us,
> enabling faster lines (USB) to benefit their full speed.
> - fix CRC calculation for big endian architectures
> Thanks a lot Antony for the many patches testing !
> - added some documentation
> - amended the split as Sascha recommended
> ---
> commands/Kconfig | 1 +
> commands/Makefile | 2 +-
> commands/loadxy.c | 238 +++++++++++++++++++++
> include/xymodem.h | 25 +++
> lib/Kconfig | 3 +
> lib/Makefile | 1 +
> lib/xymodem.c | 591 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 7 files changed, 860 insertions(+), 1 deletion(-)
> create mode 100644 commands/loadxy.c
> create mode 100644 include/xymodem.h
> create mode 100644 lib/xymodem.c
>
> diff --git a/commands/Kconfig b/commands/Kconfig
> index a52a01a..a7e9974 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -261,6 +261,7 @@ config CMD_LOADB
>
> config CMD_LOADY
> select CRC16
> + select XYMODEM
> tristate
> prompt "loady"
>
> diff --git a/commands/Makefile b/commands/Makefile
> index ff98051..44ad904 100644
> --- a/commands/Makefile
> +++ b/commands/Makefile
> @@ -3,7 +3,7 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
> obj-$(CONFIG_CMD_UIMAGE) += uimage.o
> obj-$(CONFIG_CMD_LINUX16) += linux16.o
> obj-$(CONFIG_CMD_LOADB) += loadb.o xyzModem.o
> -obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o
> +obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o loadxy.o
> obj-$(CONFIG_CMD_LOADS) += loads.o
> obj-$(CONFIG_CMD_ECHO) += echo.o
> obj-$(CONFIG_CMD_MEMORY) += mem.o
> diff --git a/commands/loadxy.c b/commands/loadxy.c
> new file mode 100644
> index 0000000..141bd7b
> --- /dev/null
> +++ b/commands/loadxy.c
> @@ -0,0 +1,238 @@
> +/**
> + * @file
> + * @brief loady and loadx support.
> + *
> + * Provides loadx (over X-Modem) and loady(over Y-Modem) support to download
> + * images.
> + *
> + * FileName: commands/loadxy.c
> + */
> +/*
> + * (C) Copyright 2012 Robert Jarzmik <robert.jarzmik@free.fr>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +/*
> + * Serial up- and download support
> + */
> +#include <common.h>
> +#include <command.h>
> +#include <console.h>
> +#include <xymodem.h>
> +#include <errno.h>
> +#include <getopt.h>
> +#include <fcntl.h>
> +#include <fs.h>
> +#include <malloc.h>
> +
> +#define DEF_FILE "image.bin"
> +
> +/**
> + * @brief returns current used console device
> + *
> + * @return console device which is registered with CONSOLE_STDIN and
> + * CONSOLE_STDOUT
> + */
> +static struct console_device *get_current_console(void)
> +{
> + struct console_device *cdev;
> + /*
> + * Assumption to have BOTH CONSOLE_STDIN AND STDOUT in the
> + * same output console
> + */
> + for_each_console(cdev) {
> + if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT)))
> + return cdev;
> + }
> + return NULL;
> +}
> +
> +static int console_change_speed(struct console_device *cdev, int baudrate)
> +{
> + int current_baudrate;
> +
> + current_baudrate =
> + (int)simple_strtoul(dev_get_param(&cdev->class_dev,
> + "baudrate"), NULL, 10);
> + if (baudrate && baudrate != current_baudrate) {
> + printf("## Switch baudrate from %d to %d bps and press ENTER ...\n",
> + current_baudrate, baudrate);
> + mdelay(50);
> + cdev->setbrg(cdev, baudrate);
> + mdelay(50);
> + }
> + return current_baudrate;
> +}
> +
> +/**
> + * @brief provide the loady(Y-Modem or Y-Modem/G) support
> + *
> + * @param argc number of arguments
> + * @param argv arguments of loady command
> + *
> + * @return success or failure
> + */
> +static int do_loady(int argc, char *argv[])
> +{
> + int is_ymodemg = 0, rc = 0, opt, rcode = 0;
> + int load_baudrate = 0, current_baudrate;
> + struct console_device *cdev = NULL;
> +
> + while ((opt = getopt(argc, argv, "b:g")) > 0) {
> + switch (opt) {
> + case 'b':
> + load_baudrate = (int)simple_strtoul(optarg, NULL, 10);
> + break;
> + case 'g':
> + is_ymodemg = 1;
> + break;
> + default:
> + perror(argv[0]);
> + return 1;
> + }
> + }
> +
> + cdev = get_current_console();
> + if (NULL == cdev) {
this really look wired
if (!cdev)
> + printf("%s:No console device with STDIN and STDOUT\n", argv[0]);
> + return -ENODEV;
> + }
> +
> + current_baudrate = console_change_speed(cdev, load_baudrate);
> + printf("## Ready for binary (ymodem) download at %d bps...\n",
> + load_baudrate ? load_baudrate : current_baudrate);
> +
> + if (is_ymodemg)
> + rc = do_load_serial_ymodemg(cdev);
> + else
> + rc = do_load_serial_ymodem(cdev);
> +
> + if (rc < 0) {
> + printf("## Binary (ymodem) download aborted (%d)\n", rc);
> + rcode = 1;
> + }
> +
> + console_change_speed(cdev, current_baudrate);
> +
> + return rcode;
> +}
> +
> +/**
> + * @brief provide the loadx(X-Modem) support
> + *
> + * @param argc number of arguments
> + * @param argv arguments of loadx command
> + *
> + * @return success or failure
> + */
> +static int do_loadx(int argc, char *argv[])
> +{
> + ulong offset = 0;
> + int load_baudrate = 0, current_baudrate, ofd, opt, rcode = 0;
> + int open_mode = O_WRONLY;
> + char *output_file = NULL;
> + struct console_device *cdev = NULL;
> +
> + while ((opt = getopt(argc, argv, "f:b:o:c")) > 0) {
> + switch (opt) {
> + case 'f':
> + output_file = optarg;
> + break;
> + case 'b':
> + load_baudrate = (int)simple_strtoul(optarg, NULL, 10);
> + break;
> + case 'o':
> + offset = (int)simple_strtoul(optarg, NULL, 10);
> + break;
> + case 'c':
> + open_mode |= O_CREAT;
> + break;
> + default:
> + perror(argv[0]);
> + return 1;
> + }
> + }
> +
> + cdev = get_current_console();
> + if (NULL == cdev) {
ditto
> + printf("%s:No console device with STDIN and STDOUT\n", argv[0]);
> + return -ENODEV;
> + }
> +
> + /* Load Defaults */
> + if (NULL == output_file)
ditto
> + output_file = DEF_FILE;
> +
> + /* File should exist */
> + ofd = open(output_file, open_mode);
> + if (ofd < 0) {
> + perror(argv[0]);
> + return 3;
> + }
> + /* Seek to the right offset */
> + if (offset) {
> + int seek = lseek(ofd, offset, SEEK_SET);
> + if (seek != offset) {
> + close(ofd);
> + ofd = 0;
> + perror(argv[0]);
> + return 4;
> + }
> + }
> +
> + current_baudrate = console_change_speed(cdev, load_baudrate);
> + printf("## Ready for binary (X-Modem) download "
> + "to 0x%08lX offset on %s device at %d bps...\n", offset,
> + output_file, load_baudrate);
> + rcode = do_load_serial_ymodem(cdev);
> + if (rcode < 0) {
> + printf("## Binary (kermit) download aborted (%d)\n", rcode);
> + rcode = 1;
> + }
> + console_change_speed(cdev, current_baudrate);
> +
> + return rcode;
> +}
> +static void xy_flush(struct console_device *cdev, struct kfifo *fifo)
> +{
> + while (cdev->tstc(cdev))
no timeout?
> + cdev->getc(cdev);
> + mdelay(250);
> + while (cdev->tstc(cdev))
ditto
> + cdev->getc(cdev);
> + kfifo_reset(fifo);
> +}
> +
> + */
> +static ssize_t xy_read_block(struct xyz_ctxt *proto, struct xy_block *blk,
> + uint64_t timeout)
> +{
> + ssize_t rc, data_len = 0;
> + unsigned char hdr, seqs[2], crcs[2];
> + int crc = 0, hdr_found = 0;
> + uint64_t start = get_time_ns();
> +
> + while (!hdr_found) {
> + rc = xy_gets(proto->cdev, proto->fifo, &hdr, 1, timeout);
> + xy_dbg("read 0x%x(%c) -> %d\n", hdr, hdr, rc);
> + if (rc < 0)
> + goto out;
> + if (is_timeout(start, timeout))
> + goto timeout;
> + switch (hdr) {
> + case SOH:
> + data_len = 128;
> + hdr_found = 1;
> + proto->total_SOH++;
no capital please
> + break;
> + case STX:
> + data_len = 1024;
> + hdr_found = 1;
boolean
> + proto->total_STX++;
> + break;
> + case CAN:
> + rc = -ECONNABORTED;
> + if (proto->total_CAN++ > MAX_CAN_BEFORE_ABORT)
> + goto out;
> + break;
> + case EOT:
> + rc = 0;
> + blk->len = 0;
> + goto out;
> + default:
> + break;
> + }
> + }
> +
> + blk->seq = 0;
> + rc = xy_gets(proto->cdev, proto->fifo, seqs, 2, timeout);
> + if (rc < 0)
> + goto out;
> + blk->seq = seqs[0];
> + if (255 - seqs[0] != seqs[1])
> + return -EBADMSG;
> +
> + rc = xy_gets(proto->cdev, proto->fifo, blk->buf, data_len, timeout);
> + if (rc < 0)
> + goto out;
> + blk->len = rc;
> +
> + switch (proto->crc_mode) {
> + case CRC_ADD8:
> + rc = xy_gets(proto->cdev, proto->fifo, crcs, 1, timeout);
> + crc = crcs[0];
> + break;
> + case CRC_CRC16:
> + rc = xy_gets(proto->cdev, proto->fifo, crcs, 2, timeout);
> + crc = be16_to_cpu(*(uint16_t *)crcs);
> + break;
> + case CRC_NONE:
> + rc = 0;
> + break;
> + }
> + if (rc < 0)
> + goto out;
> +
> + rc = check_crc(blk->buf, data_len, crc, proto->crc_mode);
> + if (rc < 0)
> + goto out;
> + return data_len;
> +timeout:
> + return -ETIMEDOUT;
> +out:
> + return rc;
> +}
> +
> +static int check_blk_seq(struct xyz_ctxt *proto, struct xy_block *blk,
> + int read_rc)
> +{
> + if (blk->seq == ((proto->next_blk - 1) % 256))
> + return -EALREADY;
> + if (blk->seq != proto->next_blk)
> + return -EILSEQ;
> + return read_rc;
> +}
> +
> +static int parse_first_block(struct xyz_ctxt *proto, struct xy_block *blk)
> +{
> + int filename_len;
> + char *str_num;
> +
> + filename_len = strlen(blk->buf);
> + if (filename_len > blk->len)
> + return -EINVAL;
> + memset(proto->filename, 0, sizeof(proto->filename));
no need just add 0 at the end
> + strncpy(proto->filename, blk->buf, filename_len);
> + str_num = blk->buf + filename_len + 1;
> + strsep(&str_num, " ");
> + proto->file_len = simple_strtoul(blk->buf + filename_len + 1, NULL, 10);
> + return 1;
> +}
Best Regards,
J.
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2012-11-04 18:39 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-01 17:37 [PATCH 0/2] Y-Modem implementation change Robert Jarzmik
2012-11-01 17:37 ` [PATCH 1/2] commands: change Y-Modem implementation Robert Jarzmik
2012-11-01 17:37 ` [PATCH 2/2] commands: remove old " Robert Jarzmik
2012-11-01 17:50 ` [PATCH 0/2] Y-Modem implementation change Jean-Christophe PLAGNIOL-VILLARD
2012-11-01 18:47 ` Antony Pavlov
2012-11-01 19:19 ` Antony Pavlov
2012-11-01 19:57 ` Robert Jarzmik
2012-11-01 19:33 ` Sascha Hauer
2012-11-04 17:55 ` [PATCH v2 1/2] commands: change Y-Modem implementation Robert Jarzmik
2012-11-04 17:55 ` [PATCH v2 2/2] commands: remove old " Robert Jarzmik
2012-11-04 18:36 ` Jean-Christophe PLAGNIOL-VILLARD [this message]
2012-11-05 18:07 ` [PATCH v2 1/2] commands: change " Robert Jarzmik
2012-11-05 18:25 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-05 18:49 ` Robert Jarzmik
2012-11-05 19:49 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-05 21:31 ` Robert Jarzmik
2012-11-06 7:34 ` Jean-Christophe PLAGNIOL-VILLARD
2012-11-06 20:50 ` Robert Jarzmik
2012-11-07 8:22 ` Antony Pavlov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121104183659.GC29599@game.jcrosoft.org \
--to=plagnioj@jcrosoft.com \
--cc=barebox@lists.infradead.org \
--cc=robert.jarzmik@free.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.