[PATCH] Fix up o2 pressure sensor handling at load time

Linus Torvalds torvalds at linux-foundation.org
Fri Jul 21 14:15:58 PDT 2017


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Fri, 21 Jul 2017 13:37:34 -0700
Subject: [PATCH] Fix up o2 pressure sensor handling at load time

Because of how we traditionally did things, the "o2pressure" parsing
depends on implicitly setting the sensor index to the last cylinder that
was marked as being used for oxygen.

We also always defaulted the primary sensor (which is used for the
diluent tank for CCR) to cylinder 0, but that doesn't work when the
oxygen tank is cylinder 0.

This gets that right at file loading time, and unifies the xml and git
sample parsing to make them match. The new defaults are:

 - unless anything else is explicitly specified, the primary sensor is
   associated with the first tank, and the secondary sensor is
   associated with the second tank

 - if we're a CCR dive, and have an explicit oxygen tank, we associate
   the secondary sensor with that oxygen cylinder.  The primary sensor
   will be switched over to the second cylinder if the oxygen cylinder
   is the first one.

   This may sound backwards, but matches our traditional behavior where
   the O2 pressure was the secondary pressure.

This is definitely not pretty, but it gets our historical files working
right, and is at least reasonably sensible.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

Thanks to Willem for his test-data - this fixes a new issue, but also an 
older issue with CCR sensor data. So it's really strictly a regression fix 
for my sensor handling updates: it's a fix for the fact that our sensor 
index code was never right for CCR dives (except occasionally by pure 
luck), and the new generalized code showed some of those issues more.

 core/load-git.c  | 22 ++++++++++++++++------
 core/parse-xml.c | 57 ++++++++++++++++++++++++++++++++++----------------------
 core/save-git.c  | 16 ++++++++++++++--
 core/save-xml.c  | 16 ++++++++++++++--
 4 files changed, 79 insertions(+), 32 deletions(-)

diff --git a/core/load-git.c b/core/load-git.c
index 87f6ecb2..6a3cc75c 100644
--- a/core/load-git.c
+++ b/core/load-git.c
@@ -354,6 +354,7 @@ static char *parse_keyvalue_entry(void (*fn)(void *, const char *, const char *)
 }
 
 static int cylinder_index, weightsystem_index;
+static int o2pressure_sensor;
 
 static void parse_cylinder_keyvalue(void *_cylinder, const char *key, const char *value)
 {
@@ -397,7 +398,6 @@ static void parse_dive_cylinder(char *line, struct membuffer *str, void *_dive)
 	struct dive *dive = _dive;
 	cylinder_t *cylinder = dive->cylinder + cylinder_index;
 
-	cylinder_index++;
 	cylinder->type.description = get_utf8(str);
 	for (;;) {
 		char c;
@@ -407,6 +407,9 @@ static void parse_dive_cylinder(char *line, struct membuffer *str, void *_dive)
 			break;
 		line = parse_keyvalue_entry(parse_cylinder_keyvalue, cylinder, line);
 	}
+	if (cylinder->cylinder_use == OXYGEN)
+		o2pressure_sensor = cylinder_index;
+	cylinder_index++;
 }
 
 static void parse_weightsystem_keyvalue(void *_ws, const char *key, const char *value)
@@ -540,11 +543,6 @@ static void parse_sample_keyvalue(void *_sample, const char *key, const char *va
 	}
 	if (!strcmp(key, "o2pressure")) {
 		pressure_t p = get_pressure(value);
-		//
-		// FIXME!!! What's the O2 cylinder index?
-		// get_cylinder_idx_by_use(dive, OXYGEN)
-		//
-		sample->sensor[1] = 1;
 		sample->pressure[1].mbar = p.mbar;
 		return;
 	}
@@ -599,6 +597,13 @@ static char *parse_sample_unit(struct sample *sample, double val, char *unit)
  * missing sample pressure doesn't mean "same as last
  * time", but "interpolate". We clear those ones
  * explicitly.
