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:
parent
fcf11209b7
commit
7dd1d19eab
@ -14,13 +14,6 @@
|
|||||||
message ("%s:%d: %s\n", __FILE__, __LINE__, expr); \
|
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 vyper {
|
||||||
struct serial *port;
|
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
|
static int
|
||||||
suunto_vyper_transfer (vyper *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size)
|
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.
|
// Receive the answer of the dive computer.
|
||||||
rc = suunto_vyper_recv (device, answer, asize);
|
rc = serial_read (device->port, answer, asize);
|
||||||
if (rc != SUUNTO_SUCCESS) {
|
if (rc != asize) {
|
||||||
WARNING ("Failed to receive the answer.");
|
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.
|
// 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)
|
if (device == NULL)
|
||||||
return SUUNTO_ERROR;
|
return SUUNTO_ERROR;
|
||||||
|
|
||||||
// Prepare the command.
|
// Send the command to the dive computer.
|
||||||
unsigned char command[3] = {init ? 0x08 : 0x09, 0xA5, 0x00};
|
unsigned char command[3] = {init ? 0x08 : 0x09, 0xA5, 0x00};
|
||||||
command[2] = suunto_vyper_checksum (command, 2, 0x00);
|
command[2] = suunto_vyper_checksum (command, 2, 0x00);
|
||||||
|
|
||||||
// Send the command to the dive computer.
|
|
||||||
int rc = suunto_vyper_send (device, command, 3);
|
int rc = suunto_vyper_send (device, command, 3);
|
||||||
if (rc != SUUNTO_SUCCESS) {
|
if (rc != SUUNTO_SUCCESS) {
|
||||||
WARNING ("Failed to send the command.");
|
WARNING ("Failed to send the command.");
|
||||||
return rc;
|
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
|
// The data transmission is split in packages
|
||||||
// of maximum $SUUNTO_VYPER_PACKET_SIZE bytes.
|
// of maximum $SUUNTO_VYPER_PACKET_SIZE bytes.
|
||||||
|
|
||||||
unsigned int nbytes = 0;
|
unsigned int nbytes = 0;
|
||||||
for (unsigned int npackages = 0;; ++npackages) {
|
for (unsigned int npackages = 0;; ++npackages) {
|
||||||
// Initial checksum value.
|
|
||||||
unsigned char ccrc = 0x00;
|
|
||||||
|
|
||||||
// Receive the header of the package.
|
// Receive the header of the package.
|
||||||
unsigned char header[2] = {0};
|
unsigned char answer[SUUNTO_VYPER_PACKET_SIZE + 3] = {0};
|
||||||
rc = serial_read (device->port, header, 2);
|
rc = serial_read (device->port, answer, 2);
|
||||||
if (rc != 2 || memcmp (command, header, 1) != 0 ||
|
if (rc != 2) {
|
||||||
header[1] > SUUNTO_VYPER_PACKET_SIZE) {
|
|
||||||
// If no data is received because a timeout occured, we assume
|
// If no data is received because a timeout occured, we assume
|
||||||
// the last package was already received and the transmission
|
// the last package was already received and the transmission
|
||||||
// can be finished. Unfortunately this is not 100% reliable,
|
// 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.
|
// an error, because the DC always sends at least one package.
|
||||||
if (rc == 0 && npackages != 0)
|
if (rc == 0 && npackages != 0)
|
||||||
break;
|
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).");
|
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.
|
// Receive the remaining part of the package.
|
||||||
unsigned char len = header[1];
|
unsigned char len = answer[1];
|
||||||
unsigned char package[SUUNTO_VYPER_PACKET_SIZE] = {0};
|
rc = serial_read (device->port, answer + 2, len + 1);
|
||||||
rc = serial_read (device->port, package, len);
|
if (rc != len + 1) {
|
||||||
if (rc != len) {
|
WARNING ("Failed to receive the answer.");
|
||||||
WARNING ("Unexpected EOF in answer.");
|
if (rc == -1)
|
||||||
return EXITCODE (rc, len);
|
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.
|
// Verify the checksum of the package.
|
||||||
unsigned char crc = 0x00;
|
unsigned char crc = answer[len + 2];
|
||||||
rc = serial_read (device->port, &crc, 1);
|
unsigned char ccrc = suunto_vyper_checksum (answer, len + 2, 0x00);
|
||||||
if (rc != 1 || ccrc != crc) {
|
if (crc != ccrc) {
|
||||||
WARNING ("Unexpected answer CRC.");
|
WARNING ("Unexpected answer CRC.");
|
||||||
return EXITCODE (rc, 1);
|
return SUUNTO_ERROR_PROTOCOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the package to the output buffer.
|
// Append the package to the output buffer.
|
||||||
if (nbytes + len <= size) {
|
if (nbytes + len <= size) {
|
||||||
memcpy (data + nbytes, package, len);
|
memcpy (data + nbytes, answer + 2, len);
|
||||||
nbytes += len;
|
nbytes += len;
|
||||||
} else {
|
} else {
|
||||||
WARNING ("Insufficient buffer space available.");
|
WARNING ("Insufficient buffer space available.");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user