From b3d2c603ddec9758fb36706bbde46ce23ca9f0ed Mon Sep 17 00:00:00 2001 From: John Van Ostrand Date: Wed, 31 May 2017 19:24:47 -0400 Subject: [PATCH] Retry read operations on failure [Jef Driesen: Modified to retry only for non-fatal errors.] --- src/cochran_commander.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/cochran_commander.c b/src/cochran_commander.c index e0c991f..2854c78 100644 --- a/src/cochran_commander.c +++ b/src/cochran_commander.c @@ -32,6 +32,8 @@ #define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array)) +#define MAXRETRIES 2 + #define COCHRAN_MODEL_COMMANDER_AIR_NITROX 0 #define COCHRAN_MODEL_EMC_14 1 #define COCHRAN_MODEL_EMC_16 2 @@ -435,6 +437,31 @@ cochran_commander_read (cochran_commander_device_t *device, dc_event_progress_t return DC_STATUS_SUCCESS; } +static unsigned int +cochran_commander_read_retry (cochran_commander_device_t *device, dc_event_progress_t *progress, unsigned int address, unsigned char data[], unsigned int size) +{ + // Save the state of the progress events. + unsigned int saved = progress->current; + + unsigned int nretries = 0; + dc_status_t rc = DC_STATUS_SUCCESS; + while ((rc = cochran_commander_read (device, progress, address, data, size)) != DC_STATUS_SUCCESS) { + // Automatically discard a corrupted packet, + // and request a new one. + if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT) + return rc; + + // Abort if the maximum number of retries is reached. + if (nretries++ >= MAXRETRIES) + return rc; + + // Restore the state of the progress events. + progress->current = saved; + } + + return rc; +} + /* * For corrupt dives the end-of-samples pointer is 0xFFFFFFFF @@ -890,7 +917,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call sample_end_address = cochran_commander_guess_sample_end_address(device, &data, i); if (sample_start_address <= sample_end_address) { - rc = cochran_commander_read (device, &progress, sample_start_address, dive + device->layout->rb_logbook_entry_size, sample_size); + rc = cochran_commander_read_retry (device, &progress, sample_start_address, dive + device->layout->rb_logbook_entry_size, sample_size); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the sample data."); status = rc; @@ -901,14 +928,15 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call // It wrapped the buffer, copy two sections unsigned int size = device->layout->rb_profile_end - sample_start_address; - rc = cochran_commander_read (device, &progress, sample_start_address, dive + device->layout->rb_logbook_entry_size, size); + rc = cochran_commander_read_retry (device, &progress, sample_start_address, dive + device->layout->rb_logbook_entry_size, size); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the sample data."); status = rc; free(dive); goto error; } - rc = cochran_commander_read (device, &progress, device->layout->rb_profile_begin, dive + device->layout->rb_logbook_entry_size + size, sample_end_address - device->layout->rb_profile_begin); + + rc = cochran_commander_read_retry (device, &progress, device->layout->rb_profile_begin, dive + device->layout->rb_logbook_entry_size + size, sample_end_address - device->layout->rb_profile_begin); if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to read the sample data."); status = rc;