From b9f7d4e42525223c0627ccdb140d12b8b663c8d4 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 18 Mar 2010 09:40:29 +0000 Subject: [PATCH] Improve the ACK/NAK error recovery to fix more errors. --- src/oceanic_atom2.c | 78 ++++++++++++++++++++++++-------------------- src/oceanic_veo250.c | 74 ++++++++++++++++++++++------------------- src/oceanic_vtpro.c | 68 ++++++++++++++++++++------------------ 3 files changed, 119 insertions(+), 101 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index b18791a..abcfd34 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -86,44 +86,26 @@ device_is_oceanic_atom2 (device_t *abstract) static device_status_t -oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +oceanic_atom2_send (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize) { device_t *abstract = (device_t *) device; - // Send the command to the device. If the device responds with an - // ACK byte, the command was received successfully and the answer - // (if any) follows after the ACK byte. If the device responds with - // a NAK byte, we try to resend the command a number of times before - // returning an error. + if (device_is_cancelled (abstract)) + return DEVICE_STATUS_CANCELLED; - unsigned int nretries = 0; + // Send the command to the dive computer. + int n = serial_write (device->port, command, csize); + if (n != csize) { + WARNING ("Failed to send the command."); + return EXITCODE (n); + } + + // Receive the response (ACK/NAK) of the dive computer. unsigned char response = NAK; - while (response == NAK) { - if (device_is_cancelled (abstract)) - return DEVICE_STATUS_CANCELLED; - - // Send the command to the dive computer. - int n = serial_write (device->port, command, csize); - if (n != csize) { - WARNING ("Failed to send the command."); - return EXITCODE (n); - } - - // Receive the response (ACK/NAK) of the dive computer. - n = serial_read (device->port, &response, 1); - if (n != 1) { - WARNING ("Failed to receive the answer."); - return EXITCODE (n); - } - -#ifndef NDEBUG - if (response != ACK) - message ("Received unexpected response (%02x).\n", response); -#endif - - // Abort if the maximum number of retries is reached. - if (nretries++ >= MAXRETRIES) - break; + n = serial_read (device->port, &response, 1); + if (n != 1) { + WARNING ("Failed to receive the answer."); + return EXITCODE (n); } // Verify the response of the dive computer. @@ -132,12 +114,36 @@ oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char comm return DEVICE_STATUS_PROTOCOL; } + return DEVICE_STATUS_SUCCESS; +} + + +static device_status_t +oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +{ + // Send the command to the device. If the device responds with an + // ACK byte, the command was received successfully and the answer + // (if any) follows after the ACK byte. If the device responds with + // a NAK byte, we try to resend the command a number of times before + // returning an error. + + unsigned int nretries = 0; + device_status_t rc = DEVICE_STATUS_SUCCESS; + while ((rc = oceanic_atom2_send (device, command, csize)) != DEVICE_STATUS_SUCCESS) { + if (rc != DEVICE_STATUS_TIMEOUT && rc != DEVICE_STATUS_PROTOCOL) + return rc; + + // Abort if the maximum number of retries is reached. + if (nretries++ >= MAXRETRIES) + return rc; + } + if (asize) { // Receive the answer of the dive computer. - int rc = serial_read (device->port, answer, asize); - if (rc != asize) { + int n = serial_read (device->port, answer, asize); + if (n != asize) { WARNING ("Failed to receive the answer."); - return EXITCODE (rc); + return EXITCODE (n); } // Verify the checksum of the answer. diff --git a/src/oceanic_veo250.c b/src/oceanic_veo250.c index 09ef6dd..9b03af3 100644 --- a/src/oceanic_veo250.c +++ b/src/oceanic_veo250.c @@ -87,10 +87,44 @@ device_is_oceanic_veo250 (device_t *abstract) static device_status_t -oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +oceanic_veo250_send (oceanic_veo250_device_t *device, const unsigned char command[], unsigned int csize) { device_t *abstract = (device_t *) device; + if (device_is_cancelled (abstract)) + return DEVICE_STATUS_CANCELLED; + + // Discard garbage bytes. + serial_flush (device->port, SERIAL_QUEUE_INPUT); + + // Send the command to the dive computer. + int n = serial_write (device->port, command, csize); + if (n != csize) { + WARNING ("Failed to send the command."); + return EXITCODE (n); + } + + // Receive the response (ACK/NAK) of the dive computer. + unsigned char response = NAK; + n = serial_read (device->port, &response, 1); + if (n != 1) { + WARNING ("Failed to receive the answer."); + return EXITCODE (n); + } + + // Verify the response of the dive computer. + if (response != ACK) { + WARNING ("Unexpected answer start byte(s)."); + return DEVICE_STATUS_PROTOCOL; + } + + return DEVICE_STATUS_SUCCESS; +} + + +static device_status_t +oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +{ // Send the command to the device. If the device responds with an // ACK byte, the command was received successfully and the answer // (if any) follows after the ACK byte. If the device responds with @@ -98,42 +132,14 @@ oceanic_veo250_transfer (oceanic_veo250_device_t *device, const unsigned char co // returning an error. unsigned int nretries = 0; - unsigned char response = NAK; - while (response == NAK) { - if (device_is_cancelled (abstract)) - return DEVICE_STATUS_CANCELLED; - - // Discard garbage bytes. - serial_flush (device->port, SERIAL_QUEUE_INPUT); - - // Send the command to the dive computer. - int n = serial_write (device->port, command, csize); - if (n != csize) { - WARNING ("Failed to send the command."); - return EXITCODE (n); - } - - // Receive the response (ACK/NAK) of the dive computer. - n = serial_read (device->port, &response, 1); - if (n != 1) { - WARNING ("Failed to receive the answer."); - return EXITCODE (n); - } - -#ifndef NDEBUG - if (response != ACK) - message ("Received unexpected response (%02x).\n", response); -#endif + device_status_t rc = DEVICE_STATUS_SUCCESS; + while ((rc = oceanic_veo250_send (device, command, csize)) != DEVICE_STATUS_SUCCESS) { + if (rc != DEVICE_STATUS_TIMEOUT && rc != DEVICE_STATUS_PROTOCOL) + return rc; // Abort if the maximum number of retries is reached. if (nretries++ >= MAXRETRIES) - break; - } - - // Verify the response of the dive computer. - if (response != ACK) { - WARNING ("Unexpected answer start byte(s)."); - return DEVICE_STATUS_PROTOCOL; + return rc; } // Receive the answer of the dive computer. diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index a2c4b26..b274680 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -100,10 +100,41 @@ device_is_oceanic_vtpro (device_t *abstract) static device_status_t -oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +oceanic_vtpro_send (oceanic_vtpro_device_t *device, const unsigned char command[], unsigned int csize) { device_t *abstract = (device_t *) device; + if (device_is_cancelled (abstract)) + return DEVICE_STATUS_CANCELLED; + + // Send the command to the dive computer. + int n = serial_write (device->port, command, csize); + if (n != csize) { + WARNING ("Failed to send the command."); + return EXITCODE (n); + } + + // Receive the response (ACK/NAK) of the dive computer. + unsigned char response = NAK; + n = serial_read (device->port, &response, 1); + if (n != 1) { + WARNING ("Failed to receive the answer."); + return EXITCODE (n); + } + + // Verify the response of the dive computer. + if (response != ACK) { + WARNING ("Unexpected answer start byte(s)."); + return DEVICE_STATUS_PROTOCOL; + } + + return DEVICE_STATUS_SUCCESS; +} + + +static device_status_t +oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +{ // Send the command to the device. If the device responds with an // ACK byte, the command was received successfully and the answer // (if any) follows after the ACK byte. If the device responds with @@ -111,39 +142,14 @@ oceanic_vtpro_transfer (oceanic_vtpro_device_t *device, const unsigned char comm // returning an error. unsigned int nretries = 0; - unsigned char response = NAK; - while (response == NAK) { - if (device_is_cancelled (abstract)) - return DEVICE_STATUS_CANCELLED; - - // Send the command to the dive computer. - int n = serial_write (device->port, command, csize); - if (n != csize) { - WARNING ("Failed to send the command."); - return EXITCODE (n); - } - - // Receive the response (ACK/NAK) of the dive computer. - n = serial_read (device->port, &response, 1); - if (n != 1) { - WARNING ("Failed to receive the answer."); - return EXITCODE (n); - } - -#ifndef NDEBUG - if (response != ACK) - message ("Received unexpected response (%02x).\n", response); -#endif + device_status_t rc = DEVICE_STATUS_SUCCESS; + while ((rc = oceanic_vtpro_send (device, command, csize)) != DEVICE_STATUS_SUCCESS) { + if (rc != DEVICE_STATUS_TIMEOUT && rc != DEVICE_STATUS_PROTOCOL) + return rc; // Abort if the maximum number of retries is reached. if (nretries++ >= MAXRETRIES) - break; - } - - // Verify the response of the dive computer. - if (response != ACK) { - WARNING ("Unexpected answer start byte(s)."); - return DEVICE_STATUS_PROTOCOL; + return rc; } // Receive the answer of the dive computer.