+ *
+ * NOTE! We default sensor use to 0, 1 respetively for
+ * the two sensors, but for CCR dives with explicit
+ * OXYGEN bottles we set the secondary sensor to that.
+ * Then the primary sensor will be either the first
+ * or the second cylinder depending on what isn't an
+ * oxygen cylinder.
  */
 static struct sample *new_sample(struct divecomputer *dc)
 {
@@ -606,6 +611,10 @@ static struct sample *new_sample(struct divecomputer *dc)
 	if (sample != dc->sample) {
 		memcpy(sample, sample-1, sizeof(struct sample));
 		sample->pressure[0].mbar = 0;
+		sample->pressure[1].mbar = 0;
+	} else {
+		sample->sensor[0] = !o2pressure_sensor;
+		sample->sensor[1] = o2pressure_sensor;
 	}
 	return sample;
 }
@@ -1502,6 +1511,7 @@ static int parse_dive_entry(git_repository *repo, const git_tree_entry *entry, c
 	if (*suffix)
 		dive->number = atoi(suffix+1);
 	cylinder_index = weightsystem_index = 0;
+	o2pressure_sensor = 1;
 	for_each_line(blob, dive_parser, active_dive);
 	git_blob_free(blob);
 	return 0;
diff --git a/core/parse-xml.c b/core/parse-xml.c
index fdb2dab4..c56a96dd 100644
--- a/core/parse-xml.c
+++ b/core/parse-xml.c
@@ -150,8 +150,8 @@ static bool in_settings = false;
 static bool in_userid = false;
 static struct tm cur_tm;
 static int cur_cylinder_index, cur_ws_index;
-static int lastndl, laststoptime, laststopdepth, lastcns, lastpo2, lastindeco;
-static int lastcylinderindex, lastsensor, lasto2sensor = 1, next_o2_sensor;
+static int lastcylinderindex, next_o2_sensor;
+static int o2pressure_sensor;
 static struct extra_data cur_extra_data;
 
 /*
@@ -356,7 +356,7 @@ static void cylinder_use(char *buffer, enum cylinderuse *cyl_use)
 		int use = cylinderuse_from_text(buffer);
 		*cyl_use = use;
 		if (use == OXYGEN)
-			lasto2sensor = cur_cylinder_index;
+			o2pressure_sensor = cur_cylinder_index;
 	}
 }
 
@@ -794,7 +794,6 @@ static void get_cylinderindex(char *buffer, uint8_t *i)
 static void get_sensor(char *buffer, uint8_t *i)
 {
 	*i = atoi(buffer);
-	lastsensor = *i;
 }
 
 static void parse_libdc_deco(char *buffer, struct sample *s)
@@ -1526,9 +1525,7 @@ static void reset_dc_info(struct divecomputer *dc)
 {
 	/* WARN: reset dc info does't touch the dc? */
 	(void) dc;
-	lastcns = lastpo2 = lastndl = laststoptime = laststopdepth = lastindeco = 0;
-	lastsensor = lastcylinderindex = 0;
-	lasto2sensor = 1;
+	lastcylinderindex = 0;
 }
 
 static void reset_dc_settings(void)
@@ -1606,6 +1603,7 @@ static void dive_start(void)
 		add_dive_to_trip(cur_dive, cur_trip);
 		cur_dive->tripflag = IN_TRIP;
 	}
+	o2pressure_sensor = 1;
 }
 
 static void dive_end(void)
@@ -1714,17 +1712,38 @@ static void ws_end(void)
 	cur_ws_index++;
 }
 
+/*
+ * By default the sample data does not change unless the
+ * save-file gives an explicit new value. So we copy the
+ * data from the previous sample if one exists, and then
+ * the parsing will update it as necessary.
+ *
+ * There are a few exceptions, like the sample pressure:
+ * missing sample pressure doesn't mean "same as last
+ * time", but "interpolate". We clear those ones
+ * explicitly.
+ *
+ * NOTE! We default sensor use to 0, 1 respetively for
+ * the two sensors, but for CCR dives with explicit
+ * OXYGEN bottles we set the secondary sensor to that.
+ * Then the primary sensor will be either the first
+ * or the second cylinder depending on what isn't an
+ * oxygen cylinder.
+ */
 static void sample_start(void)
 {
-	cur_sample = prepare_sample(get_dc());
-	cur_sample->ndl.seconds = lastndl;
-	cur_sample->in_deco = lastindeco;
-	cur_sample->stoptime.seconds = laststoptime;
-	cur_sample->stopdepth.mm = laststopdepth;
-	cur_sample->cns = lastcns;
-	cur_sample->setpoint.mbar = lastpo2;
-	cur_sample->sensor[0] = lastsensor;
-	cur_sample->sensor[1] = lasto2sensor;
+	struct divecomputer *dc = get_dc();
+	struct sample *sample = prepare_sample(dc);
+
+	if (sample != dc->sample) {
+		memcpy(sample, sample-1, sizeof(struct sample));
+		sample->pressure[0].mbar = 0;
+		sample->pressure[1].mbar = 0;
+	} else {
+		sample->sensor[0] = !o2pressure_sensor;
+		sample->sensor[1] = o2pressure_sensor;
+	}
+	cur_sample = sample;
 	next_o2_sensor = 0;
 }
 
