>From 9b43d7644d75eabf558e305b24a3d8bdbf0b1eb3 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 24 Sep 2014 21:26:32 -0700 Subject: [PATCH 2/3] Prepare Oceanic infrastructure for mixed multi page reads Some new Oceanic dive computers like the Aeris A300CS support a new read command that always reads 256 byte pages instead of 16 byte pages. So far the only known implementations of this command is known to support mixing and matching different read page sizes. On the other hand, some older dive computers that support the 128 byte pagesize read appear not to support mixing different read page sizes. So in order not to break support for older dive computer, this patch only implements mixing different page sizes where explicitly enabled This patch adds two fields to the oceanic_atom2_device_t structure to indicate which type of device this is. The multipage algorithm will request larger, (and in the case of 256 byte reads, aligned) reads wherever possible and fall back to standard 16 byte reads otherwise. Signed-off-by: Dirk Hohndel --- src/oceanic_atom2.c | 62 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 8cc2c71a2b77..295fd0ac846b 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -49,6 +49,8 @@ typedef struct oceanic_atom2_device_t { oceanic_common_device_t base; serial_t *port; unsigned int delay; + unsigned char bigpage; + unsigned char mixed_pagesize_support; } oceanic_atom2_device_t; static dc_status_t oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size); @@ -423,9 +425,15 @@ oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char comm return EXITCODE (n); } - // Verify the checksum of the answer. - unsigned char crc = answer[asize - 1]; - unsigned char ccrc = checksum_add_uint8 (answer, asize - 1, 0x00); + // Verify the checksum of the answer; we can use unsigned short in both cases + unsigned short crc, ccrc; + if (asize == 256 + 2) { // 256 byte pages get two crc bytes + crc = (answer[asize - 1] << 8) | answer[asize - 2] ; + ccrc = checksum_add_uint16 (answer, asize - 2, 0x0000); + } else { + crc = answer[asize - 1]; + ccrc = checksum_add_uint8 (answer, asize - 1, 0x00); + } if (crc != ccrc) { ERROR (abstract->context, "Unexpected answer checksum."); return DC_STATUS_PROTOCOL; @@ -468,6 +476,8 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char // Set the default values. device->port = NULL; device->delay = 0; + device->bigpage = 1; // no big pages + device->mixed_pagesize_support = 0; // don't mix different page sizes when reading // Open the device. int rc = serial_open (&device->port, context, name); @@ -623,33 +633,59 @@ oceanic_atom2_device_version (dc_device_t *abstract, unsigned char data[], unsig } +/* newer devices like the A300CS allow switching between different page sizes between reads across + * the whole address space - but some older devices have problems when doing that. In order not to + * break support for older dive computers, we only support mixed block sized for models that + * explicitly enable support for that. In that case, if we have aligned reads of a larger pagesize + * use the larger block reads, otherwise just loop and read in PAGESIZE chunks */ static dc_status_t oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size) { oceanic_atom2_device_t *device = (oceanic_atom2_device_t*) abstract; - if ((address % PAGESIZE != 0) || - (size % PAGESIZE != 0)) + // pick the best pagesize to use + unsigned int pagesize = PAGESIZE; + + if (device->mixed_pagesize_support && size == device->bigpage * PAGESIZE && address % (device->bigpage * PAGESIZE) == 0) + pagesize = device->bigpage * PAGESIZE; + + // pick the correct read command and number of crc bytes based on the page size + unsigned char read_cmd, crc_size; + if (pagesize == 16 * PAGESIZE) { + read_cmd = 0xB8; + crc_size = 2; + } else if (pagesize == 8 * PAGESIZE) { + read_cmd = 0xB4; + crc_size = 1; + } else { + read_cmd = 0xB1; + crc_size = 1; + } + + if ((address % pagesize != 0) || + (size % pagesize != 0)) return DC_STATUS_INVALIDARGS; unsigned int nbytes = 0; + while (nbytes < size) { // Read the package. - unsigned int number = address / PAGESIZE; - unsigned char answer[PAGESIZE + 1] = {0}; - unsigned char command[4] = {0xB1, + unsigned int number = address / PAGESIZE; // this is always PAGESIZE, even in BIGPAGE mode + unsigned char answer[256 + 2] = {0}; // maximum we support for the known commands + unsigned int answersize = pagesize + crc_size; + unsigned char command[4] = {read_cmd, (number >> 8) & 0xFF, // high (number ) & 0xFF, // low 0}; - dc_status_t rc = oceanic_atom2_transfer (device, command, sizeof (command), answer, sizeof (answer)); + dc_status_t rc = oceanic_atom2_transfer (device, command, sizeof (command), answer, answersize); if (rc != DC_STATUS_SUCCESS) return rc; - memcpy (data, answer, PAGESIZE); + memcpy (data, answer, pagesize); - nbytes += PAGESIZE; - address += PAGESIZE; - data += PAGESIZE; + nbytes += pagesize; + address += pagesize; + data += pagesize; } return DC_STATUS_SUCCESS; -- 1.8.0.rc0.18.gf84667d