Commit 3f0584aa authored by Bernhard Nortmann's avatar Bernhard Nortmann
Browse files

fel: implement simple progress bar for larger transfers

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: default avatarBernhard Nortmann <bernhard.nortmann@web.de>
Reviewed-by: default avatarSiarhei Siamashka <siarhei.siamashka@gmail.com>
parent 447eb661
......@@ -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",
......
......@@ -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)
{
/*
* This is a non-functional placeholder!
* It will be replaced in a later patch.
*/
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)
{
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);
}
......@@ -28,6 +28,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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment