Add "--progress" option and a progress bar display for FEL transfers. This picks up on a suggestion from Alexander Kaplan and the discussion at https://groups.google.com/forum/#!topic/linux-sunxi/lz0oQBwjex0
Signed-off-by: Bernhard Nortmann <bernhard.nortm...@web.de> --- fel.c | 16 ++++++++++++++-- progress.c | 49 ++++++++++++++++++++++++++++++++++++++++++------- progress.h | 4 ++++ 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/fel.c b/fel.c index 89014d7..595b682 100644 --- a/fel.c +++ b/fel.c @@ -81,7 +81,12 @@ static const int AW_USB_MAX_BULK_SEND = 4 * 1024 * 1024; // 4 MiB per bulk reque void usb_bulk_send(libusb_device_handle *usb, int ep, const void *data, size_t length, bool progress) { - size_t max_chunk = AW_USB_MAX_BULK_SEND; /* maximum chunk size */ + /* + * With no progress notifications, we'll use the maximum chunk size. + * Otherwise, it's useful to lower the size (have more chunks) to get + * more frequent status updates. 128 KiB per request seem suitable. + */ + size_t max_chunk = progress ? 128 * 1024 : AW_USB_MAX_BULK_SEND; size_t chunk; int rc, sent; @@ -1215,6 +1220,7 @@ static int aw_fel_get_endpoint(libusb_device_handle *usb) int main(int argc, char **argv) { + bool pflag_active = false; /* -p switch, causing "write" to output progress */ int rc; libusb_device_handle *handle = NULL; int iface_detached = -1; @@ -1224,6 +1230,7 @@ int main(int argc, char **argv) if (argc <= 1) { printf("Usage: %s [options] command arguments... [command...]\n" " -v, --verbose Verbose logging\n" + " -p, --progress \"write\" transfers show a progress bar\n" "\n" " spl file Load and execute U-Boot SPL\n" " If file additionally contains a main U-Boot binary\n" @@ -1283,7 +1290,11 @@ int main(int argc, char **argv) while (argc > 1 ) { int skip = 1; - if (strncmp(argv[1], "hex", 3) == 0 && argc > 3) { + + if (strcmp(argv[1], "--progress") == 0 || + strcmp(argv[1], "-p") == 0) { + pflag_active = true; + } else if (strncmp(argv[1], "hex", 3) == 0 && argc > 3) { aw_fel_hexdump(handle, strtoul(argv[2], NULL, 0), strtoul(argv[3], NULL, 0)); skip = 3; } else if (strncmp(argv[1], "dump", 4) == 0 && argc > 3) { @@ -1300,6 +1311,7 @@ int main(int argc, char **argv) size_t size; void *buf = load_file(argv[3], &size); uint32_t offset = strtoul(argv[2], NULL, 0); + progress_start(pflag_active ? progress_bar : NULL, size); double elapsed = aw_write_buffer(handle, buf, offset, size, true); if (elapsed > 0) pr_info("%.1f kB written in %.1f sec (speed: %.1f kB/s)\n", diff --git a/progress.c b/progress.c index 9c2a7d4..5b24198 100644 --- a/progress.c +++ b/progress.c @@ -20,8 +20,6 @@ #include <sys/time.h> #include <unistd.h> -#include "common.h" - /* Less reliable than clock_gettime, but does not require linking with -lrt */ inline double gettime(void) { @@ -30,11 +28,48 @@ inline double gettime(void) return tv.tv_sec + (double)tv.tv_usec / 1000000.; } +/* Private progress state variable */ + +typedef struct { + progress_cb_t callback; + size_t total; + size_t done; +} progress_private_t; + +static progress_private_t progress = { + .callback = NULL, +}; + +/* 'External' API */ + +void progress_start(progress_cb_t callback, size_t expected_total) +{ + progress.callback = callback; + progress.total = expected_total; + progress.done = 0; +} + /* Update progress status, passing information to the callback function. */ -void progress_update(size_t UNUSED(bytes_done)) +void progress_update(size_t bytes_done) +{ + progress.done += bytes_done; + if (progress.callback) + progress.callback(progress.total, progress.done); +} + +/* Callback function implementing a simple progress bar written to stdout */ +void progress_bar(size_t total, size_t done) { - /* - * This is a non-functional placeholder! - * It will be replaced in a later patch. - */ + static const int WIDTH = 60; /* # of characters to use for progress bar */ + + float ratio = total > 0 ? (float)done / total : 0; + int i, pos = WIDTH * ratio; + + printf("\r%3.0f%% [", ratio * 100); /* current percentage */ + for (i = 0; i < pos; i++) putchar('='); + for (i = pos; i < WIDTH; i++) putchar(' '); + printf("] "); + + if (done >= total) putchar('\n'); /* output newline when complete */ + fflush(stdout); } diff --git a/progress.h b/progress.h index 360988e..6c4dc7f 100644 --- a/progress.h +++ b/progress.h @@ -29,6 +29,10 @@ typedef void (*progress_cb_t)(size_t total, size_t done); double gettime(void); +void progress_start(progress_cb_t callback, size_t expected_total); void progress_update(size_t bytes_done); +/* progress callback implementations for various display styles */ +void progress_bar(size_t total, size_t done); + #endif /* _SUNXI_TOOLS_PROGRESS_H */ -- 2.4.6 -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.