Reduce the number of read operations.

Only the header of the package needs to be read separately (to obtain 
the size of the entire package). Removed the suunto_vyper_recv function.
This commit is contained in:
Jef Driesen 2008-03-26 08:47:14 +00:00
parent fcf11209b7
commit 7dd1d19eab

View File

@ -14,13 +14,6 @@
message ("%s:%d: %s\n", __FILE__, __LINE__, expr); \
}
#define EXITCODE(rc, n) \
( \
rc == -1 ? \
SUUNTO_ERROR_IO : \
(rc != n ? SUUNTO_ERROR_TIMEOUT : SUUNTO_ERROR_PROTOCOL) \
)
struct vyper {
struct serial *port;
@ -255,18 +248,6 @@ suunto_vyper_send (vyper *device, const unsigned char command[], unsigned int cs
}
static int
suunto_vyper_recv (vyper *device, unsigned char data[], unsigned int size)
{
int rc = serial_read (device->port, data, size);
if (rc != size) {
return EXITCODE (rc, size);
}
return SUUNTO_SUCCESS;
}
static int
suunto_vyper_transfer (vyper *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size)
{
@ -280,10 +261,12 @@ suunto_vyper_transfer (vyper *device, const unsigned char command[], unsigned in
}
// Receive the answer of the dive computer.
rc = suunto_vyper_recv (device, answer, asize);
if (rc != SUUNTO_SUCCESS) {
rc = serial_read (device->port, answer, asize);
if (rc != asize) {
WARNING ("Failed to receive the answer.");
return rc;
if (rc == -1)
return SUUNTO_ERROR_IO;
return SUUNTO_ERROR_TIMEOUT;
}
// Verify the header of the package.
@ -410,33 +393,24 @@ suunto_vyper_read_dive (vyper *device, unsigned char data[], unsigned int size,
if (device == NULL)
return SUUNTO_ERROR;
// Prepare the command.
// Send the command to the dive computer.
unsigned char command[3] = {init ? 0x08 : 0x09, 0xA5, 0x00};
command[2] = suunto_vyper_checksum (command, 2, 0x00);
// Send the command to the dive computer.
int rc = suunto_vyper_send (device, command, 3);
if (rc != SUUNTO_SUCCESS) {
WARNING ("Failed to send the command.");
return rc;
}
// FIXME: Give the DC extra answer time to send its first byte,
// then let the standard timeout apply.
// The data transmission is split in packages
// of maximum $SUUNTO_VYPER_PACKET_SIZE bytes.
unsigned int nbytes = 0;
for (unsigned int npackages = 0;; ++npackages) {
// Initial checksum value.
unsigned char ccrc = 0x00;
// Receive the header of the package.
unsigned char header[2] = {0};
rc = serial_read (device->port, header, 2);
if (rc != 2 || memcmp (command, header, 1) != 0 ||
header[1] > SUUNTO_VYPER_PACKET_SIZE) {
unsigned char answer[SUUNTO_VYPER_PACKET_SIZE + 3] = {0};
rc = serial_read (device->port, answer, 2);
if (rc != 2) {
// If no data is received because a timeout occured, we assume
// the last package was already received and the transmission
// can be finished. Unfortunately this is not 100% reliable,
@ -447,34 +421,40 @@ suunto_vyper_read_dive (vyper *device, unsigned char data[], unsigned int size,
// an error, because the DC always sends at least one package.
if (rc == 0 && npackages != 0)
break;
WARNING ("Failed to receive the answer.");
if (rc == -1)
return SUUNTO_ERROR_IO;
return SUUNTO_ERROR_TIMEOUT;
}
// Verify the header of the package.
if (answer[0] != command[0] ||
answer[1] > SUUNTO_VYPER_PACKET_SIZE) {
WARNING ("Unexpected answer start byte(s).");
return EXITCODE (rc, 2);
return SUUNTO_ERROR_PROTOCOL;
}
// Update the checksum.
ccrc = suunto_vyper_checksum (header, 2, ccrc);
// Receive the contents of the package.
unsigned char len = header[1];
unsigned char package[SUUNTO_VYPER_PACKET_SIZE] = {0};
rc = serial_read (device->port, package, len);
if (rc != len) {
WARNING ("Unexpected EOF in answer.");
return EXITCODE (rc, len);
// Receive the remaining part of the package.
unsigned char len = answer[1];
rc = serial_read (device->port, answer + 2, len + 1);
if (rc != len + 1) {
WARNING ("Failed to receive the answer.");
if (rc == -1)
return SUUNTO_ERROR_IO;
return SUUNTO_ERROR_TIMEOUT;
}
// Update the checksum.
ccrc = suunto_vyper_checksum (package, len, ccrc);
// Receive (and verify) the checksum of the package.
unsigned char crc = 0x00;
rc = serial_read (device->port, &crc, 1);
if (rc != 1 || ccrc != crc) {
// Verify the checksum of the package.
unsigned char crc = answer[len + 2];
unsigned char ccrc = suunto_vyper_checksum (answer, len + 2, 0x00);
if (crc != ccrc) {
WARNING ("Unexpected answer CRC.");
return EXITCODE (rc, 1);
return SUUNTO_ERROR_PROTOCOL;
}
// Append the package to the output buffer.
if (nbytes + len <= size) {
memcpy (data + nbytes, package, len);
memcpy (data + nbytes, answer + 2, len);
nbytes += len;
} else {
WARNING ("Insufficient buffer space available.");