summaryrefslogtreecommitdiffstats
path: root/subsurface-core/liquivision.c
diff options
context:
space:
mode:
Diffstat (limited to 'subsurface-core/liquivision.c')
-rw-r--r--subsurface-core/liquivision.c420
1 files changed, 0 insertions, 420 deletions
diff --git a/subsurface-core/liquivision.c b/subsurface-core/liquivision.c
deleted file mode 100644
index 9347a724a..000000000
--- a/subsurface-core/liquivision.c
+++ /dev/null
@@ -1,420 +0,0 @@
-#include <string.h>
-
-#include "dive.h"
-#include "divelist.h"
-#include "file.h"
-#include "strndup.h"
-
-// Convert bytes into an INT
-#define array_uint16_le(p) ((unsigned int) (p)[0] \
- + ((p)[1]<<8) )
-#define array_uint32_le(p) ((unsigned int) (p)[0] \
- + ((p)[1]<<8) + ((p)[2]<<16) \
- + ((p)[3]<<24))
-
-struct lv_event {
- time_t time;
- struct pressure {
- int sensor;
- int mbar;
- } pressure;
-};
-
-uint16_t primary_sensor;
-
-static int handle_event_ver2(int code, const unsigned char *ps, unsigned int ps_ptr, struct lv_event *event)
-{
- (void) code;
- (void) ps;
- (void) ps_ptr;
- (void) event;
-
- // Skip 4 bytes
- return 4;
-}
-
-
-static int handle_event_ver3(int code, const unsigned char *ps, unsigned int ps_ptr, struct lv_event *event)
-{
- int skip = 4;
- uint16_t current_sensor;
-
- switch (code) {
- case 0x0002: // Unknown
- case 0x0004: // Unknown
- skip = 4;
- break;
- case 0x0005: // Unknown
- skip = 6;
- break;
- case 0x0007: // Gas
- // 4 byte time
- // 1 byte O2, 1 bye He
- skip = 6;
- break;
- case 0x0008:
- // 4 byte time
- // 2 byte gas set point 2
- skip = 6;
- break;
- case 0x000f:
- // Tank pressure
- event->time = array_uint32_le(ps + ps_ptr);
-
- /* As far as I know, Liquivision supports 2 sensors, own and buddie's. This is my
- * best guess how it is represented. */
-
- current_sensor = array_uint16_le(ps + ps_ptr + 4);
- if (primary_sensor == 0) {
- primary_sensor = current_sensor;
- }
- if (current_sensor == primary_sensor) {
- event->pressure.sensor = 0;
- event->pressure.mbar = array_uint16_le(ps + ps_ptr + 6) * 10; // cb->mb
- } else {
- /* Ignoring the buddy sensor for no as we cannot draw it on the profile.
- event->pressure.sensor = 1;
- event->pressure.mbar = array_uint16_le(ps + ps_ptr + 6) * 10; // cb->mb
- */
- }
- // 1 byte PSR
- // 1 byte ST
- skip = 10;
- break;
- case 0x0010:
- skip = 26;
- break;
- case 0x0015: // Unknown
- skip = 2;
- break;
- default:
- skip = 4;
- break;
- }
-
- return skip;
-}
-
-static void parse_dives (int log_version, const unsigned char *buf, unsigned int buf_size)
-{
- unsigned int ptr = 0;
- unsigned char model;
-
- struct dive *dive;
- struct divecomputer *dc;
- struct sample *sample;
-
- while (ptr < buf_size) {
- int i;
- bool found_divesite = false;
- dive = alloc_dive();
- primary_sensor = 0;
- dc = &dive->dc;
-
- /* Just the main cylinder until we can handle the buddy cylinder porperly */
- for (i = 0; i < 1; i++)
- fill_default_cylinder(&dive->cylinder[i]);
-
- // Model 0=Xen, 1,2=Xeo, 4=Lynx, other=Liquivision
- model = *(buf + ptr);
- switch (model) {
- case 0:
- dc->model = strdup("Xen");
- break;
- case 1:
- case 2:
- dc->model = strdup("Xeo");
- break;
- case 4:
- dc->model = strdup("Lynx");
- break;
- default:
- dc->model = strdup("Liquivision");
- break;
- }
- ptr++;
-
- // Dive location, assemble Location and Place
- unsigned int len, place_len;
- char *location;
- len = array_uint32_le(buf + ptr);
- ptr += 4;
- place_len = array_uint32_le(buf + ptr + len);
-
- if (len && place_len) {
- location = malloc(len + place_len + 4);
- memset(location, 0, len + place_len + 4);
- memcpy(location, buf + ptr, len);
- memcpy(location + len, ", ", 2);
- memcpy(location + len + 2, buf + ptr + len + 4, place_len);
- } else if (len) {
- location = strndup((char *)buf + ptr, len);
- } else if (place_len) {
- location = strndup((char *)buf + ptr + len + 4, place_len);
- }
-
- /* Store the location only if we have one */
- if (len || place_len)
- found_divesite = true;
-
- ptr += len + 4 + place_len;
-
- // Dive comment
- len = array_uint32_le(buf + ptr);
- ptr += 4;
-
- // Blank notes are better than the default text
- if (len && strncmp((char *)buf + ptr, "Comment ...", 11)) {
- dive->notes = strndup((char *)buf + ptr, len);
- }
- ptr += len;
-
- dive->id = array_uint32_le(buf + ptr);
- ptr += 4;
-
- dive->number = array_uint16_le(buf + ptr) + 1;
- ptr += 2;
-
- dive->duration.seconds = array_uint32_le(buf + ptr); // seconds
- ptr += 4;
-
- dive->maxdepth.mm = array_uint16_le(buf + ptr) * 10; // cm->mm
- ptr += 2;
-
- dive->meandepth.mm = array_uint16_le(buf + ptr) * 10; // cm->mm
- ptr += 2;
-
- dive->when = array_uint32_le(buf + ptr);
- ptr += 4;
-
- // now that we have the dive time we can store the divesite
- // (we need the dive time to create deterministic uuids)
- if (found_divesite) {
- dive->dive_site_uuid = find_or_create_dive_site_with_name(location, dive->when);
- free(location);
- }
- //unsigned int end_time = array_uint32_le(buf + ptr);
- ptr += 4;
-
- //unsigned int sit = array_uint32_le(buf + ptr);
- ptr += 4;
- //if (sit == 0xffffffff) {
- //}
-
- dive->surface_pressure.mbar = array_uint16_le(buf + ptr); // ???
- ptr += 2;
-
- //unsigned int rep_dive = array_uint16_le(buf + ptr);
- ptr += 2;
-
- dive->mintemp.mkelvin = C_to_mkelvin((float)array_uint16_le(buf + ptr)/10);// C->mK
- ptr += 2;
-
- dive->maxtemp.mkelvin = C_to_mkelvin((float)array_uint16_le(buf + ptr)/10);// C->mK
- ptr += 2;
-
- dive->salinity = *(buf + ptr); // ???
- ptr += 1;
-
- unsigned int sample_count = array_uint32_le(buf + ptr);
- ptr += 4;
-
- // Sample interval
- unsigned char sample_interval;
- sample_interval = 1;
-
- unsigned char intervals[6] = {1,2,5,10,30,60};
- if (*(buf + ptr) < 6)
- sample_interval = intervals[*(buf + ptr)];
- ptr += 1;
-
- float start_cns = 0;
- unsigned char dive_mode = 0, algorithm = 0;
- if (array_uint32_le(buf + ptr) != sample_count) {
- // Xeo, with CNS and OTU
- start_cns = *(float *) (buf + ptr);
- ptr += 4;
- dive->cns = *(float *) (buf + ptr); // end cns
- ptr += 4;
- dive->otu = *(float *) (buf + ptr);
- ptr += 4;
- dive_mode = *(buf + ptr++); // 0=Deco, 1=Gauge, 2=None
- algorithm = *(buf + ptr++); // 0=ZH-L16C+GF
- sample_count = array_uint32_le(buf + ptr);
- }
- // we aren't using the start_cns, dive_mode, and algorithm, yet
- (void)start_cns;
- (void)dive_mode;
- (void)algorithm;
-
- ptr += 4;
-
- // Parse dive samples
- const unsigned char *ds = buf + ptr;
- const unsigned char *ts = buf + ptr + sample_count * 2 + 4;
- const unsigned char *ps = buf + ptr + sample_count * 4 + 4;
- unsigned int ps_count = array_uint32_le(ps);
- ps += 4;
-
- // Bump ptr
- ptr += sample_count * 4 + 4;
-
- // Handle events
- unsigned int ps_ptr;
- ps_ptr = 0;
-
- unsigned int event_code, d = 0, e;
- struct lv_event event;
-
- // Loop through events
- for (e = 0; e < ps_count; e++) {
- // Get event
- event_code = array_uint16_le(ps + ps_ptr);
- ps_ptr += 2;
-
- if (log_version == 3) {
- ps_ptr += handle_event_ver3(event_code, ps, ps_ptr, &event);
- if (event_code != 0xf)
- continue; // ignore all by pressure sensor event
- } else { // version 2
- ps_ptr += handle_event_ver2(event_code, ps, ps_ptr, &event);
- continue; // ignore all events
- }
- int sample_time, last_time;
- int depth_mm, last_depth, temp_mk, last_temp;
-
- while (true) {
- sample = prepare_sample(dc);
-
- // Get sample times
- sample_time = d * sample_interval;
- depth_mm = array_uint16_le(ds + d * 2) * 10; // cm->mm
- temp_mk = C_to_mkelvin((float)array_uint16_le(ts + d * 2) / 10); // dC->mK
- last_time = (d ? (d - 1) * sample_interval : 0);
-
- if (d == sample_count) {
- // We still have events to record
- sample->time.seconds = event.time;
- sample->depth.mm = array_uint16_le(ds + (d - 1) * 2) * 10; // cm->mm
- sample->temperature.mkelvin = C_to_mkelvin((float) array_uint16_le(ts + (d - 1) * 2) / 10); // dC->mK
- sample->sensor = event.pressure.sensor;
- sample->cylinderpressure.mbar = event.pressure.mbar;
- finish_sample(dc);
-
- break;
- } else if (event.time > sample_time) {
- // Record sample and loop
- sample->time.seconds = sample_time;
- sample->depth.mm = depth_mm;
- sample->temperature.mkelvin = temp_mk;
- finish_sample(dc);
- d++;
-
- continue;
- } else if (event.time == sample_time) {
- sample->time.seconds = sample_time;
- sample->depth.mm = depth_mm;
- sample->temperature.mkelvin = temp_mk;
- sample->sensor = event.pressure.sensor;
- sample->cylinderpressure.mbar = event.pressure.mbar;
- finish_sample(dc);
-
- break;
- } else { // Event is prior to sample
- sample->time.seconds = event.time;
- sample->sensor = event.pressure.sensor;
- sample->cylinderpressure.mbar = event.pressure.mbar;
- if (last_time == sample_time) {
- sample->depth.mm = depth_mm;
- sample->temperature.mkelvin = temp_mk;
- } else {
- // Extrapolate
- last_depth = array_uint16_le(ds + (d - 1) * 2) * 10; // cm->mm
- last_temp = C_to_mkelvin((float) array_uint16_le(ts + (d - 1) * 2) / 10); // dC->mK
- sample->depth.mm = last_depth + (depth_mm - last_depth)
- * (event.time - last_time) / sample_interval;
- sample->temperature.mkelvin = last_temp + (temp_mk - last_temp)
- * (event.time - last_time) / sample_interval;
- }
- finish_sample(dc);
-
- break;
- }
- } // while (true);
- } // for each event sample
-
- // record trailing depth samples
- for ( ;d < sample_count; d++) {
- sample = prepare_sample(dc);
- sample->time.seconds = d * sample_interval;
-
- sample->depth.mm = array_uint16_le(ds + d * 2) * 10; // cm->mm
- sample->temperature.mkelvin =
- C_to_mkelvin((float)array_uint16_le(ts + d * 2) / 10);
- finish_sample(dc);
- }
-
- if (log_version == 3 && model == 4) {
- // Advance to begin of next dive
- switch (array_uint16_le(ps + ps_ptr)) {
- case 0x0000:
- ps_ptr += 5;
- break;
- case 0x0100:
- ps_ptr += 7;
- break;
- case 0x0200:
- ps_ptr += 9;
- break;
- case 0x0300:
- ps_ptr += 11;
- break;
- case 0x0b0b:
- ps_ptr += 27;
- break;
- }
-
- while (*(ps + ps_ptr) != 0x04)
- ps_ptr++;
- }
-
- // End dive
- dive->downloaded = true;
- record_dive(dive);
- mark_divelist_changed(true);
-
- // Advance ptr for next dive
- ptr += ps_ptr + 4;
- } // while
-
- //DEBUG save_dives("/tmp/test.xml");
-}
-
-int try_to_open_liquivision(const char *filename, struct memblock *mem)
-{
- (void) filename;
- const unsigned char *buf = mem->buffer;
- unsigned int buf_size = mem->size;
- unsigned int ptr;
- int log_version;
-
- // Get name length
- unsigned int len = array_uint32_le(buf);
- // Ignore length field and the name
- ptr = 4 + len;
-
- unsigned int dive_count = array_uint32_le(buf + ptr);
- if (dive_count == 0xffffffff) {
- // File version 3.0
- log_version = 3;
- ptr += 6;
- dive_count = array_uint32_le(buf + ptr);
- } else {
- log_version = 2;
- }
- ptr += 4;
-
- parse_dives(log_version, buf + ptr, buf_size - ptr);
-
- return 1;
-}