Merge branch 'rbstream'

This commit is contained in:
Jef Driesen 2024-03-14 12:26:07 +01:00
commit 04fe252625
10 changed files with 126 additions and 40 deletions

View File

@ -965,7 +965,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
last_start_address = base + array_uint32_le(data.config + layout->cf_last_log ); last_start_address = base + array_uint32_le(data.config + layout->cf_last_log );
// Create the ringbuffer stream. // Create the ringbuffer stream.
status = dc_rbstream_new (&rbstream, abstract, 1, layout->rbstream_size, layout->rb_profile_begin, layout->rb_profile_end, last_start_address); status = dc_rbstream_new (&rbstream, abstract, 1, layout->rbstream_size, layout->rb_profile_begin, layout->rb_profile_end, last_start_address, DC_RBSTREAM_BACKWARD);
if (status != DC_STATUS_SUCCESS) { if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
goto error; goto error;

View File

@ -481,7 +481,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
rc = dc_rbstream_new (&rbstream, abstract, SZ_PAGE, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, eop); rc = dc_rbstream_new (&rbstream, abstract, SZ_PAGE, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, eop, DC_RBSTREAM_BACKWARD);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
return rc; return rc;

View File

@ -469,7 +469,7 @@ liquivision_lynx_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rblogbook = NULL; dc_rbstream_t *rblogbook = NULL;
status = dc_rbstream_new (&rblogbook, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_LOGBOOK_BEGIN, RB_LOGBOOK_END, rb_logbook_end); status = dc_rbstream_new (&rblogbook, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_LOGBOOK_BEGIN, RB_LOGBOOK_END, rb_logbook_end, DC_RBSTREAM_BACKWARD);
if (status != DC_STATUS_SUCCESS) { if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
goto error_free_logbook; goto error_free_logbook;
@ -600,7 +600,7 @@ liquivision_lynx_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbprofile = NULL; dc_rbstream_t *rbprofile = NULL;
status = dc_rbstream_new (&rbprofile, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_PROFILE_BEGIN, RB_PROFILE_END, rb_profile_end); status = dc_rbstream_new (&rbprofile, abstract, SEGMENTSIZE, SEGMENTSIZE, RB_PROFILE_BEGIN, RB_PROFILE_END, rb_profile_end, DC_RBSTREAM_BACKWARD);
if (status != DC_STATUS_SUCCESS) { if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
goto error_free_profile; goto error_free_profile;

View File

@ -686,7 +686,7 @@ mares_iconhd_device_foreach_raw (dc_device_t *abstract, dc_dive_callback_t callb
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
rc = dc_rbstream_new (&rbstream, abstract, 1, device->packetsize, layout->rb_profile_begin, layout->rb_profile_end, eop); rc = dc_rbstream_new (&rbstream, abstract, 1, device->packetsize, layout->rb_profile_begin, layout->rb_profile_end, eop, DC_RBSTREAM_BACKWARD);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
return rc; return rc;

View File

@ -327,7 +327,7 @@ oceanic_common_device_logbook (dc_device_t *abstract, dc_event_progress_t *progr
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; 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); rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_logbook_begin, layout->rb_logbook_end, rb_logbook_end, DC_RBSTREAM_BACKWARD);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
return rc; return rc;
@ -489,7 +489,7 @@ oceanic_common_device_profile (dc_device_t *abstract, dc_event_progress_t *progr
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_profile_begin, layout->rb_profile_end, rb_profile_end); rc = dc_rbstream_new (&rbstream, abstract, PAGESIZE, PAGESIZE * device->multipage, layout->rb_profile_begin, layout->rb_profile_end, rb_profile_end, DC_RBSTREAM_BACKWARD);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
return rc; return rc;

View File

@ -28,11 +28,13 @@
struct dc_rbstream_t { struct dc_rbstream_t {
dc_device_t *device; dc_device_t *device;
dc_rbstream_direction_t direction;
unsigned int pagesize; unsigned int pagesize;
unsigned int packetsize; unsigned int packetsize;
unsigned int begin; unsigned int begin;
unsigned int end; unsigned int end;
unsigned int address; unsigned int address;
unsigned int offset;
unsigned int available; unsigned int available;
unsigned int skip; unsigned int skip;
unsigned char cache[]; unsigned char cache[];
@ -53,7 +55,7 @@ iceil (unsigned int x, unsigned int n)
} }
dc_status_t dc_status_t
dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address) dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address, dc_rbstream_direction_t direction)
{ {
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
@ -78,6 +80,18 @@ dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize
return DC_STATUS_INVALIDARGS; return DC_STATUS_INVALIDARGS;
} }
// Ringbuffer boundaries should not be reversed.
if (begin > end) {
ERROR (device->context, "Ringbuffer boundaries reversed!");
return DC_STATUS_INVALIDARGS;
}
// Packet size should be smaller than the ringbuffer size.
if (packetsize > (end - begin)) {
ERROR (device->context, "Packet size larger than the ringbuffer size!");
return DC_STATUS_INVALIDARGS;
}
// Address should be inside the ringbuffer. // Address should be inside the ringbuffer.
if (address < begin || address > end) { if (address < begin || address > end) {
ERROR (device->context, "Address outside the ringbuffer!"); ERROR (device->context, "Address outside the ringbuffer!");
@ -92,64 +106,64 @@ dc_rbstream_new (dc_rbstream_t **out, dc_device_t *device, unsigned int pagesize
} }
rbstream->device = device; rbstream->device = device;
rbstream->direction = direction;
rbstream->pagesize = pagesize; rbstream->pagesize = pagesize;
rbstream->packetsize = packetsize; rbstream->packetsize = packetsize;
rbstream->begin = begin; rbstream->begin = begin;
rbstream->end = end; rbstream->end = end;
rbstream->address = iceil(address, pagesize); if (direction == DC_RBSTREAM_FORWARD) {
rbstream->address = ifloor(address, pagesize);
rbstream->skip = address - rbstream->address;
} else {
rbstream->address = iceil(address, pagesize);
rbstream->skip = rbstream->address - address;
}
rbstream->offset = 0;
rbstream->available = 0; rbstream->available = 0;
rbstream->skip = rbstream->address - address;
*out = rbstream; *out = rbstream;
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;
} }
dc_status_t static dc_status_t
dc_rbstream_read (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size) dc_rbstream_read_backward (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
{ {
dc_status_t rc = DC_STATUS_SUCCESS; dc_status_t rc = DC_STATUS_SUCCESS;
if (rbstream == NULL)
return DC_STATUS_INVALIDARGS;
unsigned int address = rbstream->address;
unsigned int available = rbstream->available;
unsigned int skip = rbstream->skip;
unsigned int nbytes = 0; unsigned int nbytes = 0;
unsigned int offset = size; unsigned int offset = size;
while (nbytes < size) { while (nbytes < size) {
if (available == 0) { if (rbstream->available == 0) {
// Handle the ringbuffer wrap point. // Handle the ringbuffer wrap point.
if (address == rbstream->begin) if (rbstream->address == rbstream->begin)
address = rbstream->end; rbstream->address = rbstream->end;
// Calculate the packet size. // Calculate the packet size.
unsigned int len = rbstream->packetsize; unsigned int len = rbstream->packetsize;
if (rbstream->begin + len > address) if (rbstream->begin + len > rbstream->address)
len = address - rbstream->begin; len = rbstream->address - rbstream->begin;
// Move to the begin of the current packet.
address -= len;
// Read the packet into the cache. // Read the packet into the cache.
rc = dc_device_read (rbstream->device, address, rbstream->cache, rbstream->packetsize); rc = dc_device_read (rbstream->device, rbstream->address - len, rbstream->cache, rbstream->packetsize);
if (rc != DC_STATUS_SUCCESS) if (rc != DC_STATUS_SUCCESS)
return rc; return rc;
available = len - skip; // Move to the end of the next packet.
skip = 0; rbstream->address -= len;
rbstream->available = len - rbstream->skip;
rbstream->skip = 0;
} }
unsigned int length = available; unsigned int length = rbstream->available;
if (nbytes + length > size) if (nbytes + length > size)
length = size - nbytes; length = size - nbytes;
offset -= length; offset -= length;
available -= length; rbstream->available -= length;
memcpy (data + offset, rbstream->cache + available, length); memcpy (data + offset, rbstream->cache + rbstream->available, length);
// Update and emit a progress event. // Update and emit a progress event.
if (progress) { if (progress) {
@ -160,13 +174,76 @@ dc_rbstream_read (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsign
nbytes += length; nbytes += length;
} }
rbstream->address = address; return rc;
rbstream->available = available; }
rbstream->skip = skip;
static dc_status_t
dc_rbstream_read_forward (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
{
dc_status_t rc = DC_STATUS_SUCCESS;
unsigned int nbytes = 0;
while (nbytes < size) {
if (rbstream->available == 0) {
// Handle the ringbuffer wrap point.
if (rbstream->address == rbstream->end)
rbstream->address = rbstream->begin;
// Calculate the packet size.
unsigned int len = rbstream->packetsize;
if (rbstream->address + len > rbstream->end)
len = rbstream->end - rbstream->address;
// Calculate the excess number of bytes.
unsigned int extra = rbstream->packetsize - len;
// Read the packet into the cache.
rc = dc_device_read (rbstream->device, rbstream->address - extra, rbstream->cache, rbstream->packetsize);
if (rc != DC_STATUS_SUCCESS)
return rc;
// Move to the begin of the next packet.
rbstream->address += len;
rbstream->offset = extra + rbstream->skip;
rbstream->available = len - rbstream->skip;
rbstream->skip = 0;
}
unsigned int length = rbstream->available;
if (nbytes + length > size)
length = size - nbytes;
memcpy (data + nbytes, rbstream->cache + rbstream->offset, length);
rbstream->offset += length;
rbstream->available -= length;
// Update and emit a progress event.
if (progress) {
progress->current += length;
device_event_emit (rbstream->device, DC_EVENT_PROGRESS, progress);
}
nbytes += length;
}
return rc; return rc;
} }
dc_status_t
dc_rbstream_read (dc_rbstream_t *rbstream, dc_event_progress_t *progress, unsigned char data[], unsigned int size)
{
if (rbstream == NULL)
return DC_STATUS_INVALIDARGS;
if (rbstream->direction == DC_RBSTREAM_FORWARD) {
return dc_rbstream_read_forward (rbstream, progress, data, size);
} else {
return dc_rbstream_read_backward (rbstream, progress, data, size);
}
}
dc_status_t dc_status_t
dc_rbstream_free (dc_rbstream_t *rbstream) dc_rbstream_free (dc_rbstream_t *rbstream)
{ {

View File

@ -33,6 +33,14 @@ extern "C" {
*/ */
typedef struct dc_rbstream_t dc_rbstream_t; typedef struct dc_rbstream_t dc_rbstream_t;
/**
* The ringbuffer read direction.
*/
typedef enum dc_rbstream_direction_t {
DC_RBSTREAM_FORWARD,
DC_RBSTREAM_BACKWARD
} dc_rbstream_direction_t;
/** /**
* Create a new ringbuffer stream. * Create a new ringbuffer stream.
* *
@ -43,11 +51,12 @@ typedef struct dc_rbstream_t dc_rbstream_t;
* @param[in] begin The ringbuffer begin address. * @param[in] begin The ringbuffer begin address.
* @param[in] end The ringbuffer end address. * @param[in] end The ringbuffer end address.
* @param[in] address The stream start address. * @param[in] address The stream start address.
* @param[in] direction The ringbuffer read direction.
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code * @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
* on failure. * on failure.
*/ */
dc_status_t dc_status_t
dc_rbstream_new (dc_rbstream_t **rbstream, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address); dc_rbstream_new (dc_rbstream_t **rbstream, dc_device_t *device, unsigned int pagesize, unsigned int packetsize, unsigned int begin, unsigned int end, unsigned int address, dc_rbstream_direction_t direction);
/** /**
* Read data from the ringbuffer stream. * Read data from the ringbuffer stream.

View File

@ -546,7 +546,7 @@ seac_screen_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback,
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
status = dc_rbstream_new (&rbstream, abstract, SZ_READ, SZ_READ, RB_PROFILE_BEGIN, RB_PROFILE_END, eop); status = dc_rbstream_new (&rbstream, abstract, SZ_READ, SZ_READ, RB_PROFILE_BEGIN, RB_PROFILE_END, eop, DC_RBSTREAM_BACKWARD);
if (status != DC_STATUS_SUCCESS) { if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
goto error_free_profile; goto error_free_profile;

View File

@ -307,7 +307,7 @@ suunto_common2_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
rc = dc_rbstream_new (&rbstream, abstract, 1, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, end); rc = dc_rbstream_new (&rbstream, abstract, 1, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, end, DC_RBSTREAM_BACKWARD);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
return rc; return rc;

View File

@ -326,7 +326,7 @@ zeagle_n2ition3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callba
// Create the ringbuffer stream. // Create the ringbuffer stream.
dc_rbstream_t *rbstream = NULL; dc_rbstream_t *rbstream = NULL;
rc = dc_rbstream_new (&rbstream, abstract, 1, SZ_PACKET, RB_PROFILE_BEGIN, RB_PROFILE_END, eop); rc = dc_rbstream_new (&rbstream, abstract, 1, SZ_PACKET, RB_PROFILE_BEGIN, RB_PROFILE_END, eop, DC_RBSTREAM_BACKWARD);
if (rc != DC_STATUS_SUCCESS) { if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to create the ringbuffer stream."); ERROR (abstract->context, "Failed to create the ringbuffer stream.");
return rc; return rc;