Fix -u option for d868uv.
This commit is contained in:
parent
2a91d00f34
commit
08ae731218
189
d868uv.c
189
d868uv.c
@ -321,14 +321,6 @@ typedef struct {
|
|||||||
|
|
||||||
// Bytes 35-38
|
// Bytes 35-38
|
||||||
uint8_t id[4]; // Call ID: BCD coded 8 digits
|
uint8_t id[4]; // Call ID: BCD coded 8 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))
|
|
||||||
#define CONTACT_ID(ct) GET_ID((ct)->id)
|
#define CONTACT_ID(ct) GET_ID((ct)->id)
|
||||||
|
|
||||||
// Byte 39
|
// Byte 39
|
||||||
@ -402,6 +394,24 @@ typedef struct {
|
|||||||
|
|
||||||
} scanlist_t;
|
} scanlist_t;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Entry of callsign map: 8 bytes.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
uint32_t id; // DMR ID
|
||||||
|
uint32_t offset; // Offset in the callsign data blob
|
||||||
|
} callsign_map_t;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sizes of callsign database.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
uint32_t count; // Number of records
|
||||||
|
uint32_t last; // Last address of data blob
|
||||||
|
uint32_t _unused3;
|
||||||
|
uint32_t _unused4;
|
||||||
|
} callsign_sizes_t;
|
||||||
|
|
||||||
static const char *POWER_NAME[] = { "Low", "Mid", "High", "Turbo" };
|
static const char *POWER_NAME[] = { "Low", "Mid", "High", "Turbo" };
|
||||||
static const char *DIGITAL_ADMIT_NAME[] = { "-", "Free", "NColor", "Color" };
|
static const char *DIGITAL_ADMIT_NAME[] = { "-", "Free", "NColor", "Color" };
|
||||||
static const char *ANALOG_ADMIT_NAME[] = { "-", "Free", "Tone", "Tone" };
|
static const char *ANALOG_ADMIT_NAME[] = { "-", "Free", "Tone", "Tone" };
|
||||||
@ -2674,6 +2684,76 @@ static int d868uv_verify_config(radio_device_t *radio)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read and dump the callsign database.
|
||||||
|
//
|
||||||
|
static void read_csv(radio_device_t *radio)
|
||||||
|
{
|
||||||
|
callsign_sizes_t sz = {0};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dump sizes.
|
||||||
|
//
|
||||||
|
serial_read_region(ADDR_CALLDB_SIZE, (uint8_t*) &sz, 16);
|
||||||
|
printf("Sizes:\n");
|
||||||
|
print_hex_addr_data(ADDR_CALLDB_SIZE, (uint8_t*)&sz, sizeof(sz));
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dump callsign map.
|
||||||
|
//
|
||||||
|
unsigned addr = ADDR_CALLDB_LIST;
|
||||||
|
unsigned index;
|
||||||
|
|
||||||
|
printf("Map:\n");
|
||||||
|
for (index = 0; index < sz.count; index += 16000) {
|
||||||
|
unsigned n = (sz.count - index) * 8;
|
||||||
|
if (n > 128000)
|
||||||
|
n = 128000;
|
||||||
|
|
||||||
|
uint8_t map[128000];
|
||||||
|
serial_read_region(addr, map, n);
|
||||||
|
print_hex_addr_data(addr, map, n);
|
||||||
|
addr += 256*1024;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dump data.
|
||||||
|
//
|
||||||
|
printf("Data:\n");
|
||||||
|
addr = ADDR_CALLDB_DATA;
|
||||||
|
for (index = 0; index < 10000000; index += 100000) {
|
||||||
|
int n = sz.last - addr;
|
||||||
|
if (n < 0)
|
||||||
|
break;
|
||||||
|
else if (n > 100000)
|
||||||
|
n = 100000;
|
||||||
|
else
|
||||||
|
n = (n + 15) & ~15; // align
|
||||||
|
|
||||||
|
uint8_t data[100000];
|
||||||
|
serial_read_region(addr, data, n);
|
||||||
|
print_hex_addr_data(addr, data, n);
|
||||||
|
addr += 256*1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sorting callback for callsign map.
|
||||||
|
//
|
||||||
|
static int compare_callsign_map(const void *ap, const void *bp)
|
||||||
|
{
|
||||||
|
uint32_t a = *(uint32_t*) ap;
|
||||||
|
uint32_t b = *(uint32_t*) bp;
|
||||||
|
|
||||||
|
if (a < b)
|
||||||
|
return -1;
|
||||||
|
if (a > b)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write CSV file to the callsign database.
|
// Write CSV file to the callsign database.
|
||||||
//
|
//
|
||||||
@ -2707,17 +2787,8 @@ static int d868uv_verify_config(radio_device_t *radio)
|
|||||||
//
|
//
|
||||||
static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
||||||
{
|
{
|
||||||
struct {
|
callsign_map_t map[NCALLSIGNS];
|
||||||
uint32_t id;
|
callsign_sizes_t sz = {0};
|
||||||
uint32_t offset;
|
|
||||||
} map[NCALLSIGNS];
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint32_t count;
|
|
||||||
uint32_t last;
|
|
||||||
uint32_t unused3;
|
|
||||||
uint32_t unused4;
|
|
||||||
} sz = {0};
|
|
||||||
|
|
||||||
// Allocate data.
|
// Allocate data.
|
||||||
char *data = malloc(CALLSIGN_SIZE);
|
char *data = malloc(CALLSIGN_SIZE);
|
||||||
@ -2725,7 +2796,7 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
fprintf(stderr, "Out of memory!\n");
|
fprintf(stderr, "Out of memory!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(data, 0xff, CALLSIGN_SIZE);
|
memset(data, 0, CALLSIGN_SIZE);
|
||||||
memset(map, 0xff, sizeof(map));
|
memset(map, 0xff, sizeof(map));
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -2742,15 +2813,26 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
unsigned nbytes = 0;
|
unsigned nbytes = 0;
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), csv)) {
|
while (fgets(line, sizeof(line), csv)) {
|
||||||
|
trim_spaces(line, 255);
|
||||||
if (line[0] < '0' || line[0] > '9') {
|
if (line[0] < '0' || line[0] > '9') {
|
||||||
|
// Eastern egg: when file contains a line "dump",
|
||||||
|
// read the callsign database from the radio
|
||||||
|
// and save to a file.
|
||||||
|
if (strcmp(line, "dump") == 0) {
|
||||||
|
free(data);
|
||||||
|
read_csv(radio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Skip header.
|
// Skip header.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip trailing spaces and newline.
|
// Replace non-ASCII characters with '?'.
|
||||||
char *e = line + strlen(line) - 1;
|
char *p;
|
||||||
while (e >= line && (*e=='\n' || *e=='\r' || *e==' ' || *e=='\t'))
|
for (p=line; *p; p++) {
|
||||||
*e-- = 0;
|
if (*p < ' ' || *p > '~')
|
||||||
|
*p = '?';
|
||||||
|
}
|
||||||
|
|
||||||
char *callsign = strchr(line, ','); if (! callsign) continue; *callsign++ = 0;
|
char *callsign = strchr(line, ','); if (! callsign) continue; *callsign++ = 0;
|
||||||
char *name = strchr(callsign, ','); if (! name) continue; *name++ = 0;
|
char *name = strchr(callsign, ','); if (! name) continue; *name++ = 0;
|
||||||
@ -2758,6 +2840,14 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
char *state = strchr(city, ','); if (! state) continue; *state++ = 0;
|
char *state = strchr(city, ','); if (! state) continue; *state++ = 0;
|
||||||
char *country = strchr(state, ','); if (! country) continue; *country++ = 0;
|
char *country = strchr(state, ','); if (! country) continue; *country++ = 0;
|
||||||
char *remarks = strchr(country, ','); if (! remarks) continue; *remarks++ = 0;
|
char *remarks = strchr(country, ','); if (! remarks) continue; *remarks++ = 0;
|
||||||
|
if ((p = strchr(remarks, ',')) != 0)
|
||||||
|
*p = 0;
|
||||||
|
callsign = trim_spaces(callsign, 16);
|
||||||
|
name = trim_spaces(name, 16);
|
||||||
|
city = trim_spaces(city, 15);
|
||||||
|
state = trim_spaces(state, 16);
|
||||||
|
country = trim_spaces(country, 16);
|
||||||
|
remarks = trim_spaces(remarks, 16);
|
||||||
//printf("%s,%s,%s,%s,%s,%s,%s\n", line, callsign, name, city, state, country, remarks);
|
//printf("%s,%s,%s,%s,%s,%s,%s\n", line, callsign, name, city, state, country, remarks);
|
||||||
|
|
||||||
unsigned id = strtoul(line, 0, 10);
|
unsigned id = strtoul(line, 0, 10);
|
||||||
@ -2773,12 +2863,16 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
fprintf(stderr, "Too many contacts!\n");
|
fprintf(stderr, "Too many contacts!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
map[sz.count].id = id << 1;
|
callsign_map_t *m = &map[sz.count];
|
||||||
map[sz.count].offset = nbytes;
|
|
||||||
sz.count++;
|
sz.count++;
|
||||||
|
m->id = ((id / 10 % 10) << 5) | (id % 10) << 1 |
|
||||||
|
((id / 1000 % 10) << 13) | ((id / 100) % 10) << 9 |
|
||||||
|
((id / 100000 % 10) << 21) | ((id / 10000) % 10) << 17 |
|
||||||
|
((id / 10000000) << 29) | ((id / 1000000) % 10) << 25;
|
||||||
|
m->offset = nbytes;
|
||||||
|
|
||||||
// Fill data.
|
// Fill data.
|
||||||
char *p = &data[nbytes];
|
p = &data[nbytes];
|
||||||
|
|
||||||
// Radio ID.
|
// Radio ID.
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
@ -2798,23 +2892,15 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
|
|
||||||
nbytes = p - data;
|
nbytes = p - data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final delimiter.
|
|
||||||
data[nbytes++] = 0;
|
|
||||||
fprintf(stderr, "Total %d contacts, %d bytes.\n", sz.count, nbytes);
|
fprintf(stderr, "Total %d contacts, %d bytes.\n", sz.count, nbytes);
|
||||||
|
|
||||||
sz.last = ADDR_CALLDB_DATA + (nbytes / 100000) * 256*1024 + (nbytes % 100000);
|
sz.last = ADDR_CALLDB_DATA + (nbytes / 100000) * 256*1024 + (nbytes % 100000);
|
||||||
|
|
||||||
#if 0
|
// Append extra zeroes and align.
|
||||||
printf("Map:\n");
|
nbytes = (nbytes + 63) & ~15;
|
||||||
print_hex((uint8_t*)map, sz.count * sizeof(map[0]));
|
|
||||||
printf("\n\nSizes:\n");
|
// Sort the map by DMR ID.
|
||||||
print_hex((uint8_t*)&sz, sizeof(sz));
|
qsort(map, sz.count, sizeof(map[0]), compare_callsign_map);
|
||||||
printf("\n\nData:\n");
|
|
||||||
print_hex((uint8_t*)data, nbytes);
|
|
||||||
printf("\n");
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (! trace_flag) {
|
if (! trace_flag) {
|
||||||
fprintf(stderr, "Write: ");
|
fprintf(stderr, "Write: ");
|
||||||
@ -2827,12 +2913,21 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
unsigned addr = ADDR_CALLDB_LIST;
|
unsigned addr = ADDR_CALLDB_LIST;
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
|
//#define DUMP_NO_WRITE
|
||||||
|
#ifdef DUMP_NO_WRITE
|
||||||
|
printf("Map:\n");
|
||||||
|
#endif
|
||||||
for (index = 0; index < sz.count; index += 16000) {
|
for (index = 0; index < sz.count; index += 16000) {
|
||||||
unsigned n = (sz.count - index) * 8;
|
unsigned n = (sz.count - index) * 8;
|
||||||
if (n > 128000)
|
if (n > 128000)
|
||||||
n = 128000;
|
n = 128000;
|
||||||
|
|
||||||
|
#ifdef DUMP_NO_WRITE
|
||||||
|
// Dump the data, for debugging purposes.
|
||||||
|
print_hex_addr_data(addr, (uint8_t*) &map[index], n);
|
||||||
|
#else
|
||||||
serial_write_region(addr, (uint8_t*) &map[index], n);
|
serial_write_region(addr, (uint8_t*) &map[index], n);
|
||||||
|
#endif
|
||||||
addr += 256*1024;
|
addr += 256*1024;
|
||||||
|
|
||||||
fprintf(stderr, "#");
|
fprintf(stderr, "#");
|
||||||
@ -2842,20 +2937,30 @@ static void d868uv_write_csv(radio_device_t *radio, FILE *csv)
|
|||||||
//
|
//
|
||||||
// Write sizes.
|
// Write sizes.
|
||||||
//
|
//
|
||||||
|
#ifdef DUMP_NO_WRITE
|
||||||
|
printf("\nSizes:\n");
|
||||||
|
print_hex_addr_data(ADDR_CALLDB_SIZE, (uint8_t*) &sz, 16);
|
||||||
|
#else
|
||||||
serial_write_region(ADDR_CALLDB_SIZE, (uint8_t*) &sz, 16);
|
serial_write_region(ADDR_CALLDB_SIZE, (uint8_t*) &sz, 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write data.
|
// Write data.
|
||||||
//
|
//
|
||||||
addr = ADDR_CALLDB_DATA;
|
addr = ADDR_CALLDB_DATA;
|
||||||
|
#ifdef DUMP_NO_WRITE
|
||||||
|
printf("\nData:\n");
|
||||||
|
#endif
|
||||||
for (index = 0; index < nbytes; index += 100000) {
|
for (index = 0; index < nbytes; index += 100000) {
|
||||||
unsigned n = nbytes - index;
|
unsigned n = nbytes - index;
|
||||||
if (n > 100000)
|
if (n > 100000)
|
||||||
n = 100000;
|
n = 100000;
|
||||||
else
|
|
||||||
n = (n + 15) & ~15; // align
|
|
||||||
|
|
||||||
|
#ifdef DUMP_NO_WRITE
|
||||||
|
print_hex_addr_data(addr, (uint8_t*) &data[index], n);
|
||||||
|
#else
|
||||||
serial_write_region(addr, (uint8_t*) &data[index], n);
|
serial_write_region(addr, (uint8_t*) &data[index], n);
|
||||||
|
#endif
|
||||||
addr += 256*1024;
|
addr += 256*1024;
|
||||||
|
|
||||||
fprintf(stderr, "#");
|
fprintf(stderr, "#");
|
||||||
|
8
serial.c
8
serial.c
@ -605,9 +605,9 @@ static int send_recv(const unsigned char *cmd, int cmdlen,
|
|||||||
// Send command.
|
// Send command.
|
||||||
//
|
//
|
||||||
if (trace_flag > 0) {
|
if (trace_flag > 0) {
|
||||||
fprintf(stderr, "----Send [%d] %x", cmdlen, cmd[0]);
|
fprintf(stderr, "----Send [%d] %02x", cmdlen, cmd[0]);
|
||||||
for (i=1; i<cmdlen; ++i)
|
for (i=1; i<cmdlen; ++i)
|
||||||
fprintf(stderr, "-%x", cmd[i]);
|
fprintf(stderr, "-%02x", cmd[i]);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,9 +631,9 @@ static int send_recv(const unsigned char *cmd, int cmdlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (trace_flag > 0) {
|
if (trace_flag > 0) {
|
||||||
fprintf(stderr, "----Recv [%d] %x", reply_len, response[0]);
|
fprintf(stderr, "----Recv [%d] %02x", reply_len, response[0]);
|
||||||
for (i=1; i<reply_len; ++i)
|
for (i=1; i<reply_len; ++i)
|
||||||
fprintf(stderr, "-%x", response[i]);
|
fprintf(stderr, "-%02x", response[i]);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
39
util.c
39
util.c
@ -103,6 +103,45 @@ void print_hex(const unsigned char *data, int len)
|
|||||||
printf("-%02x", (unsigned char) data[i]);
|
printf("-%02x", (unsigned char) data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_hex_addr_data(unsigned addr, const unsigned char *data, int len)
|
||||||
|
{
|
||||||
|
for (; len >= 16; len -= 16) {
|
||||||
|
printf("%08x: ", addr);
|
||||||
|
print_hex(data, 16);
|
||||||
|
printf("\n");
|
||||||
|
addr += 16;
|
||||||
|
data += 16;
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
printf("%08x: ", addr);
|
||||||
|
print_hex(data, len);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Strip trailing spaces and newline.
|
||||||
|
// Shorten the string in place to a specified limit.
|
||||||
|
//
|
||||||
|
char *trim_spaces(char *line, int limit)
|
||||||
|
{
|
||||||
|
// Strip leading spaces.
|
||||||
|
while (*line==' ' || *line=='\t')
|
||||||
|
line++;
|
||||||
|
|
||||||
|
// Shorten to the limit.
|
||||||
|
unsigned len = strlen(line);
|
||||||
|
if (len > limit)
|
||||||
|
line[limit] = 0;
|
||||||
|
|
||||||
|
// Strip trailing spaces and newlines.
|
||||||
|
char *e = line + strlen(line) - 1;
|
||||||
|
while (e >= line && (*e=='\n' || *e=='\r' || *e==' ' || *e=='\t'))
|
||||||
|
*e-- = 0;
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Delay in milliseconds.
|
// Delay in milliseconds.
|
||||||
//
|
//
|
||||||
|
7
util.h
7
util.h
@ -41,6 +41,13 @@ int trace_flag;
|
|||||||
// Print data in hex format.
|
// Print data in hex format.
|
||||||
//
|
//
|
||||||
void print_hex(const unsigned char *data, int len);
|
void print_hex(const unsigned char *data, int len);
|
||||||
|
void print_hex_addr_data(unsigned addr, const unsigned char *data, int len);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Strip trailing spaces and newline.
|
||||||
|
// Shorten the string in place to a specified limit.
|
||||||
|
//
|
||||||
|
char *trim_spaces(char *line, int limit);
|
||||||
|
|
||||||
//
|
//
|
||||||
// DFU functions.
|
// DFU functions.
|
||||||
|
Loading…
Reference in New Issue
Block a user