From 6f4d8634987ee8c45e8e39c874c3a66621deadb3 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 17 Feb 2008 09:01:40 +0000 Subject: [PATCH] Read the entire package with a single operation. Since the package size is known in advance, there is no need to read each part (header, data and checksum) separately. --- suunto_d9.c | 87 +++++++++++++++++++++++++----------------------- suunto_vyper.c | 81 +++++++++++++++++++++++---------------------- suunto_vyper2.c | 88 ++++++++++++++++++++++++++----------------------- 3 files changed, 132 insertions(+), 124 deletions(-) diff --git a/suunto_d9.c b/suunto_d9.c index 45eba0d..7f052e0 100644 --- a/suunto_d9.c +++ b/suunto_d9.c @@ -146,8 +146,22 @@ suunto_d9_send (d9 *device, const unsigned char command[], unsigned int csize) static int -suunto_d9_transfer (d9 *device, const unsigned char command[], unsigned int csize, unsigned char header[], unsigned int hsize, unsigned char data[], unsigned int size) +suunto_d9_recv (d9 *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_d9_transfer (d9 *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size) +{ + assert (asize >= size + 4); + // Send the command to the dive computer. int rc = suunto_d9_send (device, command, csize); if (rc != SUUNTO_SUCCESS) { @@ -155,40 +169,27 @@ suunto_d9_transfer (d9 *device, const unsigned char command[], unsigned int csiz return rc; } - // Initial checksum value. - unsigned char ccrc = 0x00; + // Receive the answer of the dive computer. + rc = suunto_d9_recv (device, answer, asize); + if (rc != SUUNTO_SUCCESS) { + WARNING ("Failed to receive the answer."); + return rc; + } - // Receive the header of the package. - rc = serial_read (device->port, header, hsize); - header[2] -= size; - if (rc != hsize || memcmp (command, header, hsize) != 0) { + // Verify the header of the package. + answer[2] -= size; // Adjust the package size for the comparision. + if (memcmp (command, answer, asize - size - 1) != 0) { WARNING ("Unexpected answer start byte(s)."); - if (rc == 0) { - WARNING ("Interface present, but the DC does not answer. Check the connection."); - } - return EXITCODE (rc, hsize); + return SUUNTO_ERROR_PROTOCOL; } - header[2] += size; - // Update the checksum. - ccrc = suunto_d9_checksum (header, hsize, ccrc); + answer[2] += size; // Restore the package size again. - if (data) { - // Receive the contents of the package. - rc = serial_read (device->port, data, size); - if (rc != size) { - WARNING ("Unexpected EOF in answer."); - return EXITCODE (rc, size); - } - // Update the checksum. - ccrc = suunto_d9_checksum (data, size, 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[asize - 1]; + unsigned char ccrc = suunto_d9_checksum (answer, asize - 1, 0x00); + if (crc != ccrc) { WARNING ("Unexpected answer CRC."); - return EXITCODE (rc, 1); + return SUUNTO_ERROR_PROTOCOL; } return SUUNTO_SUCCESS; @@ -204,13 +205,14 @@ suunto_d9_read_version (d9 *device, unsigned char data[], unsigned int size) if (size < 4) return SUUNTO_ERROR_MEMORY; - unsigned char header[3] = {0}; - unsigned char command[4] = {0x0F, 0x00, 0x00, 0}; - command[3] = suunto_d9_checksum (command, 3, 0x00); - int rc = suunto_d9_transfer (device, command, 4, header, 3, data, 4); + unsigned char answer[4 + 4] = {0}; + unsigned char command[4] = {0x0F, 0x00, 0x00, 0x0F}; + int rc = suunto_d9_transfer (device, command, sizeof (command), answer, sizeof (answer), 4); if (rc != SUUNTO_SUCCESS) return rc; + memcpy (data, answer + 3, 4); + #ifndef NDEBUG message ("D9ReadVersion()=\"%02x %02x %02x %02x\"\n", data[0], data[1], data[2], data[3]); #endif @@ -225,10 +227,9 @@ suunto_d9_reset_maxdepth (d9 *device) if (device == NULL) return SUUNTO_ERROR; - unsigned char header[3] = {0}; - unsigned char command[4] = {0x20, 0x00, 0x00, 0}; - command[3] = suunto_d9_checksum (command, 3, 0x00); - int rc = suunto_d9_transfer (device, command, 4, header, 3, NULL, 0); + unsigned char answer[4] = {0}; + unsigned char command[4] = {0x20, 0x00, 0x00, 0x20}; + int rc = suunto_d9_transfer (device, command, sizeof (command), answer, sizeof (answer), 0); if (rc != SUUNTO_SUCCESS) return rc; @@ -255,17 +256,19 @@ suunto_d9_read_memory (d9 *device, unsigned int address, unsigned char data[], u unsigned int len = MIN (size - nbytes, SUUNTO_D9_PACKET_SIZE); // Read the package. - unsigned char header[6] = {0}; + unsigned char answer[SUUNTO_D9_PACKET_SIZE + 7] = {0}; unsigned char command[7] = {0x05, 0x00, 0x03, (address >> 8) & 0xFF, // high (address ) & 0xFF, // low len, // count 0}; // CRC command[6] = suunto_d9_checksum (command, 6, 0x00); - int rc = suunto_d9_transfer (device, command, 7, header, 6, data, len); + int rc = suunto_d9_transfer (device, command, sizeof (command), answer, len + 7, len); if (rc != SUUNTO_SUCCESS) return rc; + memcpy (data, answer + 6, len); + #ifndef NDEBUG message ("D9Read(0x%04x,%d)=\"", address, len); for (unsigned int i = 0; i < len; ++i) { @@ -298,7 +301,7 @@ suunto_d9_write_memory (d9 *device, unsigned int address, const unsigned char da unsigned int len = MIN (size - nbytes, SUUNTO_D9_PACKET_SIZE); // Write the package. - unsigned char header[6] = {0}; + unsigned char answer[7] = {0}; unsigned char command[SUUNTO_D9_PACKET_SIZE + 7] = {0x06, 0x00, 0x03, (address >> 8) & 0xFF, // high (address ) & 0xFF, // low @@ -306,7 +309,7 @@ suunto_d9_write_memory (d9 *device, unsigned int address, const unsigned char da 0}; // data + CRC memcpy (command + 6, data, len); command[len + 6] = suunto_d9_checksum (command, len + 6, 0x00); - int rc = suunto_d9_transfer (device, command, len + 7, header, 6, NULL, 0); + int rc = suunto_d9_transfer (device, command, len + 7, answer, sizeof (answer), 0); if (rc != SUUNTO_SUCCESS) return rc; diff --git a/suunto_vyper.c b/suunto_vyper.c index c521ff9..b7b22cb 100644 --- a/suunto_vyper.c +++ b/suunto_vyper.c @@ -1,5 +1,6 @@ #include // memcmp, memcpy #include // malloc, free +#include // assert #include "suunto.h" #include "serial.h" @@ -219,6 +220,7 @@ suunto_vyper_set_delay (vyper *device, unsigned int delay) return SUUNTO_SUCCESS; } + static int suunto_vyper_send (vyper *device, const unsigned char command[], unsigned int csize) { @@ -254,8 +256,22 @@ suunto_vyper_send (vyper *device, const unsigned char command[], unsigned int cs static int -suunto_vyper_transfer (vyper *device, const unsigned char command[], unsigned int csize, unsigned char header[], unsigned int hsize, unsigned char data[], unsigned int size) +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) +{ + assert (asize >= size + 2); + // Send the command to the dive computer. int rc = suunto_vyper_send (device, command, csize); if (rc != SUUNTO_SUCCESS) { @@ -263,41 +279,25 @@ suunto_vyper_transfer (vyper *device, const unsigned char command[], unsigned in return rc; } - // Initial checksum value. - unsigned char ccrc = 0x00; + // Receive the answer of the dive computer. + rc = suunto_vyper_recv (device, answer, asize); + if (rc != SUUNTO_SUCCESS) { + WARNING ("Failed to receive the answer."); + return rc; + } - // FIXME: Give the DC extra answer time to send its first byte, - // then let the standard timeout apply. - - // Receive the header of the package. - rc = serial_read (device->port, header, hsize); - if (rc != hsize || memcmp (command, header, hsize) != 0) { + // Verify the header of the package. + if (memcmp (command, answer, asize - size - 1) != 0) { WARNING ("Unexpected answer start byte(s)."); - if (rc == 0) { - WARNING ("Interface present, but the DC does not answer. Check the connection."); - } - return EXITCODE (rc, hsize); - } - // Update the checksum. - ccrc = suunto_vyper_checksum (header, hsize, ccrc); - - if (data) { - // Receive the contents of the package. - rc = serial_read (device->port, data, size); - if (rc != size) { - WARNING ("Unexpected EOF in answer."); - return EXITCODE (rc, size); - } - // Update the checksum. - ccrc = suunto_vyper_checksum (data, size, ccrc); + return SUUNTO_ERROR_PROTOCOL; } - // 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[asize - 1]; + unsigned char ccrc = suunto_vyper_checksum (answer, asize - 1, 0x00); + if (crc != ccrc) { WARNING ("Unexpected answer CRC."); - return EXITCODE (rc, 1); + return SUUNTO_ERROR_PROTOCOL; } return SUUNTO_SUCCESS; @@ -317,19 +317,21 @@ suunto_vyper_read_memory (vyper *device, unsigned int address, unsigned char dat while (nbytes < size) { // Calculate the package size. unsigned int len = MIN (size - nbytes, SUUNTO_VYPER_PACKET_SIZE); - + // Read the package. - unsigned char header[4] = {0}; + unsigned char answer[SUUNTO_VYPER_PACKET_SIZE + 5] = {0}; unsigned char command[5] = {0x05, (address >> 8) & 0xFF, // high (address ) & 0xFF, // low len, // count 0}; // CRC command[4] = suunto_vyper_checksum (command, 4, 0x00); - int rc = suunto_vyper_transfer (device, command, 5, header, 4, data, len); + int rc = suunto_vyper_transfer (device, command, sizeof (command), answer, len + 5, len); if (rc != SUUNTO_SUCCESS) return rc; + memcpy (data, answer + 4, len); + #ifndef NDEBUG message ("VyperRead(0x%04x,%d)=\"", address, len); for (unsigned int i = 0; i < len; ++i) { @@ -362,10 +364,9 @@ suunto_vyper_write_memory (vyper *device, unsigned int address, const unsigned c unsigned int len = MIN (size - nbytes, SUUNTO_VYPER_PACKET_SIZE); // Prepare to write the package. - unsigned char pheader[2] = {0}; - unsigned char pcommand[3] = {0x07, 0xA5, 0}; - pcommand[2] = suunto_vyper_checksum (pcommand, 2, 0x00); - int rc = suunto_vyper_transfer (device, pcommand, 3, pheader, 2, NULL, 0); + unsigned char panswer[3] = {0}; + unsigned char pcommand[3] = {0x07, 0xA5, 0xA2}; + int rc = suunto_vyper_transfer (device, pcommand, sizeof (pcommand), panswer, sizeof (panswer), 0); if (rc != SUUNTO_SUCCESS) return rc; @@ -374,7 +375,7 @@ suunto_vyper_write_memory (vyper *device, unsigned int address, const unsigned c #endif // Write the package. - unsigned char wheader[4] = {0}; + unsigned char wanswer[5] = {0}; unsigned char wcommand[SUUNTO_VYPER_PACKET_SIZE + 5] = {0x06, (address >> 8) & 0xFF, // high (address ) & 0xFF, // low @@ -382,7 +383,7 @@ suunto_vyper_write_memory (vyper *device, unsigned int address, const unsigned c 0}; // data + CRC memcpy (wcommand + 4, data, len); wcommand[len + 4] = suunto_vyper_checksum (wcommand, len + 4, 0x00); - rc = suunto_vyper_transfer (device, wcommand, len + 5, wheader, 4, NULL, 0); + rc = suunto_vyper_transfer (device, wcommand, len + 5, wanswer, sizeof (wanswer), 0); if (rc != SUUNTO_SUCCESS) return rc; diff --git a/suunto_vyper2.c b/suunto_vyper2.c index 02d3192..3bf0191 100644 --- a/suunto_vyper2.c +++ b/suunto_vyper2.c @@ -1,5 +1,6 @@ #include // memcmp, memcpy #include // malloc, free +#include // assert #include "suunto.h" #include "serial.h" @@ -140,8 +141,22 @@ suunto_vyper2_send (vyper2 *device, const unsigned char command[], unsigned int static int -suunto_vyper2_transfer (vyper2 *device, const unsigned char command[], unsigned int csize, unsigned char header[], unsigned int hsize, unsigned char data[], unsigned int size) +suunto_vyper2_recv (vyper2 *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_vyper2_transfer (vyper2 *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size) +{ + assert (asize >= size + 4); + // Send the command to the dive computer. int rc = suunto_vyper2_send (device, command, csize); if (rc != SUUNTO_SUCCESS) { @@ -149,40 +164,27 @@ suunto_vyper2_transfer (vyper2 *device, const unsigned char command[], unsigned return rc; } - // Initial checksum value. - unsigned char ccrc = 0x00; + // Receive the answer of the dive computer. + rc = suunto_vyper2_recv (device, answer, asize); + if (rc != SUUNTO_SUCCESS) { + WARNING ("Failed to receive the answer."); + return rc; + } - // Receive the header of the package. - rc = serial_read (device->port, header, hsize); - header[2] -= size; - if (rc != hsize || memcmp (command, header, hsize) != 0) { + // Verify the header of the package. + answer[2] -= size; // Adjust the package size for the comparision. + if (memcmp (command, answer, asize - size - 1) != 0) { WARNING ("Unexpected answer start byte(s)."); - if (rc == 0) { - WARNING ("Interface present, but the DC does not answer. Check the connection."); - } - return EXITCODE (rc, hsize); + return SUUNTO_ERROR_PROTOCOL; } - header[2] += size; - // Update the checksum. - ccrc = suunto_vyper2_checksum (header, hsize, ccrc); + answer[2] += size; // Restore the package size again. - if (data) { - // Receive the contents of the package. - rc = serial_read (device->port, data, size); - if (rc != size) { - WARNING ("Unexpected EOF in answer."); - return EXITCODE (rc, size); - } - // Update the checksum. - ccrc = suunto_vyper2_checksum (data, size, 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[asize - 1]; + unsigned char ccrc = suunto_vyper2_checksum (answer, asize - 1, 0x00); + if (crc != ccrc) { WARNING ("Unexpected answer CRC."); - return EXITCODE (rc, 1); + return SUUNTO_ERROR_PROTOCOL; } return SUUNTO_SUCCESS; @@ -198,13 +200,14 @@ suunto_vyper2_read_version (vyper2 *device, unsigned char data[], unsigned int s if (size < 4) return SUUNTO_ERROR_MEMORY; - unsigned char header[3] = {0}; - unsigned char command[4] = {0x0F, 0x00, 0x00, 0}; - command[3] = suunto_vyper2_checksum (command, 3, 0x00); - int rc = suunto_vyper2_transfer (device, command, 4, header, 3, data, 4); + unsigned char answer[4 + 4] = {0}; + unsigned char command[4] = {0x0F, 0x00, 0x00, 0x0F}; + int rc = suunto_vyper2_transfer (device, command, sizeof (command), answer, sizeof (answer), 4); if (rc != SUUNTO_SUCCESS) return rc; + memcpy (data, answer + 3, 4); + #ifndef NDEBUG message ("Vyper2ReadVersion()=\"%02x %02x %02x %02x\"\n", data[0], data[1], data[2], data[3]); #endif @@ -219,10 +222,9 @@ suunto_vyper2_reset_maxdepth (vyper2 *device) if (device == NULL) return SUUNTO_ERROR; - unsigned char header[3] = {0}; - unsigned char command[4] = {0x20, 0x00, 0x00, 0}; - command[3] = suunto_vyper2_checksum (command, 3, 0x00); - int rc = suunto_vyper2_transfer (device, command, 4, header, 3, NULL, 0); + unsigned char answer[4] = {0}; + unsigned char command[4] = {0x20, 0x00, 0x00, 0x20}; + int rc = suunto_vyper2_transfer (device, command, sizeof (command), answer, sizeof (answer), 0); if (rc != SUUNTO_SUCCESS) return rc; @@ -249,17 +251,19 @@ suunto_vyper2_read_memory (vyper2 *device, unsigned int address, unsigned char d unsigned int len = MIN (size - nbytes, SUUNTO_VYPER2_PACKET_SIZE); // Read the package. - unsigned char header[6] = {0}; + unsigned char answer[SUUNTO_VYPER2_PACKET_SIZE + 7] = {0}; unsigned char command[7] = {0x05, 0x00, 0x03, (address >> 8) & 0xFF, // high (address ) & 0xFF, // low len, // count 0}; // CRC command[6] = suunto_vyper2_checksum (command, 6, 0x00); - int rc = suunto_vyper2_transfer (device, command, 7, header, 6, data, len); + int rc = suunto_vyper2_transfer (device, command, sizeof (command), answer, len + 7, len); if (rc != SUUNTO_SUCCESS) return rc; + memcpy (data, answer + 6, len); + #ifndef NDEBUG message ("Vyper2Read(0x%04x,%d)=\"", address, len); for (unsigned int i = 0; i < len; ++i) { @@ -292,7 +296,7 @@ suunto_vyper2_write_memory (vyper2 *device, unsigned int address, const unsigned unsigned int len = MIN (size - nbytes, SUUNTO_VYPER2_PACKET_SIZE); // Write the package. - unsigned char header[6] = {0}; + unsigned char answer[7] = {0}; unsigned char command[SUUNTO_VYPER2_PACKET_SIZE + 7] = {0x06, 0x00, 0x03, (address >> 8) & 0xFF, // high (address ) & 0xFF, // low @@ -300,7 +304,7 @@ suunto_vyper2_write_memory (vyper2 *device, unsigned int address, const unsigned 0}; // data + CRC memcpy (command + 6, data, len); command[len + 6] = suunto_vyper2_checksum (command, len + 6, 0x00); - int rc = suunto_vyper2_transfer (device, command, len + 7, header, 6, NULL, 0); + int rc = suunto_vyper2_transfer (device, command, len + 7, answer, sizeof (answer), 0); if (rc != SUUNTO_SUCCESS) return rc;