From 9773d34f38157e305778d1c77c6a03979c7e45e2 Mon Sep 17 00:00:00 2001 From: Sergey Gridassov Date: Fri, 10 Dec 2010 15:14:43 +0300 Subject: [PATCH] Implemented transfer progress --- ingenic.c | 45 +++++++++++++++++++++++++---- ingenic.h | 8 +++++- shell.c | 74 +++++++++++++++++++++++++++++++++++++++++++----- shell_internal.h | 1 + 4 files changed, 114 insertions(+), 14 deletions(-) diff --git a/ingenic.c b/ingenic.c index 30164c5..bb5ec24 100644 --- a/ingenic.c +++ b/ingenic.c @@ -34,6 +34,12 @@ #define CPUID(id) ((id) & 0xFFFF) #define CMDSET(id) (((id) & 0xFFFF0000) >> 16) +#define CFGOPT(name, var, exp) { char *str = cfg_getenv(name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", name, #exp); return -1; }; handle->cfg.var = v; } + +#define NOPT(name, var, exp) { char *str = cfg_getenv("NAND_" name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", "NAND_" name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", "NAND_" name, #exp); return -1; }; handle->nand.nand_##var = v; } + +#define CALLBACK(function, ...) if(handle->callbacks && handle->callbacks->function) handle->callbacks->function(__VA_ARGS__, handle->callbacks_data) + typedef struct { void *usb; uint32_t type; @@ -138,8 +144,9 @@ int ingenic_redetect(void *hndl) { handle->type = type; - if(CMDSET(prev) != CMDSET(type) && handle->callbacks && handle->callbacks->cmdset_change) - handle->callbacks->cmdset_change(handle->callbacks_data); + if(CMDSET(prev) != CMDSET(type)) { + CALLBACK(cmdset_change, CMDSET(type)); + } return 0; } @@ -169,10 +176,6 @@ void ingenic_close(void *hndl) { free(handle); } -#define CFGOPT(name, var, exp) { char *str = cfg_getenv(name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", name, #exp); return -1; }; handle->cfg.var = v; } - -#define NOPT(name, var, exp) { char *str = cfg_getenv("NAND_" name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", "NAND_" name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", "NAND_" name, #exp); return -1; }; handle->nand.nand_##var = v; } - int ingenic_rebuild(void *hndl) { HANDLE; @@ -390,6 +393,10 @@ int ingenic_configure_stage2(void *hndl) { int ingenic_load_sdram(void *hndl, void *data, uint32_t base, uint32_t size) { HANDLE; + int max = size, value = 0; + + CALLBACK(progress, PROGRESS_INIT, 0, max); + while(size) { int block = size > STAGE2_IOBUF ? STAGE2_IOBUF : size; @@ -419,7 +426,14 @@ int ingenic_load_sdram(void *hndl, void *data, uint32_t base, uint32_t size) { data += block; base += block; size -= block; + value += block; + + CALLBACK(progress, PROGRESS_UPDATE, value, max); + } + + CALLBACK(progress, PROGRESS_FINI, 0, 0); + debug(LEVEL_DEBUG, "Load done\n"); return 0; @@ -505,6 +519,9 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const void *iobuf = malloc(chunk_pages * page_size); int ret = 0; + int value = 0, max = pages; + + CALLBACK(progress, PROGRESS_INIT, 0, max); while(pages > 0) { int chunk = pages < chunk_pages ? pages : chunk_pages; @@ -558,11 +575,17 @@ int ingenic_dump_nand(void *hndl, int cs, int start, int pages, int type, const start += chunk; pages -= chunk; + + value += chunk; + + CALLBACK(progress, PROGRESS_UPDATE, value, max); } free(iobuf); fclose(dest); + CALLBACK(progress, PROGRESS_FINI, 0, 0); + return ret; } @@ -612,6 +635,10 @@ int ingenic_program_nand(void *hndl, int cs, int start, int type, const char *fi debug(LEVEL_INFO, "Programming %d pages from %d (%d bytes, %d bytes/page)\n", pages, start, file_size, page_size); + int value = 0, max = pages; + + CALLBACK(progress, PROGRESS_INIT, 0, max); + while(pages > 0) { int chunk = pages < chunk_pages ? pages : chunk_pages; int bytes = chunk * page_size; @@ -658,10 +685,15 @@ int ingenic_program_nand(void *hndl, int cs, int start, int type, const char *fi start += chunk; pages -= chunk; + value += chunk; + + CALLBACK(progress, PROGRESS_UPDATE, value, max); } free(iobuf); fclose(in); + + CALLBACK(progress, PROGRESS_FINI, 0, 0); return ret; } @@ -688,3 +720,4 @@ int ingenic_load_nand(void *hndl, int cs, int start, int pages, uint32_t base) { return 0; } + diff --git a/ingenic.h b/ingenic.h index 5e6b25c..8c09d5f 100644 --- a/ingenic.h +++ b/ingenic.h @@ -54,6 +54,10 @@ #define NO_OOB 2 #define NAND_RAW (1 << 7) +#define PROGRESS_INIT 0 +#define PROGRESS_UPDATE 1 +#define PROGRESS_FINI 2 + typedef struct { /* debug args */ uint8_t debug_ops; @@ -111,8 +115,10 @@ typedef struct { uint8_t plane; } nand_info_t; + typedef struct { - void (*cmdset_change)(void *arg); + void (*cmdset_change)(uint32_t cmdset, void *arg); + void (*progress)(int action, int value, int max, void *arg); } ingenic_callbacks_t; void *ingenic_open(void *usb_hndl); diff --git a/shell.c b/shell.c index 24a937f..41b49c5 100644 --- a/shell.c +++ b/shell.c @@ -26,15 +26,18 @@ #include #include #include +#include #include "shell_internal.h" #include "debug.h" #include "ingenic.h" -static void shell_update_cmdset(void *arg); +static void shell_update_cmdset(uint32_t cmdset, void *arg); +static void shell_progress(int action, int value, int max, void *arg); static const ingenic_callbacks_t shell_callbacks = { shell_update_cmdset, + shell_progress }; static const struct { @@ -60,7 +63,7 @@ shell_context_t *shell_init(void *ingenic) { ingenic_set_callbacks(ingenic, &shell_callbacks, ctx); - shell_update_cmdset(ctx); + shell_update_cmdset(ingenic_cmdset(ingenic), ctx); return ctx; } @@ -424,15 +427,13 @@ void shell_interactive(shell_context_t *ctx) { #endif } -static void shell_update_cmdset(void *arg) { +static void shell_update_cmdset(uint32_t cmdset, void *arg) { shell_context_t *ctx = arg; ctx->set_cmds = NULL; - int set = ingenic_cmdset(ctx->device); - for(int i = 0; cmdsets[i].name != NULL; i++) { - if(cmdsets[i].set == set) { + if(cmdsets[i].set == cmdset) { printf("Shell: using command set '%s', run 'help' for command list. CPU: %04X\n", cmdsets[i].name, ingenic_type(ctx->device)); ctx->set_cmds = cmdsets[i].commands; @@ -441,7 +442,7 @@ static void shell_update_cmdset(void *arg) { } } - debug(LEVEL_ERROR, "Shell: unknown cmdset %d\n", set); + debug(LEVEL_ERROR, "Shell: unknown cmdset %u\n", cmdset); } void *shell_device(shell_context_t *ctx) { @@ -452,3 +453,62 @@ void shell_exit(shell_context_t *ctx, int val) { ctx->shell_exit = val; } +static void shell_progress(int action, int value, int max, void *arg) { + shell_context_t *ctx = arg; + + if(isatty(STDOUT_FILENO)) { + struct winsize size; + + int progress, percent; + + if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) == -1) + return; + + int bar_size = size.ws_col - 6; + + switch(action) { + case PROGRESS_INIT: + ctx->prev_progress = -1; + + + case PROGRESS_FINI: + putchar('\r'); + + for(int i = 0; i < size.ws_col; i++) + putchar(' '); + + putchar('\r'); + + fflush(stdout); + + break; + + case PROGRESS_UPDATE: + progress = value * bar_size / max; + percent = value * 100 / max; + + if(progress != ctx->prev_progress) { + fputs("\r|", stdout); + + for(int i = 0; i < progress; i++) { + putchar('='); + } + + for(int i = progress; i < bar_size; i++) + putchar(' '); + + printf("|%3d%%", percent); + + fflush(stdout); + + ctx->prev_progress = progress; + + } + + + break; + + } + } +} + diff --git a/shell_internal.h b/shell_internal.h index e416c20..0378e26 100644 --- a/shell_internal.h +++ b/shell_internal.h @@ -35,6 +35,7 @@ typedef struct { char *line; const struct shell_command *set_cmds; int shell_exit; + int prev_progress; } shell_context_t;