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.
This commit is contained in:
Jef Driesen 2024-02-07 20:39:38 +01:00
parent 121c7c12fb
commit a91a7dbc38

View File

@ -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.