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_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_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_DISTANCE(a,b,l,m) ringbuffer_distance (a, b, m, 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 INVALID 0 #define INVALID 0
static unsigned int static dc_status_t
get_profile_first (const unsigned char data[], const oceanic_common_layout_t *layout, unsigned int pagesize) 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) { 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) { } else if (layout->pt_mode_logbook == 1) {
value = array_uint16_le (data + 4); first = array_uint16_le (data + 4);
} else if (layout->pt_mode_logbook == 2) { last = array_uint16_le (data + 6);
value = array_uint16_le (data + 16); } else if (layout->pt_mode_logbook == 2 || layout->pt_mode_logbook == 3) {
} else { first = array_uint16_le (data + 16);
return array_uint16_le (data + 16); last = array_uint16_le (data + 18);
} }
// Convert pages to bytes.
if (layout->pt_mode_logbook < 3) {
unsigned int npages = (layout->memsize - layout->highmem) / pagesize; unsigned int npages = (layout->memsize - layout->highmem) / pagesize;
if (npages > 0x4000) { if (npages > 0x4000) {
value &= 0x7FFF; first &= 0x7FFF;
last &= 0x7FFF;
} else if (npages > 0x2000) { } else if (npages > 0x2000) {
value &= 0x3FFF; first &= 0x3FFF;
last &= 0x3FFF;
} else if (npages > 0x1000) { } else if (npages > 0x1000) {
value &= 0x1FFF; first &= 0x1FFF;
last &= 0x1FFF;
} else { } else {
value &= 0x0FFF; first &= 0x0FFF;
last &= 0x0FFF;
} }
return layout->highmem + value * pagesize; first *= pagesize;
last *= pagesize;
} }
*begin = layout->highmem + first;
*end = layout->highmem + last + pagesize;
static unsigned int return DC_STATUS_SUCCESS;
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;
} }
@ -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; 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. // Cache the logbook pointer and size.
const unsigned char *logbooks = dc_buffer_get_data (logbook); const unsigned char *logbooks = dc_buffer_get_data (logbook);
unsigned int rb_logbook_size = dc_buffer_get_size (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. // Get the profile pointers.
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize); unsigned int rb_entry_begin = 0, rb_entry_end = 0;
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize); oceanic_common_device_get_profile (logbooks + entry, layout, &rb_entry_begin, &rb_entry_end);
if (rb_entry_first < layout->rb_profile_begin || if (rb_entry_begin < layout->rb_profile_begin ||
rb_entry_first >= layout->rb_profile_end || rb_entry_begin > layout->rb_profile_end ||
rb_entry_last < layout->rb_profile_begin || rb_entry_end < layout->rb_profile_begin ||
rb_entry_last >= layout->rb_profile_end) rb_entry_end > layout->rb_profile_end)
{ {
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).", 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; status = DC_STATUS_DATAFORMAT;
continue; 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 // Take the end pointer of the most recent logbook entry as the
// end of profile pointer. // end of profile pointer.
if (rb_profile_end == INVALID) { if (rb_profile_end == INVALID) {
rb_profile_end = previous = rb_entry_end; 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. // Skip gaps between the profiles.
unsigned int gap = 0; unsigned int gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout, DC_RINGBUFFER_EMPTY);
if (rb_entry_end != previous) { if (gap) {
gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout);
WARNING (abstract->context, "Profiles are not continuous (%u bytes).", 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; rb_profile_size += rb_entry_size + gap;
remaining -= 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 // 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. // Get the profile pointers.
unsigned int rb_entry_first = get_profile_first (logbooks + entry, layout, pagesize); unsigned int rb_entry_begin = 0, rb_entry_end = 0;
unsigned int rb_entry_last = get_profile_last (logbooks + entry, layout, pagesize); oceanic_common_device_get_profile (logbooks + entry, layout, &rb_entry_begin, &rb_entry_end);
if (rb_entry_first < layout->rb_profile_begin || if (rb_entry_begin < layout->rb_profile_begin ||
rb_entry_first >= layout->rb_profile_end || rb_entry_begin > layout->rb_profile_end ||
rb_entry_last < layout->rb_profile_begin || rb_entry_end < layout->rb_profile_begin ||
rb_entry_last >= layout->rb_profile_end) rb_entry_end > layout->rb_profile_end)
{ {
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%06x 0x%06x).", 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; status = DC_STATUS_DATAFORMAT;
continue; continue;
} }
// Calculate the end pointer and the number of bytes. // Calculate 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_begin, rb_entry_end, layout, DC_RINGBUFFER_FULL);
unsigned int rb_entry_size = RB_PROFILE_DISTANCE (rb_entry_first, rb_entry_last, layout) + pagesize;
// Skip gaps between the profiles. // Skip gaps between the profiles.
unsigned int gap = 0; unsigned int gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout, DC_RINGBUFFER_EMPTY);
if (rb_entry_end != previous) { if (gap) {
gap = RB_PROFILE_DISTANCE (rb_entry_end, previous, layout);
WARNING (abstract->context, "Profiles are not continuous (%u bytes).", 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; 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 // Prepend the logbook entry to the profile data. The memory buffer is
// large enough to store this entry. // large enough to store this entry.