Shearwater: convert predator parser to use generic field interface

This only converts the string fields and the divemode field.

Why? Those were the only ones that were in the proper libdivecomputer
type format: a lot of the other fields are kept in the Shearwater
internal format, and then converted at get_field() time.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2020-02-13 12:26:39 -08:00
parent 0638482209
commit 752bfaab3d

View File

@ -35,6 +35,7 @@
#include "context-private.h"
#include "parser-private.h"
#include "array.h"
#include "field-cache.h"
#define ISINSTANCE(parser) ( \
dc_parser_isinstance((parser), &shearwater_predator_parser_vtable) || \
@ -123,13 +124,12 @@ struct shearwater_predator_parser_t {
unsigned int calibrated;
double calibration[3];
unsigned int serial;
dc_divemode_t mode;
unsigned int units;
unsigned int atmospheric;
unsigned int density;
/* String fields */
dc_field_string_t strings[MAXSTRINGS];
/* Generic field cache */
struct dc_field_cache cache;
};
static dc_status_t shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
@ -233,11 +233,12 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
for (unsigned int i = 0; i < 3; ++i) {
parser->calibration[i] = 0.0;
}
parser->mode = DC_DIVEMODE_OC;
parser->units = METRIC;
parser->density = 1025;
parser->atmospheric = ATM / (BAR / 1000);
DC_ASSIGN_FIELD(parser->cache, DIVEMODE, DC_DIVEMODE_OC);
*out = (dc_parser_t *) parser;
return DC_STATUS_SUCCESS;
@ -290,11 +291,12 @@ shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char
for (unsigned int i = 0; i < 3; ++i) {
parser->calibration[i] = 0.0;
}
parser->mode = DC_DIVEMODE_OC;
parser->units = METRIC;
parser->density = 1025;
parser->atmospheric = ATM / (BAR / 1000);
DC_ASSIGN_FIELD(parser->cache, DIVEMODE, DC_DIVEMODE_OC);
return DC_STATUS_SUCCESS;
}
@ -320,48 +322,6 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d
return DC_STATUS_SUCCESS;
}
/*
* These string cache interfaces should be some generic
* library rather than copied for all the dive computers.
*
* This is just copied from the EON Steel code.
*/
static void
add_string(shearwater_predator_parser_t *parser, const char *desc, const char *value)
{
int i;
for (i = 0; i < MAXSTRINGS; i++) {
dc_field_string_t *str = parser->strings+i;
if (str->desc)
continue;
str->desc = desc;
str->value = strdup(value);
break;
}
}
static void
add_string_fmt(shearwater_predator_parser_t *parser, const char *desc, const char *fmt, ...)
{
char buffer[256];
va_list ap;
/*
* We ignore the return value from vsnprintf, and we
* always NUL-terminate the destination buffer ourselves.
*
* That way we don't have to worry about random bad legacy
* implementations.
*/
va_start(ap, fmt);
buffer[sizeof(buffer)-1] = 0;
(void) vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
va_end(ap);
return add_string(parser, desc, buffer);
}
// Show the battery state
//
// NOTE! Right now it only shows the most serious bit
@ -387,7 +347,7 @@ add_battery_info(shearwater_predator_parser_t *parser, const char *desc, unsigne
"critical", // 110 - warning and critical
"critical", // 111 - normal, warning and critical
};
add_string(parser, desc, states[state]);
dc_field_add_string(&parser->cache, desc, states[state]);
}
}
@ -399,16 +359,16 @@ add_deco_model(shearwater_predator_parser_t *parser, const unsigned char *data)
switch (data[idx_deco_model]) {
case 0:
add_string_fmt(parser, "Deco model", "GF %u/%u", data[4], data[5]);
dc_field_add_string_fmt(&parser->cache, "Deco model", "GF %u/%u", data[4], data[5]);
break;
case 1:
add_string_fmt(parser, "Deco model", "VPM-B +%u", data[idx_deco_model + 1]);
dc_field_add_string_fmt(&parser->cache, "Deco model", "VPM-B +%u", data[idx_deco_model + 1]);
break;
case 2:
add_string_fmt(parser, "Deco model", "VPM-B/GFS +%u %u%%", data[idx_deco_model + 1], data[idx_gfs]);
dc_field_add_string_fmt(&parser->cache, "Deco model", "VPM-B/GFS +%u %u%%", data[idx_deco_model + 1], data[idx_gfs]);
break;
default:
add_string_fmt(parser, "Deco model", "Unknown model %d", data[idx_deco_model]);
dc_field_add_string_fmt(&parser->cache, "Deco model", "Unknown model %d", data[idx_deco_model]);
}
}
@ -421,22 +381,22 @@ add_battery_type(shearwater_predator_parser_t *parser, const unsigned char *data
unsigned int idx_battery_type = parser->pnf ? parser->opening[4] + 9 : 120;
switch (data[idx_battery_type]) {
case 1:
add_string(parser, "Battery type", "1.5V Alkaline");
dc_field_add_string(&parser->cache, "Battery type", "1.5V Alkaline");
break;
case 2:
add_string(parser, "Battery type", "1.5V Lithium");
dc_field_add_string(&parser->cache, "Battery type", "1.5V Lithium");
break;
case 3:
add_string(parser, "Battery type", "1.2V NiMH");
dc_field_add_string(&parser->cache, "Battery type", "1.2V NiMH");
break;
case 4:
add_string(parser, "Battery type", "3.6V Saft");
dc_field_add_string(&parser->cache, "Battery type", "3.6V Saft");
break;
case 5:
add_string(parser, "Battery type", "3.7V Li-Ion");
dc_field_add_string(&parser->cache, "Battery type", "3.7V Li-Ion");
break;
default:
add_string_fmt(parser, "Battery type", "unknown type %d", data[idx_battery_type]);
dc_field_add_string_fmt(&parser->cache, "Battery type", "unknown type %d", data[idx_battery_type]);
break;
}
}
@ -451,7 +411,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
if (parser->cached) {
return DC_STATUS_SUCCESS;
}
memset(parser->strings, 0, sizeof(parser->strings));
memset(&parser->cache, 0, sizeof(parser->cache));
// Log versions before 6 weren't reliably stored in the data, but
// 6 is also the oldest version that we assume in our code
@ -616,7 +576,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
}
}
add_string_fmt(parser, "Logversion", "%d%s", logversion, pnf ? "(PNF)" : "");
dc_field_add_string_fmt(&parser->cache, "Logversion", "%d%s", logversion, pnf ? "(PNF)" : "");
// Cache sensor calibration for later use
unsigned int nsensors = 0, ndefaults = 0;
@ -647,11 +607,11 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
WARNING (abstract->context, "Disabled all O2 sensors due to a default calibration value.");
parser->calibrated = 0;
if (mode != DC_DIVEMODE_OC)
add_string(parser, "PPO2 source", "voted/averaged");
dc_field_add_string(&parser->cache, "PPO2 source", "voted/averaged");
} else {
parser->calibrated = data[base];
if (mode != DC_DIVEMODE_OC)
add_string(parser, "PPO2 source", "cells");
dc_field_add_string(&parser->cache, "PPO2 source", "cells");
}
// Cache the data for later use.
@ -673,18 +633,19 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
parser->tankidx[i] = UNDEFINED;
}
}
parser->mode = mode;
parser->units = data[parser->opening[0] + 8];
parser->atmospheric = array_uint16_be (data + parser->opening[1] + (parser->pnf ? 16 : 47));
parser->density = array_uint16_be (data + parser->opening[3] + (parser->pnf ? 3 : 83));
parser->cached = 1;
add_string_fmt(parser, "Serial", "%08x", parser->serial);
DC_ASSIGN_FIELD(parser->cache, DIVEMODE, mode);
dc_field_add_string_fmt(&parser->cache, "Serial", "%08x", parser->serial);
// bytes 1-31 are identical in all formats
add_string_fmt(parser, "FW Version", "%2x", data[19]);
dc_field_add_string_fmt(&parser->cache, "FW Version", "%2x", data[19]);
add_deco_model(parser, data);
add_battery_type(parser, data);
add_string_fmt(parser, "Battery at end", "%.1f V", data[9] / 10.0);
dc_field_add_string_fmt(&parser->cache, "Battery at end", "%.1f V", data[9] / 10.0);
add_battery_info(parser, "T1 battery", tank[0].battery);
add_battery_info(parser, "T2 battery", tank[1].battery);
@ -754,17 +715,9 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
*((double *) value) = parser->atmospheric / 1000.0;
break;
case DC_FIELD_DIVEMODE:
*((dc_divemode_t *) value) = parser->mode;
break;
return DC_FIELD_VALUE(parser->cache, value, DIVEMODE);
case DC_FIELD_STRING:
if (flags < MAXSTRINGS) {
dc_field_string_t *p = parser->strings + flags;
if (p->desc) {
*string = *p;
break;
}
}
return DC_STATUS_UNSUPPORTED;
return dc_field_get_string(&parser->cache, flags, string);
default:
return DC_STATUS_UNSUPPORTED;
}