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

Note that this particular progress callback - and thus the
display output - will ignore any smaller transfers, i.e. those
that complete in a single loop iteration. In other words:
progress will only be shown if the transfer size requires
multiple chunks to be sent.

Signed-off-by: Bernhard Nortmann <[email protected]>
---
 fel.c      | 17 +++++++++--------
 progress.c | 44 +++++++++++++++++++++++++++++++++++++++-----
 progress.h |  4 ++++
 3 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/fel.c b/fel.c
index ec8c063..aa30fa6 100644
--- a/fel.c
+++ b/fel.c
@@ -1084,6 +1084,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                  Show progress 
bar on larger transfers\n"
                        "\n"
                        "       spl file                        Load and 
execute U-Boot SPL\n"
                        "               If file additionally contains a main 
U-Boot binary\n"
@@ -1134,16 +1135,16 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       if (argc > 1 && (strcmp(argv[1], "--verbose") == 0 ||
-                        strcmp(argv[1], "-v") == 0)) {
-               verbose = 1;
-               argc -= 1;
-               argv += 1;
-       }
-
        while (argc > 1 ) {
                int skip = 1;
-               if (strncmp(argv[1], "hex", 3) == 0 && argc > 3) {
+
+               if (strcmp(argv[1], "--verbose") == 0 ||
+                   strcmp(argv[1], "-v") == 0) {
+                       verbose = true;
+               } else if (strcmp(argv[1], "--progress") == 0 ||
+                          strcmp(argv[1], "-p") == 0) {
+                       set_progress_callback(progress_bar);
+               } 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) {
diff --git a/progress.c b/progress.c
index 85d23a0..f8d7854 100644
--- a/progress.c
+++ b/progress.c
@@ -30,6 +30,23 @@ inline double gettime(void)
        return tv.tv_sec + (double)tv.tv_usec / 1000000.;
 }
 
+/* Private progress state variable(s) */
+
+typedef struct {
+       progress_cb_t callback;
+} progress_private_t;
+
+static progress_private_t progress = {
+       .callback = NULL
+};
+
+/* Exposed functions to manipulate private variables */
+
+void set_progress_callback(progress_cb_t callback)
+{
+       progress.callback = callback;
+}
+
 /*
  * Update progress status, passing information to the callback function.
  * "quick" is an opaque flag that can indicate "small", frequent or
@@ -37,10 +54,27 @@ inline double gettime(void)
  * function, where it might possibly get consideration / special treatment.
  * If you have no use for that, simply always pass 'false'.
  */
-void progress_update(size_t UNUSED(total), size_t UNUSED(done), bool 
UNUSED(quick))
+void progress_update(size_t total, size_t done, bool quick)
 {
-       /*
-        * This is a non-functional placeholder!
-        * It will be replaced in a later patch.
-        */
+       if (progress.callback)
+               progress.callback(total, done, quick);
+}
+
+/* Callback function implementing a simple progress bar written to stdout */
+void progress_bar(size_t total, size_t done, bool quick)
+{
+       static const int WIDTH = 60; /* # of characters to use for progress bar 
*/
+
+       if (quick) return; /* ignore small transfers completing "instantly" */
+
+       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 27e22c5..8718a02 100644
--- a/progress.h
+++ b/progress.h
@@ -29,6 +29,10 @@ typedef void (*progress_cb_t)(size_t total, size_t done, 
bool quick);
 
 double gettime(void);
 
+void set_progress_callback(progress_cb_t callback);
 void progress_update(size_t total, size_t done, bool quick);
 
+/* progress callback implementations for various display styles */
+void progress_bar(size_t total, size_t done, bool quick);
+
 #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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to