From 5824254cf58f8d2a572aebb7e5b6d627a4d2f7a5 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 22 Apr 2016 21:34:13 +0200 Subject: [PATCH] Add support for the INTR protocol variant. There are two variants of the vtpro communication protocol: the existing MOD variant and the new INTR variant. The main difference is in the initialization sequence, with two completely different response packets: MOD--OK_V2.00 INTR-OK_V1.11 The INTR variant does not appear to return useful information in the version packet. --- src/oceanic_vtpro.c | 73 ++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index 2101167..0b37779 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -40,10 +40,16 @@ #define NAK 0xA5 #define END 0x51 +typedef enum oceanic_vtpro_protocol_t { + MOD, + INTR, +} oceanic_vtpro_protocol_t; + typedef struct oceanic_vtpro_device_t { oceanic_common_device_t base; dc_serial_t *port; unsigned int model; + oceanic_vtpro_protocol_t protocol; } oceanic_vtpro_device_t; static dc_status_t oceanic_vtpro_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size); @@ -179,8 +185,10 @@ oceanic_vtpro_init (oceanic_vtpro_device_t *device) dc_device_t *abstract = (dc_device_t *) device; // Send the command to the dive computer. - unsigned char command[2] = {0xAA, 0x00}; - status = dc_serial_write (device->port, command, sizeof (command), NULL); + unsigned char command[2][2] = { + {0xAA, 0x00}, + {0x20, 0x00}}; + status = dc_serial_write (device->port, command[device->protocol], sizeof (command[device->protocol]), NULL); if (status != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to send the command."); return status; @@ -195,10 +203,10 @@ oceanic_vtpro_init (oceanic_vtpro_device_t *device) } // Verify the answer. - const unsigned char response[13] = { - 0x4D, 0x4F, 0x44, 0x2D, 0x2D, 0x4F, 0x4B, - 0x5F, 0x56, 0x32, 0x2E, 0x30, 0x30}; - if (memcmp (answer, response, sizeof (response)) != 0) { + const unsigned char response[2][13] = { + {0x4D, 0x4F, 0x44, 0x2D, 0x2D, 0x4F, 0x4B, 0x5F, 0x56, 0x32, 0x2E, 0x30, 0x30}, + {0x49, 0x4E, 0x54, 0x52, 0x2D, 0x4F, 0x4B, 0x5F, 0x56, 0x31, 0x2E, 0x31, 0x31}}; + if (memcmp (answer, response[device->protocol], sizeof (response[device->protocol])) != 0) { ERROR (abstract->context, "Unexpected answer byte(s)."); return DC_STATUS_PROTOCOL; } @@ -287,6 +295,7 @@ oceanic_vtpro_device_open2 (dc_device_t **out, dc_context_t *context, const char // Set the default values. device->port = NULL; device->model = model; + device->protocol = MOD; // Open the device. status = dc_serial_open (&device->port, context, name); @@ -324,7 +333,7 @@ oceanic_vtpro_device_open2 (dc_device_t **out, dc_context_t *context, const char } // Give the interface 100 ms to settle and draw power up. - dc_serial_sleep (device->port, 100); + dc_serial_sleep (device->port, device->protocol == MOD ? 100 : 1000); // Make sure everything is in a sane state. dc_serial_purge (device->port, DC_DIRECTION_ALL); @@ -444,32 +453,36 @@ oceanic_vtpro_device_version (dc_device_t *abstract, unsigned char data[], unsig return DC_STATUS_PROTOCOL; } - // Obtain the device identification string. This string is - // split over two packets, but we join both parts again. + if (device->protocol == MOD) { + // Obtain the device identification string. This string is + // split over two packets, but we join both parts again. + for (unsigned int i = 0; i < 2; ++i) { + unsigned char command[4] = {0x72, 0x03, i * 0x10, 0x00}; + unsigned char answer[PAGESIZE / 2 + 2] = {0}; + rc = oceanic_vtpro_transfer (device, command, sizeof (command), answer, sizeof (answer)); + if (rc != DC_STATUS_SUCCESS) + return rc; - for (unsigned int i = 0; i < 2; ++i) { - unsigned char command[4] = {0x72, 0x03, i * 0x10, 0x00}; - unsigned char answer[PAGESIZE / 2 + 2] = {0}; - rc = oceanic_vtpro_transfer (device, command, sizeof (command), answer, sizeof (answer)); - if (rc != DC_STATUS_SUCCESS) - return rc; + // Verify the checksum of the answer. + unsigned char crc = answer[PAGESIZE / 2]; + unsigned char ccrc = checksum_add_uint4 (answer, PAGESIZE / 2, 0x00); + if (crc != ccrc) { + ERROR (abstract->context, "Unexpected answer checksum."); + return DC_STATUS_PROTOCOL; + } - // Verify the checksum of the answer. - unsigned char crc = answer[PAGESIZE / 2]; - unsigned char ccrc = checksum_add_uint4 (answer, PAGESIZE / 2, 0x00); - if (crc != ccrc) { - ERROR (abstract->context, "Unexpected answer checksum."); - return DC_STATUS_PROTOCOL; + // Verify the last byte of the answer. + if (answer[PAGESIZE / 2 + 1] != END) { + ERROR (abstract->context, "Unexpected answer byte."); + return DC_STATUS_PROTOCOL; + } + + // Append the answer to the output buffer. + memcpy (data + i * PAGESIZE / 2, answer, PAGESIZE / 2); } - - // Verify the last byte of the answer. - if (answer[PAGESIZE / 2 + 1] != END) { - ERROR (abstract->context, "Unexpected answer byte."); - return DC_STATUS_PROTOCOL; - } - - // Append the answer to the output buffer. - memcpy (data + i * PAGESIZE / 2, answer, PAGESIZE / 2); + } else { + // Return an empty device identification string. + memset (data, 0x00, PAGESIZE); } return DC_STATUS_SUCCESS;