tools/ftdi_transfer: add help/usage
This commit is contained in:
parent
d2c28febd7
commit
eeb2de8de1
@ -338,7 +338,7 @@ int do_jump(struct ftdi_context * ftdi, const uint32_t dest)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_show_baudrate_error(struct ftdi_context * ftdi, uint32_t rows)
|
int do_show_baudrate_error(struct ftdi_context * ftdi)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
B = (390625 * 4^(1 - n)) / (N + 1)
|
B = (390625 * 4^(1 - n)) / (N + 1)
|
||||||
@ -349,7 +349,8 @@ int do_show_baudrate_error(struct ftdi_context * ftdi, uint32_t rows)
|
|||||||
fprintf(stderr, " ------------|-------------|---------\n");
|
fprintf(stderr, " ------------|-------------|---------\n");
|
||||||
unsigned short value;
|
unsigned short value;
|
||||||
unsigned short index;
|
unsigned short index;
|
||||||
rows = min(rows, 256);
|
//rows = min(rows, 256);
|
||||||
|
const int rows = 256;
|
||||||
for (uint32_t i = 0; i < rows; i++) {
|
for (uint32_t i = 0; i < rows; i++) {
|
||||||
int baud = convert_baudrate_UT_export(dreamcast_rate(0, i), ftdi, &value, &index);
|
int baud = convert_baudrate_UT_export(dreamcast_rate(0, i), ftdi, &value, &index);
|
||||||
if (baud < 0) {
|
if (baud < 0) {
|
||||||
@ -368,13 +369,14 @@ int do_show_baudrate_error(struct ftdi_context * ftdi, uint32_t rows)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_list_baudrates(struct ftdi_context * ftdi, uint32_t rows)
|
int do_list_baudrates(struct ftdi_context * ftdi)
|
||||||
{
|
{
|
||||||
(void)ftdi;
|
(void)ftdi;
|
||||||
|
|
||||||
fprintf(stderr, " scbrr | cks 0 | cks 1 | cks 2 | cks 3\n");
|
fprintf(stderr, " scbrr | cks 0 | cks 1 | cks 2 | cks 3\n");
|
||||||
fprintf(stderr, "---------------------------------------------------------\n");
|
fprintf(stderr, "---------------------------------------------------------\n");
|
||||||
rows = min(rows, 256);
|
//rows = min(rows, 256);
|
||||||
|
const int rows = 256;
|
||||||
for (uint32_t i = 0; i < rows; i++) {
|
for (uint32_t i = 0; i < rows; i++) {
|
||||||
fprintf(stderr, " 0x%02x % 11.2f % 11.2f % 11.2f % 11.2f\n",
|
fprintf(stderr, " 0x%02x % 11.2f % 11.2f % 11.2f % 11.2f\n",
|
||||||
i,
|
i,
|
||||||
@ -662,23 +664,52 @@ enum struct argument_type {
|
|||||||
integer
|
integer
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct usage_example {
|
||||||
|
const char * usage;
|
||||||
|
const char * example;
|
||||||
|
};
|
||||||
|
|
||||||
struct cli_command {
|
struct cli_command {
|
||||||
const char * name;
|
const char * name;
|
||||||
int num_arguments;
|
int num_arguments;
|
||||||
void * func;
|
void * func;
|
||||||
|
bool need_ftdi_init;
|
||||||
|
const struct usage_example * usage_example;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cli_command commands[] = {
|
constexpr struct usage_example read_help = {
|
||||||
{ "read" , 3, (void *)&do_read },
|
"SRC_ADDR READ_SIZE FILENAME",
|
||||||
{ "write" , 2, (void *)&do_write },
|
"0xa5000000 0x800000 ./texture_memory.bin",
|
||||||
{ "jump" , 1, (void *)&do_jump },
|
|
||||||
{ "speed" , 1, (void *)&do_speed },
|
|
||||||
{ "console" , 0, (void *)&do_console },
|
|
||||||
{ "maple_storage_dump" , 0, (void *)&do_maple_storage_dump },
|
|
||||||
{ "list_baudrates" , 1, (void *)&do_list_baudrates },
|
|
||||||
{ "show_baudrate_error", 1, (void *)&do_show_baudrate_error },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr struct usage_example write_help = {
|
||||||
|
"DEST_ADDR FILENAME",
|
||||||
|
"0xac010000 ./program.bin",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr struct usage_example jump_help = {
|
||||||
|
"JUMP_ADDR",
|
||||||
|
"0xac010000",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr struct usage_example speed_help = {
|
||||||
|
"SCBRR",
|
||||||
|
"0x0",
|
||||||
|
};
|
||||||
|
|
||||||
|
void do_help();
|
||||||
|
|
||||||
|
const struct cli_command commands[] = {
|
||||||
|
{ "read" , 3, (void *)&do_read , true, &read_help},
|
||||||
|
{ "write" , 2, (void *)&do_write , true, &write_help},
|
||||||
|
{ "jump" , 1, (void *)&do_jump , true, &jump_help},
|
||||||
|
{ "speed" , 1, (void *)&do_speed , true, &speed_help},
|
||||||
|
{ "console" , 0, (void *)&do_console , true, NULL},
|
||||||
|
{ "maple_storage_dump" , 0, (void *)&do_maple_storage_dump , true, NULL},
|
||||||
|
{ "list_baudrates" , 0, (void *)&do_list_baudrates , false, NULL},
|
||||||
|
{ "show_baudrate_error", 0, (void *)&do_show_baudrate_error , true, NULL},
|
||||||
|
{ "help" , 0, (void *)&do_help , false, NULL},
|
||||||
|
};
|
||||||
constexpr int commands_length = (sizeof (commands)) / (sizeof (commands[0]));
|
constexpr int commands_length = (sizeof (commands)) / (sizeof (commands[0]));
|
||||||
|
|
||||||
typedef int (*func_0_arg)(struct ftdi_context *);
|
typedef int (*func_0_arg)(struct ftdi_context *);
|
||||||
@ -728,9 +759,19 @@ int parse_integer(const char * s, uint32_t * value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void short_help(const struct cli_command * command)
|
||||||
|
{
|
||||||
|
if (commands->usage_example != NULL) {
|
||||||
|
printf("\nusage:\n\n");
|
||||||
|
printf(" %s %s\n\n", command->name, command->usage_example->usage);
|
||||||
|
printf(" %s %s\n\n", command->name, command->usage_example->example);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define CHECK_ARGC(__name__) \
|
#define CHECK_ARGC(__name__) \
|
||||||
if (arg_index >= argc) { \
|
if (arg_index >= argc) { \
|
||||||
fprintf(stderr, "while processing command `%s` expected argument `%s`\n", name, #__name__); \
|
fprintf(stderr, "while processing command `%s` expected argument `%s`\n", name, #__name__); \
|
||||||
|
short_help(&commands[i]); \
|
||||||
return -1; \
|
return -1; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,6 +782,7 @@ int parse_integer(const char * s, uint32_t * value)
|
|||||||
{ int res = parse_integer(__name__##str, &__name__); \
|
{ int res = parse_integer(__name__##str, &__name__); \
|
||||||
if (res < 0) { \
|
if (res < 0) { \
|
||||||
fprintf(stderr, "while processing command `%s` expected integer at `%s`", name, __name__##str); \
|
fprintf(stderr, "while processing command `%s` expected integer at `%s`", name, __name__##str); \
|
||||||
|
short_help(&commands[i]); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} }
|
} }
|
||||||
|
|
||||||
@ -748,7 +790,7 @@ int parse_integer(const char * s, uint32_t * value)
|
|||||||
CHECK_ARGC(__name__); \
|
CHECK_ARGC(__name__); \
|
||||||
const char * __name__ = argv[arg_index++];
|
const char * __name__ = argv[arg_index++];
|
||||||
|
|
||||||
int handle_command(int argc, const char * argv[], struct ftdi_context * ftdi)
|
int handle_command(int argc, const char * argv[], struct ftdi_context * ftdi, bool * ftdi_init_done)
|
||||||
{
|
{
|
||||||
assert(argc >= 1);
|
assert(argc >= 1);
|
||||||
int arg_index = 0;
|
int arg_index = 0;
|
||||||
@ -757,13 +799,20 @@ int handle_command(int argc, const char * argv[], struct ftdi_context * ftdi)
|
|||||||
|
|
||||||
for (int i = 0; i < commands_length; i++) {
|
for (int i = 0; i < commands_length; i++) {
|
||||||
if (strcmp(commands[i].name, name) == 0) {
|
if (strcmp(commands[i].name, name) == 0) {
|
||||||
|
if (!(*ftdi_init_done) && commands[i].need_ftdi_init) {
|
||||||
|
int res;
|
||||||
|
res = init_ftdi_context(ftdi, 0);
|
||||||
|
if (res < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ftdi_init_done = true;
|
||||||
|
}
|
||||||
|
|
||||||
switch (commands[i].num_arguments) {
|
switch (commands[i].num_arguments) {
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
fprintf(stderr, "handle command: %s ()\n", commands[i].name);
|
fprintf(stderr, "handle command: %s ()\n", commands[i].name);
|
||||||
func_0_arg func = (func_0_arg)commands[i].func;
|
func_0_arg func = (func_0_arg)commands[i].func;
|
||||||
fprintf(stderr, "%p\n", &do_console);
|
|
||||||
fprintf(stderr, "%p\n", func);
|
|
||||||
func_ret = func(ftdi);
|
func_ret = func(ftdi);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -829,12 +878,39 @@ int handle_command(int argc, const char * argv[], struct ftdi_context * ftdi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "unknown command `%s`\n", name);
|
fprintf(stderr, "unknown command `%s`\n", name);
|
||||||
|
do_help();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char * argv_0;
|
||||||
|
|
||||||
|
void do_help()
|
||||||
|
{
|
||||||
|
printf("\nusage: %s [command ...]\n\n", argv_0);
|
||||||
|
printf("where [command] is one or more of:\n\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < commands_length; i++) {
|
||||||
|
printf(" %s", commands[i].name);
|
||||||
|
if (commands[i].usage_example != NULL) {
|
||||||
|
printf(" %s", commands[i].usage_example->usage);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("\nexamples for commands that have arguments:\n\n");
|
||||||
|
for (int i = 0; i < commands_length; i++) {
|
||||||
|
if (commands[i].usage_example != NULL) {
|
||||||
|
printf(" %s %s\n", commands[i].name, commands[i].usage_example->example);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\nnote: all integers are given in base 16; the `0x` prefix is optional and may be omitted.\n");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char * argv[])
|
int main(int argc, const char * argv[])
|
||||||
{
|
{
|
||||||
|
argv_0 = argv[0];
|
||||||
|
|
||||||
struct ftdi_context * ftdi;
|
struct ftdi_context * ftdi;
|
||||||
|
bool ftdi_init_done = false;
|
||||||
|
|
||||||
ftdi = ftdi_new();
|
ftdi = ftdi_new();
|
||||||
if (ftdi == 0) {
|
if (ftdi == 0) {
|
||||||
@ -842,17 +918,11 @@ int main(int argc, const char * argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res;
|
|
||||||
res = init_ftdi_context(ftdi, 0);
|
|
||||||
if (res < 0) {
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(argc >= 1);
|
assert(argc >= 1);
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
res = handle_command(argc, argv, ftdi);
|
int res = handle_command(argc, argv, ftdi, &ftdi_init_done);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user