summaryrefslogtreecommitdiffstats
path: root/uemis-downloader.c
diff options
context:
space:
mode:
authorGravatar Tomaz Canabrava <tomaz.canabrava@intel.com>2015-09-02 20:52:34 -0300
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-10-30 10:36:48 -0700
commit4c0156e3d51b389db8eccc3fa3da4b8f248f9b13 (patch)
tree966868d29150fdba13a5a56fb4305bc432ec7a72 /uemis-downloader.c
parenta0798214231c652ac6142228f5ddfc4b65c921f8 (diff)
downloadsubsurface-4c0156e3d51b389db8eccc3fa3da4b8f248f9b13.tar.gz
Move all core-functionality to subsurface-core
And adapt a new CMakeLists.txt file for it. On the way I've also found out that we where double-compilling a few files. I've also set the subsurface-core as a include_path but that was just to reduce the noise on this commit, since I plan to remove it from the include path to make it obligatory to specify something like include "subsurface-core/dive.h" for the header files. Since the app is growing quite a bit we ended up having a few different files with almost same name that did similar things, I want to kill that (for instance Dive.h, dive.h, PrintDive.h and such). Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'uemis-downloader.c')
-rw-r--r--uemis-downloader.c1359
1 files changed, 0 insertions, 1359 deletions
diff --git a/uemis-downloader.c b/uemis-downloader.c
deleted file mode 100644
index 2a6e5178c..000000000
--- a/uemis-downloader.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- * uemis-downloader.c
- *
- * Copyright (c) Dirk Hohndel <dirk@hohndel.org>
- * released under GPL2
- *
- * very (VERY) loosely based on the algorithms found in Java code by Fabian Gast <fgast@only640k.net>
- * which was released under the BSD-STYLE BEER WARE LICENSE
- * I believe that I only used the information about HOW to do this (download data from the Uemis
- * Zurich) but did not actually use any of his copyrighted code, therefore the license under which
- * he released his code does not apply to this new implementation in C
- *
- * Modified by Guido Lerch guido.lerch@gmail.com in August 2015
- */
-#include <fcntl.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "gettext.h"
-#include "libdivecomputer.h"
-#include "uemis.h"
-#include "divelist.h"
-
-#define ERR_FS_ALMOST_FULL QT_TRANSLATE_NOOP("gettextFromC", "Uemis Zurich: the file system is almost full.\nDisconnect/reconnect the dive computer\nand click \'Retry\'")
-#define ERR_FS_FULL QT_TRANSLATE_NOOP("gettextFromC", "Uemis Zurich: the file system is full.\nDisconnect/reconnect the dive computer\nand click Retry")
-#define ERR_FS_SHORT_WRITE QT_TRANSLATE_NOOP("gettextFromC", "Short write to req.txt file.\nIs the Uemis Zurich plugged in correctly?")
-#define ERR_NO_FILES QT_TRANSLATE_NOOP("gettextFromC", "No dives to download.")
-#define BUFLEN 2048
-#define BUFLEN 2048
-#define NUM_PARAM_BUFS 10
-
-// debugging setup
-// #define UEMIS_DEBUG 1 + 2 + 4 + 8 + 16 + 32
-
-#define UEMIS_MAX_FILES 4000
-#define UEMIS_MEM_FULL 1
-#define UEMIS_MEM_OK 0
-#define UEMIS_SPOT_BLOCK_SIZE 1
-#define UEMIS_DIVE_DETAILS_SIZE 2
-#define UEMIS_LOG_BLOCK_SIZE 10
-#define UEMIS_CHECK_LOG 1
-#define UEMIS_CHECK_DETAILS 2
-#define UEMIS_CHECK_SINGLE_DIVE 3
-
-#if UEMIS_DEBUG
-const char *home, *user, *d_time;
-static int debug_round = 0;
-#define debugfile stderr
-#endif
-
-#if UEMIS_DEBUG & 64 /* we are reading from a copy of the filesystem, not the device - no need to wait */
-#define UEMIS_TIMEOUT 50 /* 50ns */
-#define UEMIS_LONG_TIMEOUT 500 /* 500ns */
-#define UEMIS_MAX_TIMEOUT 2000 /* 2ms */
-#else
-#define UEMIS_TIMEOUT 50000 /* 50ms */
-#define UEMIS_LONG_TIMEOUT 500000 /* 500ms */
-#define UEMIS_MAX_TIMEOUT 2000000 /* 2s */
-#endif
-
-static char *param_buff[NUM_PARAM_BUFS];
-static char *reqtxt_path;
-static int reqtxt_file;
-static int filenr;
-static int number_of_files;
-static char *mbuf = NULL;
-static int mbuf_size = 0;
-
-static int max_mem_used = -1;
-static int next_table_index = 0;
-static int dive_to_read = 0;
-
-/* helper function to parse the Uemis data structures */
-static void uemis_ts(char *buffer, void *_when)
-{
- struct tm tm;
- timestamp_t *when = _when;
-
- memset(&tm, 0, sizeof(tm));
- sscanf(buffer, "%d-%d-%dT%d:%d:%d",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
- tm.tm_mon -= 1;
- tm.tm_year -= 1900;
- *when = utc_mktime(&tm);
-}
-
-/* float minutes */
-static void uemis_duration(char *buffer, duration_t *duration)
-{
- duration->seconds = rint(ascii_strtod(buffer, NULL) * 60);
-}
-
-/* int cm */
-static void uemis_depth(char *buffer, depth_t *depth)
-{
- depth->mm = atoi(buffer) * 10;
-}
-
-static void uemis_get_index(char *buffer, int *idx)
-{
- *idx = atoi(buffer);
-}
-
-/* space separated */
-static void uemis_add_string(const char *buffer, char **text, const char *delimit)
-{
- /* do nothing if this is an empty buffer (Uemis sometimes returns a single
- * space for empty buffers) */
- if (!buffer || !*buffer || (*buffer == ' ' && *(buffer + 1) == '\0'))
- return;
- if (!*text) {
- *text = strdup(buffer);
- } else {
- char *buf = malloc(strlen(buffer) + strlen(*text) + 2);
- strcpy(buf, *text);
- strcat(buf, delimit);
- strcat(buf, buffer);
- free(*text);
- *text = buf;
- }
-}
-
-/* still unclear if it ever reports lbs */
-static void uemis_get_weight(char *buffer, weightsystem_t *weight, int diveid)
-{
- weight->weight.grams = uemis_get_weight_unit(diveid) ?
- lbs_to_grams(ascii_strtod(buffer, NULL)) :
- ascii_strtod(buffer, NULL) * 1000;
- weight->description = strdup(translate("gettextFromC", "unknown"));
-}
-
-static struct dive *uemis_start_dive(uint32_t deviceid)
-{
- struct dive *dive = alloc_dive();
- dive->downloaded = true;
- dive->dc.model = strdup("Uemis Zurich");
- dive->dc.deviceid = deviceid;
- return dive;
-}
-
-static struct dive *get_dive_by_uemis_diveid(device_data_t *devdata, uint32_t object_id)
-{
- for (int i = 0; i < devdata->download_table->nr; i++) {
- if (object_id == devdata->download_table->dives[i]->dc.diveid)
- return devdata->download_table->dives[i];
- }
- return NULL;
-}
-
-static void record_uemis_dive(device_data_t *devdata, struct dive *dive)
-{
- if (devdata->create_new_trip) {
- if (!devdata->trip)
- devdata->trip = create_and_hookup_trip_from_dive(dive);
- else
- add_dive_to_trip(dive, devdata->trip);
- }
- record_dive_to_table(dive, devdata->download_table);
-}
-
-/* send text to the importer progress bar */
-static void uemis_info(const char *fmt, ...)
-{
- static char buffer[256];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(buffer, sizeof(buffer), fmt, ap);
- va_end(ap);
- progress_bar_text = buffer;
-}
-
-static long bytes_available(int file)
-{
- long result;
- long now = lseek(file, 0, SEEK_CUR);
- if (now == -1)
- return 0;
- result = lseek(file, 0, SEEK_END);
- lseek(file, now, SEEK_SET);
- if (now == -1 || result == -1)
- return 0;
- return result;
-}
-
-static int number_of_file(char *path)
-{
- int count = 0;
-#ifdef WIN32
- struct _wdirent *entry;
- _WDIR *dirp = (_WDIR *)subsurface_opendir(path);
-#else
- struct dirent *entry;
- DIR *dirp = (DIR *)subsurface_opendir(path);
-#endif
-
- while (dirp) {
-#ifdef WIN32
- entry = _wreaddir(dirp);
- if (!entry)
- break;
-#else
- entry = readdir(dirp);
- if (!entry)
- break;
- if (strstr(entry->d_name, ".TXT") || strstr(entry->d_name, ".txt")) /* If the entry is a regular file */
-#endif
- count++;
- }
-#ifdef WIN32
- _wclosedir(dirp);
-#else
- closedir(dirp);
-#endif
- return count;
-}
-
-static char *build_filename(const char *path, const char *name)
-{
- int len = strlen(path) + strlen(name) + 2;
- char *buf = malloc(len);
-#if WIN32
- snprintf(buf, len, "%s\\%s", path, name);
-#else
- snprintf(buf, len, "%s/%s", path, name);
-#endif
- return buf;
-}
-
-/* Check if there's a req.txt file and get the starting filenr from it.
- * Test for the maximum number of ANS files (I believe this is always
- * 4000 but in case there are differences depending on firmware, this
- * code is easy enough */
-static bool uemis_init(const char *path)
-{
- char *ans_path;
- int i;
-
- if (!path)
- return false;
- /* let's check if this is indeed a Uemis DC */
- reqtxt_path = build_filename(path, "req.txt");
- reqtxt_file = subsurface_open(reqtxt_path, O_RDONLY | O_CREAT, 0666);
- if (reqtxt_file < 0) {
-#if UEMIS_DEBUG & 1
- fprintf(debugfile, ":EE req.txt can't be opened\n");
-#endif
- return false;
- }
- if (bytes_available(reqtxt_file) > 5) {
- char tmp[6];
- read(reqtxt_file, tmp, 5);
- tmp[5] = '\0';
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "::r req.txt \"%s\"\n", tmp);
-#endif
- if (sscanf(tmp + 1, "%d", &filenr) != 1)
- return false;
- } else {
- filenr = 0;
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "::r req.txt skipped as there were fewer than 5 bytes\n");
-#endif
- }
- close(reqtxt_file);
-
- /* It would be nice if we could simply go back to the first set of
- * ANS files. But with a FAT filesystem that isn't possible */
- ans_path = build_filename(path, "ANS");
- number_of_files = number_of_file(ans_path);
- free(ans_path);
- /* initialize the array in which we collect the answers */
- for (i = 0; i < NUM_PARAM_BUFS; i++)
- param_buff[i] = "";
- return true;
-}
-
-static void str_append_with_delim(char *s, char *t)
-{
- int len = strlen(s);
- snprintf(s + len, BUFLEN - len, "%s{", t);
-}
-
-/* The communication protocoll with the DC is truly funky.
- * After you write your request to the req.txt file you call this function.
- * It writes the number of the next ANS file at the beginning of the req.txt
- * file (prefixed by 'n' or 'r') and then again at the very end of it, after
- * the full request (this time without the prefix).
- * Then it syncs (not needed on Windows) and closes the file. */
-static void trigger_response(int file, char *command, int nr, long tailpos)
-{
- char fl[10];
-
- snprintf(fl, 8, "%s%04d", command, nr);
-#if UEMIS_DEBUG & 4
- fprintf(debugfile, ":tr %s (after seeks)\n", fl);
-#endif
- if (lseek(file, 0, SEEK_SET) == -1)
- goto fs_error;
- if (write(file, fl, strlen(fl)) == -1)
- goto fs_error;
- if (lseek(file, tailpos, SEEK_SET) == -1)
- goto fs_error;
- if (write(file, fl + 1, strlen(fl + 1)) == -1)
- goto fs_error;
-#ifndef WIN32
- fsync(file);
-#endif
-fs_error:
- close(file);
-}
-
-static char *next_token(char **buf)
-{
- char *q, *p = strchr(*buf, '{');
- if (p)
- *p = '\0';
- else
- p = *buf + strlen(*buf) - 1;
- q = *buf;
- *buf = p + 1;
- return q;
-}
-
-/* poor man's tokenizer that understands a quoted delimter ('{') */
-static char *next_segment(char *buf, int *offset, int size)
-{
- int i = *offset;
- int seg_size;
- bool done = false;
- char *segment;
-
- while (!done) {
- if (i < size) {
- if (i < size - 1 && buf[i] == '\\' &&
- (buf[i + 1] == '\\' || buf[i + 1] == '{'))
- memcpy(buf + i, buf + i + 1, size - i - 1);
- else if (buf[i] == '{')
- done = true;
- i++;
- } else {
- done = true;
- }
- }
- seg_size = i - *offset - 1;
- if (seg_size < 0)
- seg_size = 0;
- segment = malloc(seg_size + 1);
- memcpy(segment, buf + *offset, seg_size);
- segment[seg_size] = '\0';
- *offset = i;
- return segment;
-}
-
-/* a dynamically growing buffer to store the potentially massive responses.
- * The binary data block can be more than 100k in size (base64 encoded) */
-static void buffer_add(char **buffer, int *buffer_size, char *buf)
-{
- if (!buf)
- return;
- if (!*buffer) {
- *buffer = strdup(buf);
- *buffer_size = strlen(*buffer) + 1;
- } else {
- *buffer_size += strlen(buf);
- *buffer = realloc(*buffer, *buffer_size);
- strcat(*buffer, buf);
- }
-#if UEMIS_DEBUG & 8
- fprintf(debugfile, "added \"%s\" to buffer - new length %d\n", buf, *buffer_size);
-#endif
-}
-
-/* are there more ANS files we can check? */
-static bool next_file(int max)
-{
- if (filenr >= max)
- return false;
- filenr++;
- return true;
-}
-
-/* try and do a quick decode - without trying to get to fancy in case the data
- * straddles a block boundary...
- * we are parsing something that looks like this:
- * object_id{int{2{date{ts{2011-04-05T12:38:04{duration{float{12.000...
- */
-static char *first_object_id_val(char *buf)
-{
- char *object, *bufend;
- if (!buf)
- return NULL;
- bufend = buf + strlen(buf);
- object = strstr(buf, "object_id");
- if (object && object + 14 < bufend) {
- /* get the value */
- char tmp[36];
- char *p = object + 14;
- char *t = tmp;
-
-#if UEMIS_DEBUG & 4
- char debugbuf[50];
- strncpy(debugbuf, object, 49);
- debugbuf[49] = '\0';
- fprintf(debugfile, "buf |%s|\n", debugbuf);
-#endif
- while (p < bufend && *p != '{' && t < tmp + 9)
- *t++ = *p++;
- if (*p == '{') {
- /* found the object_id - let's quickly look for the date */
- if (strncmp(p, "{date{ts{", 9) == 0 && strstr(p, "{duration{") != NULL) {
- /* cool - that was easy */
- *t++ = ',';
- *t++ = ' ';
- /* skip the 9 characters we just found and take the date, ignoring the seconds
- * and replace the silly 'T' in the middle with a space */
- strncpy(t, p + 9, 16);
- if (*(t + 10) == 'T')
- *(t + 10) = ' ';
- t += 16;
- }
- *t = '\0';
- return strdup(tmp);
- }
- }
- return NULL;
-}
-
-/* ultra-simplistic; it doesn't deal with the case when the object_id is
- * split across two chunks. It also doesn't deal with the discrepancy between
- * object_id and dive number as understood by the dive computer */
-static void show_progress(char *buf, const char *what)
-{
- char *val = first_object_id_val(buf);
- if (val) {
-/* let the user know what we are working on */
-#if UEMIS_DEBUG & 8
- fprintf(debugfile, "reading %s\n %s\n %s\n", what, val, buf);
-#endif
- uemis_info(translate("gettextFromC", "%s %s"), what, val);
- free(val);
- }
-}
-
-static void uemis_increased_timeout(int *timeout)
-{
- if (*timeout < UEMIS_MAX_TIMEOUT)
- *timeout += UEMIS_LONG_TIMEOUT;
- usleep(*timeout);
-}
-
-/* send a request to the dive computer and collect the answer */
-static bool uemis_get_answer(const char *path, char *request, int n_param_in,
- int n_param_out, const char **error_text)
-{
- int i = 0, file_length;
- char sb[BUFLEN];
- char fl[13];
- char tmp[101];
- const char *what = translate("gettextFromC", "data");
- bool searching = true;
- bool assembling_mbuf = false;
- bool ismulti = false;
- bool found_answer = false;
- bool more_files = true;
- bool answer_in_mbuf = false;
- char *ans_path;
- int ans_file;
- int timeout = UEMIS_LONG_TIMEOUT;
-
- reqtxt_file = subsurface_open(reqtxt_path, O_RDWR | O_CREAT, 0666);
- if (reqtxt_file == -1) {
- *error_text = "can't open req.txt";
-#ifdef UEMIS_DEBUG
- fprintf(debugfile, "open %s failed with errno %d\n", reqtxt_path, errno);
-#endif
- return false;
- }
- snprintf(sb, BUFLEN, "n%04d12345678", filenr);
- str_append_with_delim(sb, request);
- for (i = 0; i < n_param_in; i++)
- str_append_with_delim(sb, param_buff[i]);
- if (!strcmp(request, "getDivelogs") || !strcmp(request, "getDeviceData") || !strcmp(request, "getDirectory") ||
- !strcmp(request, "getDivespot") || !strcmp(request, "getDive")) {
- answer_in_mbuf = true;
- str_append_with_delim(sb, "");
- if (!strcmp(request, "getDivelogs"))
- what = translate("gettextFromC", "divelog #");
- else if (!strcmp(request, "getDivespot"))
- what = translate("gettextFromC", "divespot #");
- else if (!strcmp(request, "getDive"))
- what = translate("gettextFromC", "details for #");
- }
- str_append_with_delim(sb, "");
- file_length = strlen(sb);
- snprintf(fl, 10, "%08d", file_length - 13);
- memcpy(sb + 5, fl, strlen(fl));
-#if UEMIS_DEBUG & 4
- fprintf(debugfile, "::w req.txt \"%s\"\n", sb);
-#endif
- if (write(reqtxt_file, sb, strlen(sb)) != strlen(sb)) {
- *error_text = translate("gettextFromC", ERR_FS_SHORT_WRITE);
- return false;
- }
- if (!next_file(number_of_files)) {
- *error_text = translate("gettextFromC", ERR_FS_FULL);
- more_files = false;
- }
- trigger_response(reqtxt_file, "n", filenr, file_length);
- usleep(timeout);
- mbuf = NULL;
- mbuf_size = 0;
- while (searching || assembling_mbuf) {
- if (import_thread_cancelled)
- return false;
- progress_bar_fraction = filenr / (double)UEMIS_MAX_FILES;
- snprintf(fl, 13, "ANS%d.TXT", filenr - 1);
- ans_path = build_filename(build_filename(path, "ANS"), fl);
- ans_file = subsurface_open(ans_path, O_RDONLY, 0666);
- read(ans_file, tmp, 100);
- close(ans_file);
-#if UEMIS_DEBUG & 8
- tmp[100] = '\0';
- fprintf(debugfile, "::t %s \"%s\"\n", ans_path, tmp);
-#elif UEMIS_DEBUG & 4
- char pbuf[4];
- pbuf[0] = tmp[0];
- pbuf[1] = tmp[1];
- pbuf[2] = tmp[2];
- pbuf[3] = 0;
- fprintf(debugfile, "::t %s \"%s...\"\n", ans_path, pbuf);
-#endif
- free(ans_path);
- if (tmp[0] == '1') {
- searching = false;
- if (tmp[1] == 'm') {
- assembling_mbuf = true;
- ismulti = true;
- }
- if (tmp[2] == 'e')
- assembling_mbuf = false;
- if (assembling_mbuf) {
- if (!next_file(number_of_files)) {
- *error_text = translate("gettextFromC", ERR_FS_FULL);
- more_files = false;
- assembling_mbuf = false;
- }
- reqtxt_file = subsurface_open(reqtxt_path, O_RDWR | O_CREAT, 0666);
- if (reqtxt_file == -1) {
- *error_text = "can't open req.txt";
- fprintf(stderr, "open %s failed with errno %d\n", reqtxt_path, errno);
- return false;
- }
- trigger_response(reqtxt_file, "n", filenr, file_length);
- }
- } else {
- if (!next_file(number_of_files - 1)) {
- *error_text = translate("gettextFromC", ERR_FS_FULL);
- more_files = false;
- assembling_mbuf = false;
- searching = false;
- }
- reqtxt_file = subsurface_open(reqtxt_path, O_RDWR | O_CREAT, 0666);
- if (reqtxt_file == -1) {
- *error_text = "can't open req.txt";
- fprintf(stderr, "open %s failed with errno %d\n", reqtxt_path, errno);
- return false;
- }
- trigger_response(reqtxt_file, "r", filenr, file_length);
- uemis_increased_timeout(&timeout);
- }
- if (ismulti && more_files && tmp[0] == '1') {
- int size;
- snprintf(fl, 13, "ANS%d.TXT", assembling_mbuf ? filenr - 2 : filenr - 1);
- ans_path = build_filename(build_filename(path, "ANS"), fl);
- ans_file = subsurface_open(ans_path, O_RDONLY, 0666);
- free(ans_path);
- size = bytes_available(ans_file);
- if (size > 3) {
- char *buf;
- int r;
- if (lseek(ans_file, 3, SEEK_CUR) == -1)
- goto fs_error;
- buf = malloc(size - 2);
- if ((r = read(ans_file, buf, size - 3)) != size - 3) {
- free(buf);
- goto fs_error;
- }
- buf[r] = '\0';
- buffer_add(&mbuf, &mbuf_size, buf);
- show_progress(buf, what);
- free(buf);
- param_buff[3]++;
- }
- close(ans_file);
- timeout = UEMIS_TIMEOUT;
- usleep(UEMIS_TIMEOUT);
- }
- }
- if (more_files) {
- int size = 0, j = 0;
- char *buf = NULL;
-
- if (!ismulti) {
- snprintf(fl, 13, "ANS%d.TXT", filenr - 1);
- ans_path = build_filename(build_filename(path, "ANS"), fl);
- ans_file = subsurface_open(ans_path, O_RDONLY, 0666);
- free(ans_path);
- size = bytes_available(ans_file);
- if (size > 3) {
- int r;
- if (lseek(ans_file, 3, SEEK_CUR) == -1)
- goto fs_error;
- buf = malloc(size - 2);
- if ((r = read(ans_file, buf, size - 3)) != size - 3) {
- free(buf);
- goto fs_error;
- }
- buf[r] = '\0';
- buffer_add(&mbuf, &mbuf_size, buf);
- show_progress(buf, what);
-#if UEMIS_DEBUG & 8
- fprintf(debugfile, "::r %s \"%s\"\n", fl, buf);
-#endif
- }
- size -= 3;
- close(ans_file);
- } else {
- ismulti = false;
- }
-#if UEMIS_DEBUG & 8
- fprintf(debugfile, ":r: %s\n", buf);
-#endif
- if (!answer_in_mbuf)
- for (i = 0; i < n_param_out && j < size; i++)
- param_buff[i] = next_segment(buf, &j, size);
- found_answer = true;
- free(buf);
- }
-#if UEMIS_DEBUG & 1
- for (i = 0; i < n_param_out; i++)
- fprintf(debugfile, "::: %d: %s\n", i, param_buff[i]);
-#endif
- return found_answer;
-fs_error:
- close(ans_file);
- return false;
-}
-
-static bool parse_divespot(char *buf)
-{
- char *bp = buf + 1;
- char *tp = next_token(&bp);
- char *tag, *type, *val;
- char locationstring[1024] = "";
- int divespot, len;
- double latitude = 0.0, longitude = 0.0;
-
- // dive spot got deleted, so fail here
- if (strstr(bp, "deleted{bool{true"))
- return false;
- // not a dive spot, fail here
- if (strcmp(tp, "divespot"))
- return false;
- do
- tag = next_token(&bp);
- while (*tag && strcmp(tag, "object_id"));
- if (!*tag)
- return false;
- next_token(&bp);
- val = next_token(&bp);
- divespot = atoi(val);
- do {
- tag = next_token(&bp);
- type = next_token(&bp);
- val = next_token(&bp);
- if (!strcmp(type, "string") && *val && strcmp(val, " ")) {
- len = strlen(locationstring);
- snprintf(locationstring + len, sizeof(locationstring) - len,
- "%s%s", len ? ", " : "", val);
- } else if (!strcmp(type, "float")) {
- if (!strcmp(tag, "longitude"))
- longitude = ascii_strtod(val, NULL);
- else if (!strcmp(tag, "latitude"))
- latitude = ascii_strtod(val, NULL);
- }
- } while (tag && *tag);
-
- uemis_set_divelocation(divespot, locationstring, longitude, latitude);
- return true;
-}
-
-static char *suit[] = {"", QT_TRANSLATE_NOOP("gettextFromC", "wetsuit"), QT_TRANSLATE_NOOP("gettextFromC", "semidry"), QT_TRANSLATE_NOOP("gettextFromC", "drysuit")};
-static char *suit_type[] = {"", QT_TRANSLATE_NOOP("gettextFromC", "shorty"), QT_TRANSLATE_NOOP("gettextFromC", "vest"), QT_TRANSLATE_NOOP("gettextFromC", "long john"), QT_TRANSLATE_NOOP("gettextFromC", "jacket"), QT_TRANSLATE_NOOP("gettextFromC", "full suit"), QT_TRANSLATE_NOOP("gettextFromC", "2 pcs full suit")};
-static char *suit_thickness[] = {"", "0.5-2mm", "2-3mm", "3-5mm", "5-7mm", "8mm+", QT_TRANSLATE_NOOP("gettextFromC", "membrane")};
-
-static void parse_tag(struct dive *dive, char *tag, char *val)
-{
- /* we can ignore computer_id, water and gas as those are redundant
- * with the binary data and would just get overwritten */
-#if UEMIS_DEBUG & 4
- if (strcmp(tag, "file_content"))
- fprintf(debugfile, "Adding to dive %d : %s = %s\n", dive->dc.diveid, tag, val);
-#endif
- if (!strcmp(tag, "date")) {
- uemis_ts(val, &dive->when);
- } else if (!strcmp(tag, "duration")) {
- uemis_duration(val, &dive->dc.duration);
- } else if (!strcmp(tag, "depth")) {
- uemis_depth(val, &dive->dc.maxdepth);
- } else if (!strcmp(tag, "file_content")) {
- uemis_parse_divelog_binary(val, dive);
- } else if (!strcmp(tag, "altitude")) {
- uemis_get_index(val, &dive->dc.surface_pressure.mbar);
- } else if (!strcmp(tag, "f32Weight")) {
- uemis_get_weight(val, &dive->weightsystem[0], dive->dc.diveid);
- } else if (!strcmp(tag, "notes")) {
- uemis_add_string(val, &dive->notes, " ");
- } else if (!strcmp(tag, "u8DiveSuit")) {
- if (*suit[atoi(val)])
- uemis_add_string(translate("gettextFromC", suit[atoi(val)]), &dive->suit, " ");
- } else if (!strcmp(tag, "u8DiveSuitType")) {
- if (*suit_type[atoi(val)])
- uemis_add_string(translate("gettextFromC", suit_type[atoi(val)]), &dive->suit, " ");
- } else if (!strcmp(tag, "u8SuitThickness")) {
- if (*suit_thickness[atoi(val)])
- uemis_add_string(translate("gettextFromC", suit_thickness[atoi(val)]), &dive->suit, " ");
- } else if (!strcmp(tag, "nickname")) {
- uemis_add_string(val, &dive->buddy, ",");
- }
-}
-
-static bool uemis_delete_dive(device_data_t *devdata, uint32_t diveid)
-{
- struct dive *dive = NULL;
-
- if (devdata->download_table->dives[devdata->download_table->nr - 1]->dc.diveid == diveid) {
- /* we hit the last one in the array */
- dive = devdata->download_table->dives[devdata->download_table->nr - 1];
- } else {
- for (int i = 0; i < devdata->download_table->nr - 1; i++) {
- if (devdata->download_table->dives[i]->dc.diveid == diveid) {
- dive = devdata->download_table->dives[i];
- for (int x = i; x < devdata->download_table->nr - 1; x++)
- devdata->download_table->dives[i] = devdata->download_table->dives[x + 1];
- }
- }
- }
- if (dive) {
- devdata->download_table->dives[--devdata->download_table->nr] = NULL;
- if (dive->tripflag != TF_NONE)
- remove_dive_from_trip(dive, false);
-
- free(dive->dc.sample);
- free((void *)dive->notes);
- free((void *)dive->divemaster);
- free((void *)dive->buddy);
- free((void *)dive->suit);
- taglist_free(dive->tag_list);
- free(dive);
-
- return true;
- }
- return false;
-}
-
-/* This function is called for both divelog and dive information that we get
- * from the SDA (what an insane design, btw). The object_id in the divelog
- * matches the logfilenr in the dive information (which has its own, often
- * different object_id) - we use this as the diveid.
- * We create the dive when parsing the divelog and then later, when we parse
- * the dive information we locate the already created dive via its diveid.
- * Most things just get parsed and converted into our internal data structures,
- * but the dive location API is even more crazy. We just get an id that is an
- * index into yet another data store that we read out later. In order to
- * correctly populate the location and gps data from that we need to remember
- * the adresses of those fields for every dive that references the divespot. */
-static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char *inbuf, char **max_divenr, bool keep_number, int *for_dive)
-{
- char *buf = strdup(inbuf);
- char *tp, *bp, *tag, *type, *val;
- bool done = false;
- int inbuflen = strlen(inbuf);
- char *endptr = buf + inbuflen;
- bool is_log = false, is_dive = false;
- char *sections[10];
- int s, nr_sections = 0;
- struct dive *dive = NULL;
- char dive_no[10];
-
-#if UEMIS_DEBUG & 8
- fprintf(debugfile, "p_r_b %s\n", inbuf);
-#endif
- if (for_dive)
- *for_dive = -1;
- bp = buf + 1;
- tp = next_token(&bp);
- if (strcmp(tp, "divelog") == 0) {
- /* this is a divelog */
- is_log = true;
- tp = next_token(&bp);
- /* is it a valid entry or nothing ? */
- if (strcmp(tp, "1.0") != 0 || strstr(inbuf, "divelog{1.0{{{{")) {
- free(buf);
- return false;
- }
- } else if (strcmp(tp, "dive") == 0) {
- /* this is dive detail */
- is_dive = true;
- tp = next_token(&bp);
- if (strcmp(tp, "1.0") != 0) {
- free(buf);
- return false;
- }
- } else {
- /* don't understand the buffer */
- free(buf);
- return false;
- }
- if (is_log) {
- dive = uemis_start_dive(deviceid);
- } else {
- /* remember, we don't know if this is the right entry,
- * so first test if this is even a valid entry */
- if (strstr(inbuf, "deleted{bool{true")) {
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "p_r_b entry deleted\n");
-#endif
- /* oops, this one isn't valid, suggest to try the previous one */
- free(buf);
- return false;
- }
- /* quickhack and workaround to capture the original dive_no
- * i am doing this so I dont have to change the original design
- * but when parsing a dive we never parse the dive number because
- * at the time it's being read the *dive varible is not set because
- * the dive_no tag comes before the object_id in the uemis ans file
- */
- dive_no[0] = '\0';
- char *dive_no_buf = strdup(inbuf);
- char *dive_no_ptr = strstr(dive_no_buf, "dive_no{int{") + 12;
- if (dive_no_ptr) {
- char *dive_no_end = strstr(dive_no_ptr, "{");
- if (dive_no_end) {
- *dive_no_end = '\0';
- strncpy(dive_no, dive_no_ptr, 9);
- dive_no[9] = '\0';
- }
- }
- free(dive_no_buf);
- }
- while (!done) {
- /* the valid buffer ends with a series of delimiters */
- if (bp >= endptr - 2 || !strcmp(bp, "{{"))
- break;
- tag = next_token(&bp);
- /* we also end if we get an empty tag */
- if (*tag == '\0')
- break;
- for (s = 0; s < nr_sections; s++)
- if (!strcmp(tag, sections[s])) {
- tag = next_token(&bp);
- break;
- }
- type = next_token(&bp);
- if (!strcmp(type, "1.0")) {
- /* this tells us the sections that will follow; the tag here
- * is of the format dive-<section> */
- sections[nr_sections] = strchr(tag, '-') + 1;
-#if UEMIS_DEBUG & 4
- fprintf(debugfile, "Expect to find section %s\n", sections[nr_sections]);
-#endif
- if (nr_sections < sizeof(sections) - 1)
- nr_sections++;
- continue;
- }
- val = next_token(&bp);
-#if UEMIS_DEBUG & 8
- if (strlen(val) < 20)
- fprintf(debugfile, "Parsed %s, %s, %s\n*************************\n", tag, type, val);
-#endif
- if (is_log && strcmp(tag, "object_id") == 0) {
- free(*max_divenr);
- *max_divenr = strdup(val);
- dive->dc.diveid = atoi(val);
-#if UEMIS_DEBUG % 2
- fprintf(debugfile, "Adding new dive from log with object_id %d.\n", atoi(val));
-#endif
- } else if (is_dive && strcmp(tag, "logfilenr") == 0) {
- /* this one tells us which dive we are adding data to */
- dive = get_dive_by_uemis_diveid(devdata, atoi(val));
- if (strcmp(dive_no, "0"))
- dive->number = atoi(dive_no);
- if (for_dive)
- *for_dive = atoi(val);
- } else if (!is_log && dive && !strcmp(tag, "divespot_id")) {
- int divespot_id = atoi(val);
- if (divespot_id != -1) {
- dive->dive_site_uuid = create_dive_site("from Uemis", dive->when);
- uemis_mark_divelocation(dive->dc.diveid, divespot_id, dive->dive_site_uuid);
- }
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "Created divesite %d for diveid : %d\n", dive->dive_site_uuid, dive->dc.diveid);
-#endif
- } else if (dive) {
- parse_tag(dive, tag, val);
- }
- if (is_log && !strcmp(tag, "file_content"))
- done = true;
- /* done with one dive (got the file_content tag), but there could be more:
- * a '{' indicates the end of the record - but we need to see another "{{"
- * later in the buffer to know that the next record is complete (it could
- * be a short read because of some error */
- if (done && ++bp < endptr && *bp != '{' && strstr(bp, "{{")) {
- done = false;
- record_uemis_dive(devdata, dive);
- mark_divelist_changed(true);
- dive = uemis_start_dive(deviceid);
- }
- }
- if (is_log) {
- if (dive->dc.diveid) {
- record_uemis_dive(devdata, dive);
- mark_divelist_changed(true);
- } else { /* partial dive */
- free(dive);
- free(buf);
- return false;
- }
- }
- free(buf);
- return true;
-}
-
-static char *uemis_get_divenr(char *deviceidstr, int force)
-{
- uint32_t deviceid, maxdiveid = 0;
- int i;
- char divenr[10];
- struct dive_table *table;
- deviceid = atoi(deviceidstr);
-
- /*
- * If we are are retrying after a disconnect/reconnect, we
- * will look up the highest dive number in the dives we
- * already have.
- *
- * Also, if "force_download" is true, do this even if we
- * don't have any dives (maxdiveid will remain zero)
- */
- if (force || downloadTable.nr)
- table = &downloadTable;
- else
- table = &dive_table;
-
- for (i = 0; i < table->nr; i++) {
- struct dive *d = table->dives[i];
- struct divecomputer *dc;
- if (!d)
- continue;
- for_each_dc (d, dc) {
- if (dc->model && !strcmp(dc->model, "Uemis Zurich") &&
- (dc->deviceid == 0 || dc->deviceid == 0x7fffffff || dc->deviceid == deviceid) &&
- dc->diveid > maxdiveid)
- maxdiveid = dc->diveid;
- }
- }
- snprintf(divenr, 10, "%d", maxdiveid);
- return strdup(divenr);
-}
-
-#if UEMIS_DEBUG
-static int bufCnt = 0;
-static bool do_dump_buffer_to_file(char *buf, char *prefix)
-{
- char path[100];
- char date[40];
- char obid[40];
- if (!buf)
- return false;
-
- if (strstr(buf, "date{ts{"))
- strncpy(date, strstr(buf, "date{ts{"), sizeof(date));
- else
- strncpy(date, "date{ts{no-date{", sizeof(date));
-
- if (!strstr(buf, "object_id{int{"))
- return false;
-
- strncpy(obid, strstr(buf, "object_id{int{"), sizeof(obid));
- char *ptr1 = strstr(date, "date{ts{");
- char *ptr2 = strstr(obid, "object_id{int{");
- char *pdate = next_token(&ptr1);
- pdate = next_token(&ptr1);
- pdate = next_token(&ptr1);
- char *pobid = next_token(&ptr2);
- pobid = next_token(&ptr2);
- pobid = next_token(&ptr2);
- snprintf(path, sizeof(path), "/%s/%s/UEMIS Dump/%s_%s_Uemis_dump_%s_in_round_%d_%d.txt", home, user, prefix, pdate, pobid, debug_round, bufCnt);
- int dumpFile = subsurface_open(path, O_RDWR | O_CREAT, 0666);
- if (dumpFile == -1)
- return false;
- write(dumpFile, buf, strlen(buf));
- close(dumpFile);
- bufCnt++;
- return true;
-}
-#endif
-
-/* do some more sophisticated calculations here to try and predict if the next round of
- * divelog/divedetail reads will fit into the UEMIS buffer,
- * filenr holds now the uemis filenr after having read several logs including the dive details,
- * fCapacity will five us the average number of files needed for all currently loaded data
- * remember the maximum file usage per dive
- * return : UEMIS_MEM_OK if there is enough memeory for a full round
- * UEMIS_MEM_CRITICAL if the memory is good for reading the dive logs
- * UEMIS_MEM_FULL if the memory is exhaused
- */
-static int get_memory(struct dive_table *td, int checkpoint)
-{
- if (td->nr <= 0)
- return UEMIS_MEM_OK;
-
- switch (checkpoint) {
- case UEMIS_CHECK_LOG:
- if (filenr / td->nr > max_mem_used)
- max_mem_used = filenr / td->nr;
-
- /* check if a full block of dive logs + dive details and dive spot fit into the UEMIS buffer */
- if (max_mem_used * UEMIS_LOG_BLOCK_SIZE > UEMIS_MAX_FILES - filenr)
- return UEMIS_MEM_FULL;
- break;
- case UEMIS_CHECK_DETAILS:
- /* check if the next set of dive details and dive spot fit into the UEMIS buffer */
- if ((UEMIS_DIVE_DETAILS_SIZE + UEMIS_SPOT_BLOCK_SIZE) * UEMIS_LOG_BLOCK_SIZE > UEMIS_MAX_FILES - filenr)
- return UEMIS_MEM_FULL;
- break;
- case UEMIS_CHECK_SINGLE_DIVE:
- if (UEMIS_DIVE_DETAILS_SIZE + UEMIS_SPOT_BLOCK_SIZE > UEMIS_MAX_FILES - filenr)
- return UEMIS_MEM_FULL;
- break;
- }
- return UEMIS_MEM_OK;
-}
-
-/* mark a dive as deleted by setting download to false
- * this will be picked up by some cleaning statement later */
-static void do_delete_dives(struct dive_table *td, int idx)
-{
- for (int x = idx; x < td->nr; x++)
- td->dives[x]->downloaded = false;
-}
-
-static bool load_uemis_divespot(const char *mountpath, int divespot_id)
-{
- char divespotnr[10];
- snprintf(divespotnr, sizeof(divespotnr), "%d", divespot_id);
- param_buff[2] = divespotnr;
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "getDivespot %d\n", divespot_id);
-#endif
- bool success = uemis_get_answer(mountpath, "getDivespot", 3, 0, NULL);
- if (mbuf && success) {
-#if UEMIS_DEBUG & 16
- do_dump_buffer_to_file(mbuf, "Spot");
-#endif
- return parse_divespot(mbuf);
- }
- return false;
-}
-
-static void get_uemis_divespot(const char *mountpath, int divespot_id, struct dive *dive)
-{
- struct dive_site *nds = get_dive_site_by_uuid(dive->dive_site_uuid);
- if (nds && nds->name && strstr(nds->name,"from Uemis")) {
- if (load_uemis_divespot(mountpath, divespot_id)) {
- /* get the divesite based on the diveid, this should give us
- * the newly created site
- */
- struct dive_site *ods = NULL;
- /* with the divesite name we got from parse_dive, that is called on load_uemis_divespot
- * we search all existing divesites if we have one with the same name already. The function
- * returns the first found which is luckily not the newly created.
- */
- (void)get_dive_site_uuid_by_name(nds->name, &ods);
- if (ods) {
- /* if the uuid's are the same, the new site is a duplicat and can be deleted */
- if (nds->uuid != ods->uuid) {
- delete_dive_site(nds->uuid);
- dive->dive_site_uuid = ods->uuid;
- }
- }
- } else {
- /* if we cant load the dive site details, delete the site we
- * created in process_raw_buffer
- */
- delete_dive_site(dive->dive_site_uuid);
- }
- }
-}
-
-static bool get_matching_dive(int idx, char *newmax, int *uemis_mem_status, struct device_data_t *data, const char *mountpath, const char deviceidnr)
-{
- struct dive *dive = data->download_table->dives[idx];
- char log_file_no_to_find[20];
- char dive_to_read_buf[10];
- bool found = false;
- int deleted_files = 0;
-
- snprintf(log_file_no_to_find, sizeof(log_file_no_to_find), "logfilenr{int{%d", dive->dc.diveid);
- while (!found) {
- if (import_thread_cancelled)
- break;
- snprintf(dive_to_read_buf, sizeof(dive_to_read_buf), "%d", dive_to_read);
- param_buff[2] = dive_to_read_buf;
- (void)uemis_get_answer(mountpath, "getDive", 3, 0, NULL);
-#if UEMIS_DEBUG & 16
- do_dump_buffer_to_file(mbuf, "Dive");
-#endif
- *uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_SINGLE_DIVE);
- if (*uemis_mem_status == UEMIS_MEM_OK) {
- /* if the memory isn's completely full we can try to read more divelog vs. dive details
- * UEMIS_MEM_CRITICAL means not enough space for a full round but the dive details
- * and the divespots should fit into the UEMIS memory
- * The match we do here is to map the object_id to the logfilenr, we do this
- * by iterating through the last set of loaded divelogs and then find the corresponding
- * dive with the matching logfilenr */
- if (mbuf) {
- if (strstr(mbuf, log_file_no_to_find)) {
- /* we found the logfilenr that matches our object_id from the divelog we were looking for
- * we mark the search sucessfull even if the dive has been deleted. */
- found = true;
- if (strstr(mbuf, "deleted{bool{true") == NULL) {
- process_raw_buffer(data, deviceidnr, mbuf, &newmax, false, NULL);
- /* remember the last log file number as it is very likely that subsequent dives
- * have the same or higher logfile number.
- * UEMIS unfortunately deletes dives by deleting the dive details and not the logs. */
-#if UEMIS_DEBUG & 2
- d_time = get_dive_date_c_string(dive->when);
- fprintf(debugfile, "Matching divelog id %d from %s with dive details %d\n", dive->dc.diveid, d_time, dive_to_read);
-#endif
- int divespot_id = uemis_get_divespot_id_by_diveid(dive->dc.diveid);
- if (divespot_id >= 0)
- get_uemis_divespot(mountpath, divespot_id, dive);
-
- } else {
- /* in this case we found a deleted file, so let's increment */
-#if UEMIS_DEBUG & 2
- d_time = get_dive_date_c_string(dive->when);
- fprintf(debugfile, "TRY matching divelog id %d from %s with dive details %d but details are deleted\n", dive->dc.diveid, d_time, dive_to_read);
-#endif
- deleted_files++;
- /* mark this log entry as deleted and cleanup later, otherwise we mess up our array */
- dive->downloaded = false;
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "Deleted dive from %s, with id %d from table\n", d_time, dive->dc.diveid);
-#endif
- }
- } else {
- uint32_t nr_found = 0;
- char *logfilenr = strstr(mbuf, "logfilenr");
- if (logfilenr) {
- sscanf(logfilenr, "logfilenr{int{%u", &nr_found);
- if (nr_found >= dive->dc.diveid)
- dive_to_read = dive_to_read - 2;
- if (dive_to_read < -1)
- dive_to_read = -1;
- }
- }
- }
- dive_to_read++;
- } else {
- /* At this point the memory of the UEMIS is full, let's cleanup all divelog files were
- * we could not match the details to. */
- do_delete_dives(data->download_table, idx);
- return false;
- }
- }
- /* decrement iDiveToRead by the amount of deleted entries found to assure
- * we are not missing any valid matches when processing subsequent logs */
- dive_to_read = (dive_to_read - deleted_files > 0 ? dive_to_read - deleted_files : 0);
- deleted_files = 0;
- return true;
-}
-
-const char *do_uemis_import(device_data_t *data)
-{
- const char *mountpath = data->devname;
- short force_download = data->force_download;
- char *newmax = NULL;
- int first, start, end = -2;
- uint32_t deviceidnr;
- char *deviceid = NULL;
- const char *result = NULL;
- char *endptr;
- bool success, keep_number = false, once = true;
- int match_dive_and_log = 0;
- int uemis_mem_status = UEMIS_MEM_OK;
-
-#if UEMIS_DEBUG
- home = getenv("HOME");
- user = getenv("LOGNAME");
-#endif
- if (dive_table.nr == 0)
- keep_number = true;
-
- uemis_info(translate("gettextFromC", "Initialise communication"));
- if (!uemis_init(mountpath)) {
- free(reqtxt_path);
- return translate("gettextFromC", "Uemis init failed");
- }
-
- if (!uemis_get_answer(mountpath, "getDeviceId", 0, 1, &result))
- goto bail;
- deviceid = strdup(param_buff[0]);
- deviceidnr = atoi(deviceid);
-
- /* param_buff[0] is still valid */
- if (!uemis_get_answer(mountpath, "initSession", 1, 6, &result))
- goto bail;
-
- uemis_info(translate("gettextFromC", "Start download"));
- if (!uemis_get_answer(mountpath, "processSync", 0, 2, &result))
- goto bail;
-
- /* before starting the long download, check if user pressed cancel */
- if (import_thread_cancelled)
- goto bail;
-
- param_buff[1] = "notempty";
- newmax = uemis_get_divenr(deviceid, force_download);
-
- first = start = atoi(newmax);
- dive_to_read = first;
- for (;;) {
-#if UEMIS_DEBUG & 2
- debug_round++;
-#endif
-#if UEMIS_DEBUG & 4
- fprintf(debugfile, "d_u_i inner loop start %d end %d newmax %s\n", start, end, newmax);
-#endif
- /* start at the last filled download table index */
- match_dive_and_log = data->download_table->nr;
- sprintf(newmax, "%d", start);
- param_buff[2] = newmax;
- param_buff[3] = 0;
- success = uemis_get_answer(mountpath, "getDivelogs", 3, 0, &result);
- uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_DETAILS);
- if (success && mbuf && uemis_mem_status != UEMIS_MEM_FULL) {
-#if UEMIS_DEBUG & 16
- do_dump_buffer_to_file(mbuf, "Divelogs");
-#endif
- /* process the buffer we have assembled */
-
- if (!process_raw_buffer(data, deviceidnr, mbuf, &newmax, keep_number, NULL)) {
- /* if no dives were downloaded, mark end appropriately */
- if (end == -2)
- end = start - 1;
- success = false;
- }
- if (once) {
- char *t = first_object_id_val(mbuf);
- if (t && atoi(t) > start)
- start = atoi(t);
- free(t);
- once = false;
- }
- /* clean up mbuf */
- endptr = strstr(mbuf, "{{{");
- if (endptr)
- *(endptr + 2) = '\0';
- /* last object_id we parsed */
- sscanf(newmax, "%d", &end);
-#if UEMIS_DEBUG & 4
- fprintf(debugfile, "d_u_i after download and parse start %d end %d newmax %s progress %4.2f\n", start, end, newmax, progress_bar_fraction);
-#endif
- /* The way this works is that I am reading the current dive from what has been loaded during the getDiveLogs call to the UEMIS.
- * As the object_id of the divelog entry and the object_id of the dive details are not necessarily the same, the match needs
- * to happen based on the logfilenr.
- * What the following part does is to optimize the mapping by using
- * dive_to_read = the dive deatils entry that need to be read using the object_id
- * logFileNoToFind = map the logfilenr of the dive details with the object_id = diveid from the get dive logs */
- for (int i = match_dive_and_log; i < data->download_table->nr; i++) {
- bool success = get_matching_dive(i, newmax, &uemis_mem_status, data, mountpath, deviceidnr);
- if (!success)
- break;
- if (import_thread_cancelled)
- break;
- }
-
- start = end;
-
- /* Do some memory checking here */
- uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_LOG);
- if (uemis_mem_status != UEMIS_MEM_OK)
- break;
-
- /* if the user clicked cancel, exit gracefully */
- if (import_thread_cancelled)
- break;
-
- /* if we got an error or got nothing back, stop trying */
- if (!success || !param_buff[3])
- break;
-#if UEMIS_DEBUG & 2
- if (debug_round != -1)
- if (debug_round-- == 0)
- goto bail;
-#endif
- } else {
- /* some of the loading from the UEMIS failed at the divelog level
- * if the memory status = full, we cant even load the divespots and/or buddys.
- * The loaded block of divelogs is useless and all new loaded divelogs need to
- * be deleted from the download_table.
- */
- if (uemis_mem_status == UEMIS_MEM_FULL)
- do_delete_dives(data->download_table, match_dive_and_log);
- break;
- }
- }
-
- if (end == -2 && sscanf(newmax, "%d", &end) != 1)
- end = start;
-
-#if UEMIS_DEBUG & 2
- fprintf(debugfile, "Done: read from object_id %d to %d\n", first, end);
-#endif
-
- /* Regardless on where we are with the memory situation, it's time now
- * to see if we have to clean some dead bodies from our download table */
- next_table_index = 0;
- while (next_table_index < data->download_table->nr) {
- if (!data->download_table->dives[next_table_index]->downloaded)
- uemis_delete_dive(data, data->download_table->dives[next_table_index]->dc.diveid);
- else
- next_table_index++;
- }
-
- if (uemis_mem_status != UEMIS_MEM_OK)
- result = translate("gettextFromC", ERR_FS_ALMOST_FULL);
-
-bail:
- (void)uemis_get_answer(mountpath, "terminateSync", 0, 3, &result);
- if (!strcmp(param_buff[0], "error")) {
- if (!strcmp(param_buff[2], "Out of Memory"))
- result = translate("gettextFromC", ERR_FS_FULL);
- else
- result = param_buff[2];
- }
- free(deviceid);
- free(reqtxt_path);
- if (!data->download_table->nr)
- result = translate("gettextFromC", ERR_NO_FILES);
- return result;
-}