From 3446dd512597d538c1c1f337a85225700c965a25 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 12 Sep 2022 16:07:57 -0400 Subject: [PATCH 1/3] fix up sample sensor indexes before fixing up cylinder pressures The cylinder pressure fixup depends on the sample sensors indexes having been fixed. Signed-off-by: Linus Torvalds --- core/dive.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/dive.c b/core/dive.c index ffbd16673..f6ada7534 100644 --- a/core/dive.c +++ b/core/dive.c @@ -1240,12 +1240,12 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc) /* Fix up gas switch events */ fixup_dc_gasswitch(dive, dc); - /* Fix up cylinder pressures based on DC info */ - fixup_dive_pressures(dive, dc); - /* Fix up cylinder ids in pressure sensors */ fixup_dc_sample_sensors(dc, dive->cylinders.nr); + /* Fix up cylinder pressures based on DC info */ + fixup_dive_pressures(dive, dc); + fixup_dc_events(dc); /* Fixup CCR / PSCR dives with o2sensor values, but without no_o2sensors */ From aa50be9cd581f9ba66afebe103c90263b74a6ec0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 20 Sep 2022 09:33:07 -0700 Subject: [PATCH 2/3] Use the right type for sanitize_sensor_id() It returned a 'uint8_t', which clashes pretty badly with NO_SENSOR being -1, and turned it into 255. That then ended up historically working, because before commit 0c84f369c35b ("core: use int16_t for sensor-id") we actually did that everywhere: #define NO_SENSOR ((uint8_t)-1) ... uint8_t sensor[MAX_SENSORS]; but that was changed to #define NO_SENSOR -1 ... int16_t sensor[MAX_SENSORS]; and this helper type became wrong. Just make it return 'int', avoiding any type narrowing issues. Signed-off-by: Linus Torvalds --- core/load-git.c | 2 +- core/parse.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/load-git.c b/core/load-git.c index a5dbf9ccc..0b6d877a6 100644 --- a/core/load-git.c +++ b/core/load-git.c @@ -644,7 +644,7 @@ static char *parse_sample_unit(struct sample *sample, double val, char *unit) /* * If the given cylinder doesn't exist, return NO_SENSOR. */ -static uint8_t sanitize_sensor_id(const struct dive *d, int nr) +static int sanitize_sensor_id(const struct dive *d, int nr) { return d && nr >= 0 && nr < d->cylinders.nr ? nr : NO_SENSOR; } diff --git a/core/parse.c b/core/parse.c index e8161b395..fddcdeff4 100644 --- a/core/parse.c +++ b/core/parse.c @@ -393,7 +393,7 @@ void ws_end(struct parser_state *state) /* * If the given cylinder doesn't exist, return NO_SENSOR. */ -static uint8_t sanitize_sensor_id(const struct dive *d, int nr) +static int sanitize_sensor_id(const struct dive *d, int nr) { return d && nr >= 0 && nr < d->cylinders.nr ? nr : NO_SENSOR; } From 02f158b0c2587e235e7e04a3f8d9c377fb2ede90 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 12 Sep 2022 16:38:22 -0400 Subject: [PATCH 3/3] Fix the dc sensor index fixup fixup_dc_sample_sensors() would make sure that any pressure sensor indexes were in range of the cylinders by just clearing the pressure data if the sensor index was larger than the number of cylinders in the dive. That certainly makes the sensor index data consistent, but at the cost of just dropping the sensor data entirely. Dirk had some cases of odd sensor data (probably because of an older version of subsurface, but possibly due to removing cylinders manually or because of oddities with the downloader for the Atomic Aquatics Cobalt dive computer he used), and when re-saving the dive, the pressure data would magically just get removed due to this. So rewrite the sensor data fixup to strive very hard to avoid throwing pressure sensor data away. The simplest way to do that is to just add the required number of cylinders, and then people can fix up their dives manually by remapping the sensor data. This whole "we clear the pressure data" was at least partly hidden by two things: (1) in the git save format, we don't rewrite dives unless you've changed the dive some way, so old dives stay around with old data in the save until explicitly changed. (2) if you had multiple dive computers, and one dive computer does not have any pressure data but another one does, our profile will use that "other" dive computer pressure data (because often times you might have only one dive computer that is air integrated, but you still want to see the tank pressure when you look at other dive computers - or you have one dive computer give pressure data for your deco bottle, and another for your travel gas etc). So those two facts hid the reality that we had actually cleared the tank sensor data for Dirk's dive with the Atomic Aquatics dive computer, because we'd still see pressure data in the profile, and the git data would still be the old one. Until Dirk renumbered his dives, and the data was rewritten. Signed-off-by: Linus Torvalds --- core/dive.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/core/dive.c b/core/dive.c index f6ada7534..88f4f036e 100644 --- a/core/dive.c +++ b/core/dive.c @@ -1210,17 +1210,41 @@ static void fixup_no_o2sensors(struct divecomputer *dc) } } -static void fixup_dc_sample_sensors(struct divecomputer *dc, int nr_cylinders) +static void fixup_dc_sample_sensors(struct dive *dive, struct divecomputer *dc) { + unsigned long sensor_mask = 0; + for (int i = 0; i < dc->samples; i++) { struct sample *s = dc->sample + i; for (int j = 0; j < MAX_SENSORS; j++) { - if (s->sensor[j] < 0 || s->sensor[j] >= nr_cylinders) { + int sensor = s->sensor[j]; + + // No invalid sensor ID's, please + if (sensor < 0 || sensor > MAX_SENSORS) { s->sensor[j] = NO_SENSOR; s->pressure[j].mbar = 0; + continue; } + + // Don't bother tracking sensors with no data + if (!s->pressure[j].mbar) { + s->sensor[j] = NO_SENSOR; + continue; + } + + // Remember the set of sensors we had + sensor_mask |= 1ul << sensor; } } + + // Ignore the sensors we have cylinders for + sensor_mask >>= dive->cylinders.nr; + + // Do we need to add empty cylinders? + while (sensor_mask) { + add_empty_cylinder(&dive->cylinders); + sensor_mask >>= 1; + } } static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc) @@ -1241,7 +1265,7 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc) fixup_dc_gasswitch(dive, dc); /* Fix up cylinder ids in pressure sensors */ - fixup_dc_sample_sensors(dc, dive->cylinders.nr); + fixup_dc_sample_sensors(dive, dc); /* Fix up cylinder pressures based on DC info */ fixup_dive_pressures(dive, dc);