@@ -1734,12 +1753,6 @@ static void sample_end(void)
 		return;
 
 	finish_sample(get_dc());
-	lastndl = cur_sample->ndl.seconds;
-	lastindeco = cur_sample->in_deco;
-	laststoptime = cur_sample->stoptime.seconds;
-	laststopdepth = cur_sample->stopdepth.mm;
-	lastcns = cur_sample->cns;
-	lastpo2 = cur_sample->setpoint.mbar;
 	cur_sample = NULL;
 }
 
diff --git a/core/save-git.c b/core/save-git.c
index 2647b88a..b734f59f 100644
--- a/core/save-git.c
+++ b/core/save-git.c
@@ -321,10 +321,22 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl
 	put_format(b, "\n");
 }
 
-static void save_samples(struct membuffer *b, int nr, struct sample *s)
+static void save_samples(struct membuffer *b, struct dive *dive, struct divecomputer *dc)
 {
+	int nr;
+	int o2sensor;
+	struct sample *s;
 	struct sample dummy = {};
 
+	/* Set up default pressure sensor indexes */
+	o2sensor = get_cylinder_idx_by_use(dive, OXYGEN);
+	if (o2sensor < 0)
+		o2sensor = 1;
+	dummy.sensor[0] = !o2sensor;
+	dummy.sensor[1] = o2sensor;
+
+	s = dc->sample;
+	nr = dc->samples;
 	while (--nr >= 0) {
 		save_sample(b, s, &dummy);
 		s++;
@@ -379,7 +391,7 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
 
 	save_extra_data(b, dc->extra_data);
 	save_events(b, dive, dc->events);
-	save_samples(b, dc->samples, dc->sample);
+	save_samples(b, dive, dc);
 }
 
 /*
diff --git a/core/save-xml.c b/core/save-xml.c
index 151ebf0a..73a00f54 100644
--- a/core/save-xml.c
+++ b/core/save-xml.c
@@ -331,10 +331,22 @@ static void show_date(struct membuffer *b, timestamp_t when)
 		   tm.tm_hour, tm.tm_min, tm.tm_sec);
 }
 
-static void save_samples(struct membuffer *b, int nr, struct sample *s)
+static void save_samples(struct membuffer *b, struct dive *dive, struct divecomputer *dc)
 {
+	int nr;
+	int o2sensor;
+	struct sample *s;
 	struct sample dummy = {};
 
+	/* Set up default pressure sensor indexes */
+	o2sensor = get_cylinder_idx_by_use(dive, OXYGEN);
+	if (o2sensor < 0)
+		o2sensor = 1;
+	dummy.sensor[0] = !o2sensor;
+	dummy.sensor[1] = o2sensor;
+
+	s = dc->sample;
+	nr = dc->samples;
 	while (--nr >= 0) {
 		save_sample(b, s, &dummy);
 		s++;
@@ -368,7 +380,7 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
 	put_duration(b, dc->surfacetime, "  <surfacetime>", " min</surfacetime>\n");
 	save_extra_data(b, dc->extra_data);
 	save_events(b, dive, dc->events);
-	save_samples(b, dc->samples, dc->sample);
+	save_samples(b, dive, dc);
 
 	put_format(b, "  </divecomputer>\n");
 }
-- 
2.13.1.518.g0d864c4df



More information about the subsurface mailing list