garmin: improve on debug log output for unknown fields

Yes, the hexdump was simple, but it was really hard to read, and we can
do so much better, including taking empty data into account, and
formatting it by the actual size of the individual fields.

So this improves on the debug log, so that when we decide to try to
parse new field information, the data will be in a somewhat more legible
format that makes more sense.  And getting rid of the empty fields makes
it much clearer what data might be even remotely interesting.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2018-09-04 17:18:37 -07:00
parent 8f7e29e1f9
commit 41303bbc70

View File

@ -747,6 +747,70 @@ static int traverse_compressed(struct garmin_parser_t *garmin,
return -1; return -1;
} }
static int all_data_inval(const unsigned char *data, int base_type, int len)
{
int base_size = base_type_info[base_type].type_size;
unsigned long long invalid = base_type_info[base_type].type_inval;
while (len > 0) {
unsigned long long val = 0;
memcpy(&val, data, base_size);
if (val != invalid)
return 0;
data += base_size;
len -= base_size;
}
return 1;
}
static void unknown_field(struct garmin_parser_t *garmin, const unsigned char *data,
const char *msg_name, unsigned int field_nr,
int base_type, int len)
{
char buffer[80];
const char *str = (const char *)data;
/* Skip empty strings */
if (base_type == 7 && !*str)
return;
/* Turn non-string data into hex values */
if (base_type != 7) {
int pos = 0;
int base_size = base_type_info[base_type].type_size;
const char *sep = "";
/* Skip empty data */
if (all_data_inval(data, base_type, len))
return;
str = buffer;
while (len > 0) {
long long val;
/* Space + hex + NUL */
int need = 2+base_size*2;
/* The "-4" is because we reserve that " ..\0" at the end */
if (pos + need >= sizeof(buffer)-4) {
strcpy(buffer+pos, " ..");
break;
}
val = 0;
memcpy(&val, data, base_size);
pos += sprintf(buffer+pos, "%s%0*llx", sep, base_size*2, val);
sep = " ";
data += base_size;
len -= base_size;
}
}
DEBUG(garmin->base.context, "%s/%d %s '%s'", msg_name, field_nr, base_type_info[base_type].type_name, str);
}
static int traverse_regular(struct garmin_parser_t *garmin, static int traverse_regular(struct garmin_parser_t *garmin,
const unsigned char *data, unsigned int size, const unsigned char *data, unsigned int size,
unsigned char type, unsigned int *timep) unsigned char type, unsigned int *timep)
@ -766,7 +830,6 @@ static int traverse_regular(struct garmin_parser_t *garmin,
unsigned int field_nr = field[0]; unsigned int field_nr = field[0];
unsigned int len = field[1]; unsigned int len = field[1];
unsigned int base_type = field[2] & 0x7f; unsigned int base_type = field[2] & 0x7f;
static const int base_size_array[] = { 1, 1, 1, 2, 2, 4, 4, 1, 4, 8, 1, 2, 4, 1, 8, 8, 8 };
const struct field_desc *field_desc; const struct field_desc *field_desc;
unsigned int base_size; unsigned int base_size;
@ -787,7 +850,7 @@ static int traverse_regular(struct garmin_parser_t *garmin,
total_len += size; total_len += size;
continue; continue;
} }
base_size = base_size_array[base_type]; base_size = base_type_info[base_type].type_size;
if (len % base_size) { if (len % base_size) {
ERROR(garmin->base.context, "Data traversal size not a multiple of base size (%d vs %d)\n", len, base_size); ERROR(garmin->base.context, "Data traversal size not a multiple of base size (%d vs %d)\n", len, base_size);
return -1; return -1;
@ -827,8 +890,7 @@ static int traverse_regular(struct garmin_parser_t *garmin,
if (field_desc) { if (field_desc) {
field_desc->parse(garmin, base_type, data); field_desc->parse(garmin, base_type, data);
} else { } else {
DEBUG(garmin->base.context, "%s/%d %s", msg_name, field_nr, base_type_info[base_type].type_name); unknown_field(garmin, data, msg_name, field_nr, base_type, len);
HEXDUMP(garmin->base.context, DC_LOGLEVEL_DEBUG, "next", data, len);
} }
data += len; data += len;
@ -920,6 +982,9 @@ traverse_data(struct garmin_parser_t *garmin)
// The data starts with our filename fingerprint. Skip it. // The data starts with our filename fingerprint. Skip it.
if (len < FIT_NAME_SIZE) if (len < FIT_NAME_SIZE)
return DC_STATUS_IO; return DC_STATUS_IO;
DEBUG(garmin->base.context, "file %s", data);
data += FIT_NAME_SIZE; data += FIT_NAME_SIZE;
len -= FIT_NAME_SIZE; len -= FIT_NAME_SIZE;