From 121c7c12fb4972be652eb81ae76b081a9ac0629d Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 5 Mar 2024 20:06:28 +0100 Subject: [PATCH 1/7] Swap values 2 and 3 of the pointer mode Swapping values 2 and 3 of the pointer mode has the advantage that only the mode with the largest value uses bytes as its unit, while all others use the page size as their unit. --- src/oceanic_atom2.c | 4 ++-- src/oceanic_common.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 0c63e16..5eb60a6 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -101,7 +101,7 @@ static const oceanic_common_layout_t aeris_f10_layout = { 0x0D80, /* rb_profile_begin */ 0x10000, /* rb_profile_end */ 0, /* pt_mode_global */ - 2, /* pt_mode_logbook */ + 3, /* pt_mode_logbook */ 0, /* pt_mode_serial */ }; @@ -116,7 +116,7 @@ static const oceanic_common_layout_t aeris_f11_layout = { 0x0D80, /* rb_profile_begin */ 0x20000, /* rb_profile_end */ 0, /* pt_mode_global */ - 3, /* pt_mode_logbook */ + 2, /* pt_mode_logbook */ 0, /* pt_mode_serial */ }; diff --git a/src/oceanic_common.c b/src/oceanic_common.c index e79406a..f09e629 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -49,7 +49,7 @@ get_profile_first (const unsigned char data[], const oceanic_common_layout_t *la value = array_uint16_le (data + 5); } else if (layout->pt_mode_logbook == 1) { value = array_uint16_le (data + 4); - } else if (layout->pt_mode_logbook == 3) { + } else if (layout->pt_mode_logbook == 2) { value = array_uint16_le (data + 16); } else { return array_uint16_le (data + 16); @@ -79,7 +79,7 @@ get_profile_last (const unsigned char data[], const oceanic_common_layout_t *lay value = array_uint16_le (data + 6) >> 4; } else if (layout->pt_mode_logbook == 1) { value = array_uint16_le (data + 6); - } else if (layout->pt_mode_logbook == 3) { + } else if (layout->pt_mode_logbook == 2) { value = array_uint16_le (data + 18); } else { return array_uint16_le(data + 18); From a91a7dbc384f9701eb6390a1a2a483e9a07dc691 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Wed, 7 Feb 2024 20:39:38 +0100 Subject: [PATCH 2/7] Refactor the function to get the profile pointers Refactor the code to retrieve the profile pointers from the logbook entry into a single function that deals with all the quirks internally and simply returns a begin/end pair. To obtain the end pointer, the page size is now added to the value of the last pointer without taking into account the ringbuffer boundaries. The consequence are: - The boundary checks in the caller need to be relaxed to accept the end pointer as a valid value. - The check for the gap between the profiles can no longer compare the pointer values directly because the begin/end values are equivalent, but not equal. --- src/oceanic_common.c | 147 +++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 83 deletions(-) diff --git a/src/oceanic_common.c b/src/oceanic_common.c index f09e629..4b5ee60 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -35,69 +35,57 @@ #define RB_LOGBOOK_DISTANCE(a,b,l) ringbuffer_distance (a, b, DC_RINGBUFFER_FULL, l->rb_logbook_begin, l->rb_logbook_end) #define RB_LOGBOOK_INCR(a,b,l) ringbuffer_increment (a, b, l->rb_logbook_begin, l->rb_logbook_end) -#define RB_PROFILE_DISTANCE(a,b,l) ringbuffer_distance (a, b, DC_RINGBUFFER_EMPTY, l->rb_profile_begin, l->rb_profile_end) -#define RB_PROFILE_INCR(a,b,l) ringbuffer_increment (a, b, l->rb_profile_begin, l->rb_profile_end) +#define RB_PROFILE_DISTANCE(a,b,l,m) ringbuffer_distance (a, b, m, l->rb_profile_begin, l->rb_profile_end) #define INVALID 0 -static unsigned int -get_profile_first (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize) +static dc_status_t +oceanic_common_device_get_profile (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int *begin, unsigned int *end) { - unsigned int value; + assert (layout != NULL); + assert (begin != NULL && end != NULL); + // Get the pagesize + unsigned int pagesize = layout->highmem ? 16 * PAGESIZE : PAGESIZE; + + // Get the profile pointers. + unsigned int first = 0, last = 0; if (layout->pt_mode_logbook == 0) { - value = array_uint16_le (data + 5); + first = array_uint16_le (data + 5); + last = array_uint16_le (data + 6) >> 4; } else if (layout->pt_mode_logbook == 1) { - value = array_uint16_le (data + 4); - } else if (layout->pt_mode_logbook == 2) { - value = array_uint16_le (data + 16); - } else { - return array_uint16_le (data + 16); + first = array_uint16_le (data + 4); + last = array_uint16_le (data + 6); + } else if (layout->pt_mode_logbook == 2 || layout->pt_mode_logbook == 3) { + first = array_uint16_le (data + 16); + last = array_uint16_le (data + 18); } - unsigned int npages = (layout->memsize - layout->highmem) / pagesize; - if (npages > 0x4000) { - value &= 0x7FFF; - } else if (npages > 0x2000) { - value &= 0x3FFF; - } else if (npages > 0x1000) { - value &= 0x1FFF; - } else { - value &= 0x0FFF; + // Convert pages to bytes. + if (layout->pt_mode_logbook < 3) { + unsigned int npages = (layout->memsize - layout->highmem) / pagesize; + if (npages > 0x4000) { + first &= 0x7FFF; + last &= 0x7FFF; + } else if (npages > 0x2000) { + first &= 0x3FFF; + last &= 0x3FFF; + } else if (npages > 0x1000) { + first &= 0x1FFF; + last &= 0x1FFF; + } else { + first &= 0x0FFF; + last &= 0x0FFF; + } + + first *= pagesize; + last *= pagesize; } - return layout->highmem + value * pagesize; -} + *begin = layout->highmem + first; + *end = layout->highmem + last + pagesize; - -static unsigned int -get_profile_last (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize) -{ - unsigned int value; - - if (layout->pt_mode_logbook == 0) { - value = array_uint16_le (data + 6) >> 4; - } else if (layout->pt_mode_logbook == 1) { - value = array_uint16_le (data + 6); - } else if (layout->pt_mode_logbook == 2) { - value = array_uint16_le (data + 18); - } else { - return array_uint16_le(data + 18); - } - - unsigned int npages = (layout->memsize - layout->highmem) / pagesize; - - if (npages > 0x4000) { - value &= 0x7FFF; - } else if (npages > 0x2000) { - value &= 0x3FFF; - } else if (npages > 0x1000) { - value &= 0x1FFF; - } else { - value &= 0x0FFF; - } - - return layout->highmem + value * pagesize; + return DC_STATUS_SUCCESS; } @@ -403,9 +391,6 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr const oceanic_common_layout_t *layout = device->layout; - // Get the pagesize - unsigned int pagesize = layout->highmem ? 16 * PAGESIZE : PAGESIZE; - // Cache the logbook pointer and size. const unsigned char *logbooks = dc_buffer_get_data (logbook); unsigned int rb_logbook_size = dc_buffer_get_size (logbook); @@ -434,33 +419,31 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr } // Get the profile pointers. - unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize); - unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize); - if (rb_entry_first < layout->rb_profile_begin || - rb_entry_first >= layout->rb_profile_end || - rb_entry_last < layout->rb_profile_begin || - rb_entry_last >= layout->rb_profile_end) + unsigned int rb_entry_begin = 0, rb_entry_end = 0; + oceanic_common_device_get_profile (logbooks + entry, layout, &rb_entry_begin, &rb_entry_end); + if (rb_entry_begin < layout->rb_profile_begin || + rb_entry_begin > layout->rb_profile_end || + rb_entry_end < layout->rb_profile_begin || + rb_entry_end > layout->rb_profile_end) { ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).", - rb_entry_first, rb_entry_last); + rb_entry_begin, rb_entry_end); status = DC_STATUS_DATAFORMAT; continue; } - // Calculate the end pointer and the number of bytes. - unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, pagesize, layout); - unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize; - // Take the end pointer of the most recent logbook entry as the // end of profile pointer. if (rb_profile_end == INVALID) { rb_profile_end = previous = rb_entry_end; } + // Calculate the number of bytes. + unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_begin, rb_entry_end, layout, DC_RINGBUFFER_FULL); + // Skip gaps between the profiles. - unsigned int gap = 0; - if (rb_entry_end != previous) { - gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout); + unsigned int gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout, DC_RINGBUFFER_EMPTY); + if (gap) { WARNING (abstract->context, "Profiles are not continuous (%u bytes).", gap); } @@ -474,7 +457,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr rb_profile_size += rb_entry_size + gap; remaining -= rb_entry_size + gap; - previous = rb_entry_first; + previous = rb_entry_begin; } // At this point, we know the exact amount of data @@ -524,27 +507,25 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr } // Get the profile pointers. - unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize); - unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize); - if (rb_entry_first < layout->rb_profile_begin || - rb_entry_first >= layout->rb_profile_end || - rb_entry_last < layout->rb_profile_begin || - rb_entry_last >= layout->rb_profile_end) + unsigned int rb_entry_begin = 0, rb_entry_end = 0; + oceanic_common_device_get_profile (logbooks + entry, layout, &rb_entry_begin, &rb_entry_end); + if (rb_entry_begin < layout->rb_profile_begin || + rb_entry_begin > layout->rb_profile_end || + rb_entry_end < layout->rb_profile_begin || + rb_entry_end > layout->rb_profile_end) { ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).", - rb_entry_first, rb_entry_last); + rb_entry_begin, rb_entry_end); status = DC_STATUS_DATAFORMAT; continue; } - // Calculate the end pointer and the number of bytes. - unsigned int rb_entry_end = RB_PROFILE_INCR (rb_entry_last, pagesize, layout); - unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize; + // Calculate the number of bytes. + unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_begin, rb_entry_end, layout, DC_RINGBUFFER_FULL); // Skip gaps between the profiles. - unsigned int gap = 0; - if (rb_entry_end != previous) { - gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout); + unsigned int gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout, DC_RINGBUFFER_EMPTY); + if (gap) { WARNING (abstract->context, "Profiles are not continuous (%u bytes).", gap); } @@ -566,7 +547,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr } remaining -= rb_entry_size + gap; - previous = rb_entry_first; + previous = rb_entry_begin; // Prepend the logbook entry to the profile data. The memory buffer is // large enough to store this entry. From ae292253ba0673059823d5a412a26f16f71b1353 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 27 Nov 2023 21:03:58 +0100 Subject: [PATCH 3/7] Refactor the code to read the device info Move the code to read and emit the device info into a separate function to reduce some code duplication. As a side effect, the check for devices without a logbook and profile ringbuffer needs to be performed earlier now, in order to prevent a division by zero in the progress events. --- src/oceanic_atom2.c | 1 + src/oceanic_common.c | 96 ++++++++++++++++++++++++-------------------- src/oceanic_common.h | 4 ++ src/oceanic_veo250.c | 1 + src/oceanic_vtpro.c | 1 + 5 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 5eb60a6..2b90448 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -86,6 +86,7 @@ static const oceanic_common_device_vtable_t oceanic_atom2_device_vtable = { NULL, /* timesync */ oceanic_atom2_device_close /* close */ }, + oceanic_common_device_devinfo, oceanic_common_device_logbook, oceanic_common_device_profile, }; diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 4b5ee60..b13c289 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -194,11 +194,11 @@ oceanic_common_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) return DC_STATUS_NOMEMORY; } - // Emit a vendor event. - dc_event_vendor_t vendor; - vendor.data = device->version; - vendor.size = sizeof (device->version); - device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); + // Read the device info. + status = VTABLE(abstract)->devinfo (abstract, NULL); + if (status != DC_STATUS_SUCCESS) { + return status; + } // Download the memory dump. status = device_dump_read (abstract, 0, dc_buffer_get_data (buffer), @@ -207,8 +207,43 @@ oceanic_common_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) return status; } + return status; +} + + +dc_status_t +oceanic_common_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progress) +{ + dc_status_t status = DC_STATUS_SUCCESS; + oceanic_common_device_t *device = (oceanic_common_device_t *) abstract; + + assert (device != NULL); + assert (device->layout != NULL); + + const oceanic_common_layout_t *layout = device->layout; + + // Read the device id. + unsigned char id[PAGESIZE] = {0}; + status = dc_device_read (abstract, layout->cf_devinfo, id, sizeof (id)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read the memory page."); + return status; + } + + // Update and emit a progress event. + if (progress) { + progress->current += PAGESIZE; + progress->maximum += PAGESIZE; + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } + + // Emit a vendor event. + dc_event_vendor_t vendor; + vendor.data = device->version; + vendor.size = sizeof (device->version); + device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); + // Emit a device info event. - unsigned char *id = dc_buffer_get_data (buffer) + layout->cf_devinfo; dc_event_devinfo_t devinfo; devinfo.model = array_uint16_be (id + 8); devinfo.firmware = device->firmware; @@ -244,13 +279,6 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr if (!dc_buffer_clear (logbook)) return DC_STATUS_NOMEMORY; - // For devices without a logbook ringbuffer, downloading dives isn't - // possible. This is not considered a fatal error, but handled as if there - // are no dives present. - if (layout->rb_logbook_begin == layout->rb_logbook_end) { - return DC_STATUS_SUCCESS; - } - // Read the pointer data. unsigned char pointers[PAGESIZE] = {0}; rc = dc_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers)); @@ -585,6 +613,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr dc_status_t oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) { + dc_status_t rc = DC_STATUS_SUCCESS; oceanic_common_device_t *device = (oceanic_common_device_t *) abstract; assert (device != NULL); @@ -592,46 +621,27 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac const oceanic_common_layout_t *layout = device->layout; + // For devices without a logbook and profile ringbuffer, downloading dives + // isn't possible. This is not considered a fatal error, but handled as if + // there are no dives present. + if (layout->rb_logbook_begin == layout->rb_logbook_end && + layout->rb_profile_begin == layout->rb_profile_end) { + return DC_STATUS_SUCCESS; + } + // Enable progress notifications. dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; - progress.maximum = PAGESIZE + + progress.maximum = (layout->rb_logbook_end - layout->rb_logbook_begin) + (layout->rb_profile_end - layout->rb_profile_begin); device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); - // Emit a vendor event. - dc_event_vendor_t vendor; - vendor.data = device->version; - vendor.size = sizeof (device->version); - device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); - - // Read the device id. - unsigned char id[PAGESIZE] = {0}; - dc_status_t rc = dc_device_read (abstract, layout->cf_devinfo, id, sizeof (id)); + // Read the device info. + rc = VTABLE(abstract)->devinfo (abstract, &progress); if (rc != DC_STATUS_SUCCESS) { - ERROR (abstract->context, "Failed to read the memory page."); return rc; } - // Update and emit a progress event. - progress.current += PAGESIZE; - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); - - // Emit a device info event. - dc_event_devinfo_t devinfo; - devinfo.model = array_uint16_be (id + 8); - devinfo.firmware = device->firmware; - if (layout->pt_mode_serial == 0) - devinfo.serial = array_convert_bcd2dec (id + 10, 3); - else if (layout->pt_mode_serial == 1) - devinfo.serial = array_convert_bin2dec (id + 11, 3); - else - devinfo.serial = - (id[11] & 0x0F) * 100000 + ((id[11] & 0xF0) >> 4) * 10000 + - (id[12] & 0x0F) * 1000 + ((id[12] & 0xF0) >> 4) * 100 + - (id[13] & 0x0F) * 10 + ((id[13] & 0xF0) >> 4) * 1; - device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); - // Memory buffer for the logbook data. dc_buffer_t *logbook = dc_buffer_new (0); if (logbook == NULL) { diff --git a/src/oceanic_common.h b/src/oceanic_common.h index 045dca4..307b6a2 100644 --- a/src/oceanic_common.h +++ b/src/oceanic_common.h @@ -168,6 +168,7 @@ typedef struct oceanic_common_device_t { typedef struct oceanic_common_device_vtable_t { dc_device_vtable_t base; + dc_status_t (*devinfo) (dc_device_t *device, dc_event_progress_t *progress); dc_status_t (*logbook) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook); dc_status_t (*profile) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata); } oceanic_common_device_vtable_t; @@ -185,6 +186,9 @@ oceanic_common_match (const unsigned char *version, const oceanic_common_version void oceanic_common_device_init (oceanic_common_device_t *device); +dc_status_t +oceanic_common_device_devinfo (dc_device_t *device, dc_event_progress_t *progress); + dc_status_t oceanic_common_device_logbook (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook); diff --git a/src/oceanic_veo250.c b/src/oceanic_veo250.c index 58a9ceb..b4030ad 100644 --- a/src/oceanic_veo250.c +++ b/src/oceanic_veo250.c @@ -58,6 +58,7 @@ static const oceanic_common_device_vtable_t oceanic_veo250_device_vtable = { NULL, /* timesync */ oceanic_veo250_device_close /* close */ }, + oceanic_common_device_devinfo, oceanic_common_device_logbook, oceanic_common_device_profile, }; diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index d7e9882..40afe80 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -67,6 +67,7 @@ static const oceanic_common_device_vtable_t oceanic_vtpro_device_vtable = { NULL, /* timesync */ oceanic_vtpro_device_close /* close */ }, + oceanic_common_device_devinfo, oceanic_vtpro_device_logbook, oceanic_common_device_profile, }; From b9d76845521fdba09a41955231b705004c7bacb6 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 27 Nov 2023 21:34:12 +0100 Subject: [PATCH 4/7] Refactor the code to read the ringbuffer pointers Move the code to read the ringbuffer pointers into a separate function that deals with all the quirks internally and simply returns two begin/end pairs. To obtain the logbook end pointer, the page size is now added to the value of the last pointer without taking into account the ringbuffer boundaries. Therefore the boundary checks in the caller need to be relaxed to accept the end pointer as a valid value. The profile begin/end pointers are not used anywhere and are only retrieved for diagnostics purposes. --- src/oceanic_atom2.c | 1 + src/oceanic_common.c | 97 +++++++++++++++++++++++++++++--------------- src/oceanic_common.h | 10 ++++- src/oceanic_veo250.c | 1 + src/oceanic_vtpro.c | 89 +++++++++++++++++++++++++++++----------- 5 files changed, 140 insertions(+), 58 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 2b90448..d520e0e 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -87,6 +87,7 @@ static const oceanic_common_device_vtable_t oceanic_atom2_device_vtable = { oceanic_atom2_device_close /* close */ }, oceanic_common_device_devinfo, + oceanic_common_device_pointers, oceanic_common_device_logbook, oceanic_common_device_profile, }; diff --git a/src/oceanic_common.c b/src/oceanic_common.c index b13c289..f9edc7c 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -32,8 +32,7 @@ #define VTABLE(abstract) ((const oceanic_common_device_vtable_t *) abstract->vtable) -#define RB_LOGBOOK_DISTANCE(a,b,l) ringbuffer_distance (a, b, DC_RINGBUFFER_FULL, l->rb_logbook_begin, l->rb_logbook_end) -#define RB_LOGBOOK_INCR(a,b,l) ringbuffer_increment (a, b, l->rb_logbook_begin, l->rb_logbook_end) +#define RB_LOGBOOK_DISTANCE(a,b,l,m) ringbuffer_distance (a, b, m, l->rb_logbook_begin, l->rb_logbook_end) #define RB_PROFILE_DISTANCE(a,b,l,m) ringbuffer_distance (a, b, m, l->rb_profile_begin, l->rb_profile_end) @@ -263,7 +262,51 @@ oceanic_common_device_devinfo (dc_device_t *abstract, dc_event_progress_t *progr dc_status_t -oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook) +oceanic_common_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, + unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, + unsigned int *rb_profile_begin, unsigned int *rb_profile_end) +{ + dc_status_t status = DC_STATUS_SUCCESS; + oceanic_common_device_t *device = (oceanic_common_device_t *) abstract; + + assert (device != NULL); + assert (device->layout != NULL); + assert (rb_logbook_begin != NULL && rb_logbook_end != NULL); + assert (rb_profile_begin != NULL && rb_profile_end != NULL); + + const oceanic_common_layout_t *layout = device->layout; + + // Read the pointer data. + unsigned char pointers[PAGESIZE] = {0}; + status = dc_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read the memory page."); + return status; + } + + // Update and emit a progress event. + if (progress) { + progress->current += PAGESIZE; + progress->maximum += PAGESIZE; + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } + + // Get the pointers. + unsigned int rb_logbook_first = array_uint16_le (pointers + 4); + unsigned int rb_logbook_last = array_uint16_le (pointers + 6); + unsigned int rb_profile_first = array_uint16_le (pointers + 8); + unsigned int rb_profile_last = array_uint16_le (pointers + 10); + + *rb_logbook_begin = rb_logbook_first; + *rb_logbook_end = rb_logbook_last + (layout->pt_mode_global == 0 ? layout->rb_logbook_entry_size : 0); + *rb_profile_begin = rb_profile_first; + *rb_profile_end = rb_profile_last; + + return status; +} + +dc_status_t +oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end) { oceanic_common_device_t *device = (oceanic_common_device_t *) abstract; dc_status_t rc = DC_STATUS_SUCCESS; @@ -279,32 +322,16 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr if (!dc_buffer_clear (logbook)) return DC_STATUS_NOMEMORY; - // Read the pointer data. - unsigned char pointers[PAGESIZE] = {0}; - rc = dc_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers)); - if (rc != DC_STATUS_SUCCESS) { - ERROR (abstract->context, "Failed to read the memory page."); - return rc; - } - - // Get the logbook pointers. - unsigned int rb_logbook_first = array_uint16_le (pointers + 4); - unsigned int rb_logbook_last = array_uint16_le (pointers + 6); - if (rb_logbook_last < layout->rb_logbook_begin || - rb_logbook_last >= layout->rb_logbook_end) + // Validate the logbook pointers. + unsigned int rb_logbook_begin = begin; + unsigned int rb_logbook_end = end; + if (rb_logbook_end < layout->rb_logbook_begin || + rb_logbook_end > layout->rb_logbook_end) { - ERROR (abstract->context, "Invalid logbook end pointer detected (0x%04x).", rb_logbook_last); + ERROR (abstract->context, "Invalid logbook end pointer detected (0x%04x).", rb_logbook_end); return DC_STATUS_DATAFORMAT; } - // Calculate the end pointer. - unsigned int rb_logbook_end = 0; - if (layout->pt_mode_global == 0) { - rb_logbook_end = RB_LOGBOOK_INCR (rb_logbook_last, layout->rb_logbook_entry_size, layout); - } else { - rb_logbook_end = rb_logbook_last; - } - // Calculate the number of bytes. // In a typical ringbuffer implementation with only two begin/end // pointers, there is no distinction possible between an empty and a @@ -312,20 +339,18 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr // case, because an empty ringbuffer can be detected by inspecting // the logbook entries once they are downloaded. unsigned int rb_logbook_size = 0; - if (rb_logbook_first < layout->rb_logbook_begin || - rb_logbook_first >= layout->rb_logbook_end) + if (rb_logbook_begin < layout->rb_logbook_begin || + rb_logbook_begin > layout->rb_logbook_end) { // Fall back to downloading the entire logbook ringbuffer as // workaround for an invalid logbook begin pointer! - ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_first); + ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_begin); rb_logbook_size = layout->rb_logbook_end - layout->rb_logbook_begin; } else { - rb_logbook_size = RB_LOGBOOK_DISTANCE (rb_logbook_first, rb_logbook_end, layout); + rb_logbook_size = RB_LOGBOOK_DISTANCE (rb_logbook_begin, rb_logbook_end, layout, DC_RINGBUFFER_FULL); } // Update and emit a progress event. - progress->current += PAGESIZE; - progress->maximum += PAGESIZE; progress->maximum -= (layout->rb_logbook_end - layout->rb_logbook_begin) - rb_logbook_size; device_event_emit (abstract, DC_EVENT_PROGRESS, progress); @@ -642,6 +667,14 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac return rc; } + // Read the ringbuffer pointers. + unsigned int rb_logbook_begin = 0, rb_logbook_end = 0; + unsigned int rb_profile_begin = 0, rb_profile_end = 0; + rc = VTABLE(abstract)->pointers (abstract, &progress, &rb_logbook_begin, &rb_logbook_end, &rb_profile_begin, &rb_profile_end); + if (rc != DC_STATUS_SUCCESS) { + return rc; + } + // Memory buffer for the logbook data. dc_buffer_t *logbook = dc_buffer_new (0); if (logbook == NULL) { @@ -649,7 +682,7 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac } // Download the logbook ringbuffer. - rc = VTABLE(abstract)->logbook (abstract, &progress, logbook); + rc = VTABLE(abstract)->logbook (abstract, &progress, logbook, rb_logbook_begin, rb_logbook_end); if (rc != DC_STATUS_SUCCESS) { dc_buffer_free (logbook); return rc; diff --git a/src/oceanic_common.h b/src/oceanic_common.h index 307b6a2..b4291f7 100644 --- a/src/oceanic_common.h +++ b/src/oceanic_common.h @@ -169,7 +169,8 @@ typedef struct oceanic_common_device_t { typedef struct oceanic_common_device_vtable_t { dc_device_vtable_t base; dc_status_t (*devinfo) (dc_device_t *device, dc_event_progress_t *progress); - dc_status_t (*logbook) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook); + dc_status_t (*pointers) (dc_device_t *device, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end); + dc_status_t (*logbook) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end); dc_status_t (*profile) (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata); } oceanic_common_device_vtable_t; @@ -190,7 +191,12 @@ dc_status_t oceanic_common_device_devinfo (dc_device_t *device, dc_event_progress_t *progress); dc_status_t -oceanic_common_device_logbook (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook); +oceanic_common_device_pointers (dc_device_t *device, dc_event_progress_t *progress, + unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, + unsigned int *rb_profile_begin, unsigned int *rb_profile_end); + +dc_status_t +oceanic_common_device_logbook (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end); dc_status_t oceanic_common_device_profile (dc_device_t *device, dc_event_progress_t *progress, dc_buffer_t *logbook, dc_dive_callback_t callback, void *userdata); diff --git a/src/oceanic_veo250.c b/src/oceanic_veo250.c index b4030ad..82f73c7 100644 --- a/src/oceanic_veo250.c +++ b/src/oceanic_veo250.c @@ -59,6 +59,7 @@ static const oceanic_common_device_vtable_t oceanic_veo250_device_vtable = { oceanic_veo250_device_close /* close */ }, oceanic_common_device_devinfo, + oceanic_common_device_pointers, oceanic_common_device_logbook, oceanic_common_device_profile, }; diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index 40afe80..cba7fcc 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -51,7 +51,8 @@ typedef struct oceanic_vtpro_device_t { oceanic_vtpro_protocol_t protocol; } oceanic_vtpro_device_t; -static dc_status_t oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook); +static dc_status_t oceanic_vtpro_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end); +static dc_status_t oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end); static dc_status_t oceanic_vtpro_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size); static dc_status_t oceanic_vtpro_device_close (dc_device_t *abstract); @@ -68,6 +69,7 @@ static const oceanic_common_device_vtable_t oceanic_vtpro_device_vtable = { oceanic_vtpro_device_close /* close */ }, oceanic_common_device_devinfo, + oceanic_vtpro_device_pointers, oceanic_vtpro_device_logbook, oceanic_common_device_profile, }; @@ -287,7 +289,49 @@ oceanic_vtpro_calibrate (oceanic_vtpro_device_t *device) } static dc_status_t -oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook) +oceanic_aeris500ai_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end) +{ + dc_status_t status = DC_STATUS_SUCCESS; + oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract; + + assert (device != NULL); + assert (device->base.layout != NULL); + assert (rb_logbook_begin != NULL && rb_logbook_end != NULL); + assert (rb_profile_begin != NULL && rb_profile_end != NULL); + + const oceanic_common_layout_t *layout = device->base.layout; + + // Read the pointer data. + unsigned char pointers[PAGESIZE] = {0}; + status = oceanic_vtpro_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers)); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read the memory page."); + return status; + } + + // Update and emit a progress event. + if (progress) { + progress->current += PAGESIZE; + progress->maximum += PAGESIZE; + device_event_emit (abstract, DC_EVENT_PROGRESS, progress); + } + + // Get the pointers. + unsigned int rb_logbook_first = pointers[0x02]; + unsigned int rb_logbook_last = pointers[0x03]; + unsigned int rb_profile_first = array_uint16_le (pointers + 4) * PAGESIZE; + unsigned int rb_profile_last = array_uint16_le (pointers + 6) * PAGESIZE; + + *rb_logbook_begin = rb_logbook_first; + *rb_logbook_end = rb_logbook_last; + *rb_profile_begin = rb_profile_first; + *rb_profile_end = rb_profile_last; + + return status; +} + +static dc_status_t +oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end) { dc_status_t rc = DC_STATUS_SUCCESS; oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract; @@ -298,30 +342,15 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p assert (device->base.layout->rb_logbook_begin == device->base.layout->rb_logbook_end); assert (progress != NULL); - const oceanic_common_layout_t *layout = device->base.layout; - // Erase the buffer. if (!dc_buffer_clear (logbook)) return DC_STATUS_NOMEMORY; - // Read the pointer data. - unsigned char pointers[PAGESIZE] = {0}; - rc = oceanic_vtpro_device_read (abstract, layout->cf_pointers, pointers, sizeof (pointers)); - if (rc != DC_STATUS_SUCCESS) { - ERROR (abstract->context, "Failed to read the memory page."); - return rc; - } - - // Get the logbook pointers. - unsigned int first = pointers[0x02]; - unsigned int last = pointers[0x03]; - // Get the number of dives. - unsigned int ndives = last - first + 1; + unsigned int ndives = end - begin + 1; // Update and emit a progress event. - progress->current += PAGESIZE; - progress->maximum += PAGESIZE + ndives * PAGESIZE / 2; + progress->maximum += ndives * PAGESIZE / 2; device_event_emit (abstract, DC_EVENT_PROGRESS, progress); // Allocate memory for the logbook entries. @@ -330,8 +359,8 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p // Send the logbook index command. unsigned char command[] = {0x52, - first & 0xFF, - last & 0xFF, + begin & 0xFF, + end & 0xFF, 0x00}; rc = oceanic_vtpro_transfer (device, command, sizeof (command), NULL, 0); if (rc != DC_STATUS_SUCCESS) { @@ -379,14 +408,26 @@ oceanic_aeris500ai_device_logbook (dc_device_t *abstract, dc_event_progress_t *p } static dc_status_t -oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook) +oceanic_vtpro_device_pointers (dc_device_t *abstract, dc_event_progress_t *progress, unsigned int *rb_logbook_begin, unsigned int *rb_logbook_end, unsigned int *rb_profile_begin, unsigned int *rb_profile_end) { oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract; if (device->base.model == AERIS500AI) { - return oceanic_aeris500ai_device_logbook (abstract, progress, logbook); + return oceanic_aeris500ai_device_pointers (abstract, progress, rb_logbook_begin, rb_logbook_end, rb_profile_begin, rb_profile_end); } else { - return oceanic_common_device_logbook (abstract, progress, logbook); + return oceanic_common_device_pointers (abstract, progress, rb_logbook_begin, rb_logbook_end, rb_profile_begin, rb_profile_end); + } +} + +static dc_status_t +oceanic_vtpro_device_logbook (dc_device_t *abstract, dc_event_progress_t *progress, dc_buffer_t *logbook, unsigned int begin, unsigned int end) +{ + oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t *) abstract; + + if (device->base.model == AERIS500AI) { + return oceanic_aeris500ai_device_logbook (abstract, progress, logbook, begin, end); + } else { + return oceanic_common_device_logbook (abstract, progress, logbook, begin, end); } } From f49af5208c0b0ea800796b5fe9a46512b3157b23 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 5 Mar 2024 21:23:10 +0100 Subject: [PATCH 5/7] Separate the error handling from the size calculation --- src/oceanic_common.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/oceanic_common.c b/src/oceanic_common.c index f9edc7c..44e0781 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -325,6 +325,14 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr // Validate the logbook pointers. unsigned int rb_logbook_begin = begin; unsigned int rb_logbook_end = end; + if (rb_logbook_begin < layout->rb_logbook_begin || + rb_logbook_begin > layout->rb_logbook_end) + { + ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_begin); + // Fall back to downloading the entire logbook ringbuffer as + // workaround for an invalid logbook begin pointer! + rb_logbook_begin = rb_logbook_end; + } if (rb_logbook_end < layout->rb_logbook_begin || rb_logbook_end > layout->rb_logbook_end) { @@ -338,17 +346,7 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr // full ringbuffer. We always consider the ringbuffer full in that // case, because an empty ringbuffer can be detected by inspecting // the logbook entries once they are downloaded. - unsigned int rb_logbook_size = 0; - if (rb_logbook_begin < layout->rb_logbook_begin || - rb_logbook_begin > layout->rb_logbook_end) - { - // Fall back to downloading the entire logbook ringbuffer as - // workaround for an invalid logbook begin pointer! - ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_begin); - rb_logbook_size = layout->rb_logbook_end - layout->rb_logbook_begin; - } else { - rb_logbook_size = RB_LOGBOOK_DISTANCE (rb_logbook_begin, rb_logbook_end, layout, DC_RINGBUFFER_FULL); - } + unsigned int rb_logbook_size = RB_LOGBOOK_DISTANCE (rb_logbook_begin, rb_logbook_end, layout, DC_RINGBUFFER_FULL); // Update and emit a progress event. progress->maximum -= (layout->rb_logbook_end - layout->rb_logbook_begin) - rb_logbook_size; From 4cc0bc25ae818c4128355aedf73b48e0a50412b9 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 4 Mar 2024 21:38:07 +0100 Subject: [PATCH 6/7] Support reading the logbook in forward direction To prepare the code to support reading the logbook ringbuffer in the forward direction, a new field is added to the layout data structure to indicate the direction of the ringbuffer, the workaround for handling an invalid pointer is extended to support both directions, and finally the correct parameters are passed to the rbstream reader. --- src/oceanic_atom2.c | 21 +++++++++++++++++++++ src/oceanic_common.c | 16 ++++++++++++++-- src/oceanic_common.h | 1 + src/oceanic_veo250.c | 1 + src/oceanic_vtpro.c | 3 +++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index d520e0e..69ab7d5 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -100,6 +100,7 @@ static const oceanic_common_layout_t aeris_f10_layout = { 0x0100, /* rb_logbook_begin */ 0x0D80, /* rb_logbook_end */ 32, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0D80, /* rb_profile_begin */ 0x10000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -115,6 +116,7 @@ static const oceanic_common_layout_t aeris_f11_layout = { 0x0100, /* rb_logbook_begin */ 0x0D80, /* rb_logbook_end */ 32, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0D80, /* rb_profile_begin */ 0x20000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -130,6 +132,7 @@ static const oceanic_common_layout_t oceanic_default_layout = { 0x0240, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0x10000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -145,6 +148,7 @@ static const oceanic_common_layout_t oceanic_atom1_layout = { 0x0240, /* rb_logbook_begin */ 0x0440, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0440, /* rb_profile_begin */ 0x8000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -160,6 +164,7 @@ static const oceanic_common_layout_t oceanic_atom2a_layout = { 0x0240, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0xFE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -175,6 +180,7 @@ static const oceanic_common_layout_t oceanic_atom2b_layout = { 0x0240, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0xFE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -190,6 +196,7 @@ static const oceanic_common_layout_t oceanic_atom2c_layout = { 0x0240, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0xFFF0, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -205,6 +212,7 @@ static const oceanic_common_layout_t sherwood_wisdom_layout = { 0x03D0, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0xFE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -220,6 +228,7 @@ static const oceanic_common_layout_t oceanic_proplus3_layout = { 0x03E0, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0xFE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -235,6 +244,7 @@ static const oceanic_common_layout_t tusa_zenair_layout = { 0x0240, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0xFE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -250,6 +260,7 @@ static const oceanic_common_layout_t oceanic_oc1_layout = { 0x0240, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0x1FE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -265,6 +276,7 @@ static const oceanic_common_layout_t oceanic_oci_layout = { 0x10C0, /* rb_logbook_begin */ 0x1400, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x1400, /* rb_profile_begin */ 0x1FE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -280,6 +292,7 @@ static const oceanic_common_layout_t oceanic_atom3_layout = { 0x0400, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0x1FE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -295,6 +308,7 @@ static const oceanic_common_layout_t oceanic_vt4_layout = { 0x0420, /* rb_logbook_begin */ 0x0A40, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0A40, /* rb_profile_begin */ 0x1FE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -310,6 +324,7 @@ static const oceanic_common_layout_t hollis_tx1_layout = { 0x0780, /* rb_logbook_begin */ 0x1000, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x1000, /* rb_profile_begin */ 0x40000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -325,6 +340,7 @@ static const oceanic_common_layout_t oceanic_veo1_layout = { 0x0400, /* rb_logbook_begin */ 0x0400, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0400, /* rb_profile_begin */ 0x0400, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -340,6 +356,7 @@ static const oceanic_common_layout_t oceanic_reactpro_layout = { 0x0400, /* rb_logbook_begin */ 0x0600, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0600, /* rb_profile_begin */ 0xFE00, /* rb_profile_end */ 1, /* pt_mode_global */ @@ -355,6 +372,7 @@ static const oceanic_common_layout_t oceanic_proplusx_layout = { 0x1000, /* rb_logbook_begin */ 0x10000, /* rb_logbook_end */ 16, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x40000, /* rb_profile_begin */ 0x440000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -370,6 +388,7 @@ static const oceanic_common_layout_t aqualung_i770r_layout = { 0x2000, /* rb_logbook_begin */ 0x10000, /* rb_logbook_end */ 16, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x40000, /* rb_profile_begin */ 0x640000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -385,6 +404,7 @@ static const oceanic_common_layout_t aeris_a300cs_layout = { 0x0900, /* rb_logbook_begin */ 0x1000, /* rb_logbook_end */ 16, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x1000, /* rb_profile_begin */ 0x3FE00, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -400,6 +420,7 @@ static const oceanic_common_layout_t aqualung_i450t_layout = { 0x10C0, /* rb_logbook_begin */ 0x1400, /* rb_logbook_end */ 16, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x1400, /* rb_profile_begin */ 0x3FE00, /* rb_profile_end */ 0, /* pt_mode_global */ diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 44e0781..2d54fb7 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -329,6 +329,9 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr rb_logbook_begin > layout->rb_logbook_end) { ERROR (abstract->context, "Invalid logbook begin pointer detected (0x%04x).", rb_logbook_begin); + if (layout->rb_logbook_direction == 0) { + return DC_STATUS_DATAFORMAT; + } // Fall back to downloading the entire logbook ringbuffer as // workaround for an invalid logbook begin pointer! rb_logbook_begin = rb_logbook_end; @@ -337,7 +340,12 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr rb_logbook_end > layout->rb_logbook_end) { ERROR (abstract->context, "Invalid logbook end pointer detected (0x%04x).", rb_logbook_end); - return DC_STATUS_DATAFORMAT; + if (layout->rb_logbook_direction != 0) { + return DC_STATUS_DATAFORMAT; + } + // Fall back to downloading the entire logbook ringbuffer as + // workaround for an invalid logbook end pointer! + rb_logbook_end = rb_logbook_begin; } // Calculate the number of bytes. @@ -366,7 +374,11 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr // Create the ringbuffer stream. dc_rbstream_t *rbstream = NULL; - rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_logbook_begin, layout->rb_logbook_end, rb_logbook_end, DC_RBSTREAM_BACKWARD); + rc = dc_rbstream_new (&rbstream, abstract, + PAGESIZE, PAGESIZE * device->multipage, + layout->rb_logbook_begin, layout->rb_logbook_end, + layout->rb_logbook_direction ? rb_logbook_end : rb_logbook_begin, + layout->rb_logbook_direction ? DC_RBSTREAM_BACKWARD : DC_RBSTREAM_FORWARD); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to create the ringbuffer stream."); return rc; diff --git a/src/oceanic_common.h b/src/oceanic_common.h index b4291f7..b468b07 100644 --- a/src/oceanic_common.h +++ b/src/oceanic_common.h @@ -144,6 +144,7 @@ typedef struct oceanic_common_layout_t { unsigned int rb_logbook_begin; unsigned int rb_logbook_end; unsigned int rb_logbook_entry_size; + unsigned int rb_logbook_direction; // Profile ringbuffer unsigned int rb_profile_begin; unsigned int rb_profile_end; diff --git a/src/oceanic_veo250.c b/src/oceanic_veo250.c index 82f73c7..f39b1cd 100644 --- a/src/oceanic_veo250.c +++ b/src/oceanic_veo250.c @@ -72,6 +72,7 @@ static const oceanic_common_layout_t oceanic_veo250_layout = { 0x0400, /* rb_logbook_begin */ 0x0600, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0600, /* rb_profile_begin */ 0x8000, /* rb_profile_end */ 1, /* pt_mode_global */ diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index cba7fcc..b63c0fb 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -82,6 +82,7 @@ static const oceanic_common_layout_t oceanic_vtpro_layout = { 0x0240, /* rb_logbook_begin */ 0x0440, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x0440, /* rb_profile_begin */ 0x8000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -97,6 +98,7 @@ static const oceanic_common_layout_t oceanic_wisdom_layout = { 0x03D0, /* rb_logbook_begin */ 0x05D0, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x05D0, /* rb_profile_begin */ 0x8000, /* rb_profile_end */ 0, /* pt_mode_global */ @@ -112,6 +114,7 @@ static const oceanic_common_layout_t aeris_500ai_layout = { 0x0200, /* rb_logbook_begin */ 0x0200, /* rb_logbook_end */ 8, /* rb_logbook_entry_size */ + 1, /* rb_logbook_direction */ 0x00200, /* rb_profile_begin */ 0x20000, /* rb_profile_end */ 0, /* pt_mode_global */ From 9070b7d035c182a432dc25a4db1c9d5e52ff4f03 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 19 Mar 2024 19:46:13 +0100 Subject: [PATCH 7/7] Log the ringbuffer pointers Logging the ringbuffer pointers is very useful while investigating problems and adding support for new models. --- src/oceanic_common.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/oceanic_common.c b/src/oceanic_common.c index 2d54fb7..1e00047 100644 --- a/src/oceanic_common.c +++ b/src/oceanic_common.c @@ -461,6 +461,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr // Go through the logbook entries a first time, to get the end of // profile pointer and calculate the total amount of bytes in the // profile ringbuffer. + unsigned int rb_profile_begin = INVALID; unsigned int rb_profile_end = INVALID; unsigned int rb_profile_size = 0; @@ -495,6 +496,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr continue; } + DEBUG (abstract->context, "Entry: %08x %08x", rb_entry_begin, rb_entry_end); + // Take the end pointer of the most recent logbook entry as the // end of profile pointer. if (rb_profile_end == INVALID) { @@ -516,6 +519,9 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr break; } + // Update the profile begin pointer. + rb_profile_begin = rb_entry_begin; + // Update the total profile size. rb_profile_size += rb_entry_size + gap; @@ -523,6 +529,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr previous = rb_entry_begin; } + DEBUG (abstract->context, "Profile: %08x %08x", rb_profile_begin, rb_profile_end); + // At this point, we know the exact amount of data // that needs to be transfered for the profiles. progress->maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - rb_profile_size; @@ -583,6 +591,8 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr continue; } + DEBUG (abstract->context, "Entry: %08x %08x", rb_entry_begin, rb_entry_end); + // Calculate the number of bytes. unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_begin, rb_entry_end, layout, DC_RINGBUFFER_FULL); @@ -685,6 +695,9 @@ oceanic_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac return rc; } + DEBUG (abstract->context, "Logbook: %08x %08x", rb_logbook_begin, rb_logbook_end); + DEBUG (abstract->context, "Profile: %08x %08x", rb_profile_begin, rb_profile_end); + // Memory buffer for the logbook data. dc_buffer_t *logbook = dc_buffer_new (0); if (logbook == NULL) {