diff --git a/d868uv.c b/d868uv.c index cffe25f..5596960 100644 --- a/d868uv.c +++ b/d868uv.c @@ -49,6 +49,13 @@ // #define OFFSET_BANK1 0x000040 #define OFFSET_CHAN_BITMAP 0x070a40 +#define OFFSET_SETTINGS 0x071600 +#define OFFSET_RADIOID 0x073d00 + +#define GET_SETTINGS() ((general_settings_t*) &radio_mem[OFFSET_SETTINGS]) +#define GET_RADIOID() ((radioid_t*) &radio_mem[OFFSET_RADIOID]) + +#define VALID_TEXT(txt) (*(txt) != 0 && *(txt) != 0xff) // // Size of memory image. @@ -80,6 +87,49 @@ typedef struct { } channel_t; +// +// General settings: 0x640 bytes at 0x02500000. +// TODO: verify the general settings with official CPS +// +typedef struct { + // Bytes 0-0x5ff. + uint8_t _unused0[0x600]; + + // Bytes 0x600-0x61f + uint8_t intro_line1[16]; // Up to 14 characters + uint8_t intro_line2[16]; // Up to 14 characters + + // Bytes 0x620-0x63f + uint8_t password[16]; // Up to 8 ascii digits + uint8_t _unused630[16]; // 0xff + +} general_settings_t; + +// +// Radio ID table: 250 entries, 0x1f40 bytes at 0x02580000. +// +typedef struct { + // Bytes 0-3. + uint8_t id[4]; // Up to 8 BCD digits +#define GET_ID(x) (((x)[0] >> 4) * 10000000 +\ + ((x)[0] & 15) * 1000000 +\ + ((x)[1] >> 4) * 100000 +\ + ((x)[1] & 15) * 10000 +\ + ((x)[2] >> 4) * 1000 +\ + ((x)[2] & 15) * 100 +\ + ((x)[3] >> 4) * 10 +\ + ((x)[3] & 15)) + // Byte 4. + uint8_t _unused4; // 0 + + // Bytes 5-20 + uint8_t name[16]; // Name + + // Bytes 21-31 + uint8_t _unused21[11]; // 0 + +} radioid_t; + // // Print a generic information about the device. // @@ -147,7 +197,8 @@ static void d868uv_upload(radio_device_t *radio, int cont_flag) unsigned file_offset = 0; unsigned last_printed = 0; - for (f=region_map; f->length; f++) { + // Skip first region. + for (f=region_map+1; f->length; f++) { unsigned addr = f->address; unsigned nbytes = f->length; @@ -180,6 +231,43 @@ static int d868uv_is_compatible(radio_device_t *radio) return 1; } +static void print_id(FILE *out, int verbose) +{ + radioid_t *ri = GET_RADIOID(); + unsigned id = GET_ID(ri->id); + + if (verbose) + fprintf(out, "\n# Unique DMR ID and name of this radio."); + fprintf(out, "\nID: %u\nName: ", id); + if (VALID_TEXT(ri->name)) { + print_ascii(out, ri->name, 16, 0); + } else { + fprintf(out, "-"); + } + fprintf(out, "\n"); +} + +static void print_intro(FILE *out, int verbose) +{ + general_settings_t *gs = GET_SETTINGS(); + + if (verbose) + fprintf(out, "\n# Text displayed when the radio powers up.\n"); + fprintf(out, "Intro Line 1: "); + if (VALID_TEXT(gs->intro_line1)) { + print_ascii(out, gs->intro_line1, 14, 0); + } else { + fprintf(out, "-"); + } + fprintf(out, "\nIntro Line 2: "); + if (VALID_TEXT(gs->intro_line2)) { + print_ascii(out, gs->intro_line2, 14, 0); + } else { + fprintf(out, "-"); + } + fprintf(out, "\n"); +} + // // Print full information about the device configuration. // @@ -190,6 +278,10 @@ static void d868uv_print_config(radio_device_t *radio, FILE *out, int verbose) d868uv_print_version(radio, out); //TODO + + // General settings. + print_id(out, verbose); + print_intro(out, verbose); } // diff --git a/md380.c b/md380.c index a9d46fe..452fb43 100644 --- a/md380.c +++ b/md380.c @@ -402,7 +402,7 @@ static void md380_upload(radio_device_t *radio, int cont_flag) // static int md380_is_compatible(radio_device_t *radio) { - return 1; + return strncmp("D868UVE", (char*)&radio_mem[0], 7) == 0; } // diff --git a/serial.c b/serial.c index f7f3632..4b2d7e8 100644 --- a/serial.c +++ b/serial.c @@ -617,16 +617,23 @@ const char *serial_identify() { static unsigned char reply[16]; unsigned char ack[3]; + int retry = 0; if (serial_open(dev_path, 115200) < 0) { return 0; } +again: send_recv(CMD_PRG, 7, ack, 3); if (memcmp(ack, CMD_QX, 3) != 0) { - fprintf(stderr, "%s: Wrong PRG acknowledge %02x-%02x-%02x, expected %02x-%02x-%02x\n", - __func__, ack[0], ack[1], ack[2], CMD_QX[0], CMD_QX[1], CMD_QX[2]); - return 0; + if (++retry >= 10) { + fprintf(stderr, "%s: Wrong PRG acknowledge %02x-%02x-%02x, expected %02x-%02x-%02x\n", + __func__, ack[0], ack[1], ack[2], CMD_QX[0], CMD_QX[1], CMD_QX[2]); + return 0; + } + usleep(500000); + tcflush(fd, TCIOFLUSH); + goto again; } // Reply: @@ -634,9 +641,14 @@ const char *serial_identify() // I D 8 6 8 U V E V 1 0 2 send_recv(CMD_PRG2, 1, reply, 16); if (reply[0] != 'I' || reply[15] != CMD_ACK[0]) { - fprintf(stderr, "%s: Wrong PRG2 reply %02x-...-%02x, expected %02x-...-%02x\n", - __func__, reply[0], reply[15], 'I', CMD_ACK[0]); - return 0; + if (++retry >= 10) { + fprintf(stderr, "%s: Wrong PRG2 reply %02x-...-%02x, expected %02x-...-%02x\n", + __func__, reply[0], reply[15], 'I', CMD_ACK[0]); + return 0; + } + usleep(500000); + tcflush(fd, TCIOFLUSH); + goto again; } // Terminate the string. diff --git a/todo-id.diff b/todo-id.diff index e54af01..c72fb2b 100644 --- a/todo-id.diff +++ b/todo-id.diff @@ -15,7 +15,7 @@ * 00071b00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * --00071c00 57 45 4c 43 4f 4d 00 00 00 00 00 00 00 00 00 00 |WELCOM..........| +-00071c00 57 45 4c 43 4f 4d 00 00 00 00 00 00 00 00 00 00 |WELCOM..........| 02500600 -00071c10 41 4e 59 54 4f 4e 45 00 00 00 00 00 00 00 00 00 |ANYTONE.........| +00071c00 4b 4b 36 41 42 51 20 41 42 43 44 45 46 47 00 00 |KK6ABQ ABCDEFG..| +00071c10 53 45 52 47 45 59 20 4b 4c 4d 4e 4f 50 51 00 00 |SERGEY KLMNOPQ..| @@ -26,7 +26,7 @@ 00071dd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00071de0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * --00073d00 12 34 56 78 00 4d 79 20 52 61 64 69 6f 00 00 00 |.4Vx.My Radio...| +-00073d00 12 34 56 78 00 4d 79 20 52 61 64 69 6f 00 00 00 |.4Vx.My Radio...| 02580000 -00073d10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00073d00 03 11 45 42 00 4b 4b 36 41 42 51 61 62 63 64 65 |..EB.KK6ABQabcde| +00073d10 66 67 68 69 6a 00 00 00 00 00 00 00 00 00 00 00 |fghij...........|