diff --git a/dfu.c b/dfu.c index 718b991..d8d114f 100644 --- a/dfu.c +++ b/dfu.c @@ -30,10 +30,9 @@ #include #include #include -#include "util.h" // -// All DFU based Commands +// USB request types. // #define REQUEST_TYPE_TO_HOST 0xA1 #define REQUEST_TYPE_TO_DEVICE 0x21 @@ -242,7 +241,28 @@ static void erase_block(uint32_t address) wait_dfu_idle(); } -void dfu_init(unsigned vid, unsigned pid, int write_nbytes) +static const char *identify() +{ + static uint8_t data[64]; + + md380_command(0xa2, 0x01); + + int error = libusb_control_transfer(dev, REQUEST_TYPE_TO_HOST, + REQUEST_UPLOAD, 0, 0, data, 64, 0); + if (error < 0) { + fprintf(stderr, "%s: cannot read data: %d: %s\n", + __func__, error, libusb_strerror(error)); + exit(-1); + } + //printf("%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", + //data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], + //data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]); + + get_status(); + return (const char*) data; +} + +const char *dfu_init(uint16_t vid, uint16_t pid) { int error = libusb_init(&ctx); if (error < 0) { @@ -278,31 +298,13 @@ void dfu_init(unsigned vid, unsigned pid, int write_nbytes) // Enter Programming Mode. md380_command(0x91, 0x01); - if (write_nbytes > 0) { - erase_block(0x00000000); - erase_block(0x00010000); - erase_block(0x00020000); - erase_block(0x00030000); - - if (write_nbytes > 256*1024) { - erase_block(0x00110000); - erase_block(0x00120000); - erase_block(0x00130000); - erase_block(0x00140000); - erase_block(0x00150000); - erase_block(0x00160000); - erase_block(0x00170000); - erase_block(0x00180000); - erase_block(0x00190000); - erase_block(0x001a0000); - erase_block(0x001b0000); - erase_block(0x001c0000); - erase_block(0x001d0000); - } - } + // Get device identifier in a static buffer. + const char *ident = identify(); // Zero address. set_address(0x00000000); + + return ident; } void dfu_close() @@ -315,7 +317,31 @@ void dfu_close() } } -void dfu_read_block(int bno, unsigned char *data, int nbytes) +void dfu_erase(int nbytes) +{ + erase_block(0x00000000); + erase_block(0x00010000); + erase_block(0x00020000); + erase_block(0x00030000); + + if (nbytes > 256*1024) { + erase_block(0x00110000); + erase_block(0x00120000); + erase_block(0x00130000); + erase_block(0x00140000); + erase_block(0x00150000); + erase_block(0x00160000); + erase_block(0x00170000); + erase_block(0x00180000); + erase_block(0x00190000); + erase_block(0x001a0000); + erase_block(0x001b0000); + erase_block(0x001c0000); + erase_block(0x001d0000); + } +} + +void dfu_read_block(int bno, uint8_t *data, int nbytes) { if (bno >= 256) bno += 832; @@ -331,7 +357,7 @@ void dfu_read_block(int bno, unsigned char *data, int nbytes) get_status(); } -void dfu_write_block(int bno, unsigned char *data, int nbytes) +void dfu_write_block(int bno, uint8_t *data, int nbytes) { if (bno >= 256) bno += 832; @@ -346,39 +372,3 @@ void dfu_write_block(int bno, unsigned char *data, int nbytes) get_status(); } - -#if 0 -void device_to_file(const char *filename) -{ - FILE *out = fopen(filename, "w"); - if (! out) { - perror(filename); - exit(-1); - } - - int bno; - for (bno=0; bno<832; bno++) { - uint8_t data[1024]; - dfu_read_block(bno, data, 1024); - - if (fwrite(data, 1, 1024, out) != 1024) { - printf("\n"); - fprintf(stderr, "%s: cannot write output image!\n", __func__); - exit(-1); - } - printf("."); - fflush(stdout); - } - printf("\n"); - fclose(out); -} - -int main() -{ - dfu_init(0x0483, 0xdf11, 0); - - device_to_file("output.img"); - - dfu_close(); -} -#endif diff --git a/main.c b/main.c index c606f95..a48f863 100644 --- a/main.c +++ b/main.c @@ -61,7 +61,7 @@ void usage() int main(int argc, char **argv) { - int write_flag = 0, config_flag = 0; + int read_flag = 0, write_flag = 0, config_flag = 0; // Set locale and message catalogs. setlocale(LC_ALL, ""); @@ -77,8 +77,9 @@ int main(int argc, char **argv) copyright = _("Copyright (C) 2018 Serge Vakulenko KK6ABQ"); serial_verbose = 0; for (;;) { - switch (getopt(argc, argv, "vcw")) { + switch (getopt(argc, argv, "vcwr")) { case 'v': ++serial_verbose; continue; + case 'r': ++read_flag; continue; case 'w': ++write_flag; continue; case 'c': ++config_flag; continue; default: @@ -99,20 +100,20 @@ int main(int argc, char **argv) if (write_flag) { // Restore image file to device. - if (argc != 2) + if (argc != 1) usage(); radio_connect(); - radio_read_image(argv[1]); + radio_read_image(argv[0]); radio_print_version(stdout); radio_upload(0); radio_disconnect(); } else if (config_flag) { - if (argc != 2) + if (argc != 1 && argc != 2) usage(); - if (is_file(argv[0])) { + if (argc == 2) { // Apply text config to image file. radio_read_image(argv[0]); radio_print_version(stdout); @@ -125,16 +126,16 @@ int main(int argc, char **argv) radio_download(); radio_print_version(stdout); radio_save_image("backup.img"); - radio_parse_config(argv[1]); + radio_parse_config(argv[0]); radio_upload(1); radio_disconnect(); } - } else { - if (argc != 1) + } else if (read_flag) { + if (argc != 0 && argc != 1) usage(); - if (is_file(argv[0])) { + if (argc == 1) { // Print configuration from image file. // Load image from file. radio_read_image(argv[0]); @@ -161,6 +162,8 @@ int main(int argc, char **argv) radio_print_config(conf, 1); fclose(conf); } + } else { + usage(); } return 0; } diff --git a/md380.c b/md380.c index c603d2b..b635bb2 100644 --- a/md380.c +++ b/md380.c @@ -299,108 +299,22 @@ static void md380_print_version(FILE *out) // Nothing to print. } -// -// Read block of data, up to 64 bytes. -// When start==0, return non-zero on success or 0 when empty. -// When start!=0, halt the program on any error. -// -static int read_block(int fd, int start, unsigned char *data, int nbytes) -{ - unsigned char reply; - int len; - - // Read data. - len = serial_read(fd, data, nbytes); - if (len != nbytes) { - if (start == 0) - return 0; - fprintf(stderr, "Reading block 0x%04x: got only %d bytes.\n", start, len); - exit(-1); - } - - // Get acknowledge. - serial_write(fd, "\x06", 1); - if (serial_read(fd, &reply, 1) != 1) { - fprintf(stderr, "No acknowledge after block 0x%04x.\n", start); - exit(-1); - } - if (reply != 0x06) { - fprintf(stderr, "Bad acknowledge after block 0x%04x: %02x\n", start, reply); - exit(-1); - } - if (serial_verbose) { - printf("# Read 0x%04x: ", start); - print_hex(data, nbytes); - printf("\n"); - } else { - ++radio_progress; - if (radio_progress % 16 == 0) { - fprintf(stderr, "#"); - fflush(stderr); - } - } - return 1; -} - -// -// Write block of data, up to 64 bytes. -// Halt the program on any error. -// Return 0 on error. -// -static int write_block(int fd, int start, const unsigned char *data, int nbytes) -{ - unsigned char reply[64]; - int len; - - serial_write(fd, data, nbytes); - - // Get echo. - len = serial_read(fd, reply, nbytes); - if (len != nbytes) { - fprintf(stderr, "! Echo for block 0x%04x: got only %d bytes.\n", start, len); - return 0; - } - - // Get acknowledge. - if (serial_read(fd, reply, 1) != 1) { - fprintf(stderr, "! No acknowledge after block 0x%04x.\n", start); - return 0; - } - if (reply[0] != 0x06) { - fprintf(stderr, "! Bad acknowledge after block 0x%04x: %02x\n", start, reply[0]); - return 0; - } - if (serial_verbose) { - printf("# Write 0x%04x: ", start); - print_hex(data, nbytes); - printf("\n"); - } else { - ++radio_progress; - if (radio_progress % 16 == 0) { - fprintf(stderr, "#"); - fflush(stderr); - } - } - return 1; -} - // // Read memory image from the device. // static void md380_download() { - int addr; + int bno; - // Wait for the first 8 bytes. - while (read_block(radio_port, 0, &radio_mem[0], 8) == 0) - continue; + for (bno=0; bno