Locate the most recent dive

The Suunto Eon Steel seems to have a limit of maximum 400 dives. Once
that limit is reached, the oldest dives get overwritten with newer
dives. But the order in which the dive entries are downloaded isn't
changed, and thus the most recent dive is no longer the last entry.

For the first 400 dives, the order is always straightforward:

   D001 D002  ... D399 D400

The most recent dive is always the last entry, and no special processing
is necessary. But once the limit is reached, the next few dives will
start to overwrite the oldest dives, but the order remains unchanged:

   D401 D402 ... D399 D400

Thus in order to return the dives in the correct order (newest first),
we can no longer assume the most recent dive is the last entry, and thus
we need to locate it manually.

The new algorithm is based on the assumption that the most recent dive
will have the hightest timestamp. And to be able to walk backwards
through all the entries, the list is assumed to be a circular list.
This commit is contained in:
Jef Driesen 2017-11-17 23:02:46 +01:00
parent f5df265300
commit 812db650d4

View File

@ -592,16 +592,6 @@ error_free:
return status;
}
static int count_dir_entries(struct directory_entry *de)
{
int count = 0;
while (de) {
count++;
de = de->next;
}
return count;
}
static dc_status_t
suunto_eonsteel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
{
@ -630,9 +620,6 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
unsigned int count = 0;
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
if (get_file_list(eon, &de) < 0)
return DC_STATUS_IO;
// Emit a device info event.
dc_event_devinfo_t devinfo;
devinfo.model = 0;
@ -640,16 +627,47 @@ suunto_eonsteel_device_foreach(dc_device_t *abstract, dc_dive_callback_t callbac
devinfo.serial = array_convert_str2num(eon->version + 0x10, 16);
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
count = count_dir_entries(de);
if (count == 0) {
if (get_file_list(eon, &de) < 0)
return DC_STATUS_IO;
if (de == NULL) {
return DC_STATUS_SUCCESS;
}
// Locate the most recent dive.
// The filename represent the time of the dive, encoded as a hexadecimal
// number. Thus the most recent dive can be found by simply sorting the
// filenames alphabetically.
struct directory_entry *head = de, *tail = de, *latest = de;
while (de) {
if (strcmp (de->name, latest->name) > 0) {
latest = de;
}
tail = de;
count++;
de = de->next;
}
// Make the most recent dive the head of the list.
// The linked list is made circular, by attaching the head to the tail and
// then cut open again just before the most recent dive.
de = head;
while (de) {
if (de->next == latest) {
de->next = NULL;
tail->next = head;
break;
}
de = de->next;
}
file = dc_buffer_new(0);
progress.maximum = count;
progress.current = 0;
device_event_emit(abstract, DC_EVENT_PROGRESS, &progress);
de = latest;
while (de) {
int len;
struct directory_entry *next = de->next;