diff --git a/src/descriptor.c b/src/descriptor.c index b59ea45..9ae3e77 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -231,6 +231,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Mares", "Puck Pro", DC_FAMILY_MARES_ICONHD , 0x18}, {"Mares", "Nemo Wide 2", DC_FAMILY_MARES_ICONHD , 0x19}, {"Mares", "Puck 2", DC_FAMILY_MARES_ICONHD , 0x1F}, + {"Mares", "Quad", DC_FAMILY_MARES_ICONHD , 0x29}, /* Heinrichs Weikamp */ {"Heinrichs Weikamp", "OSTC", DC_FAMILY_HW_OSTC, 0}, {"Heinrichs Weikamp", "OSTC Mk2", DC_FAMILY_HW_OSTC, 1}, @@ -290,8 +291,15 @@ static const dc_descriptor_t g_descriptors[] = { {"DiveSystem", "iDive Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x0B}, {"DiveSystem", "iX3M Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x22}, {"DiveSystem", "iX3M Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x23}, - {"DiveSystem", "iX3M Tec", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24}, + {"DiveSystem", "iX3M Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x24}, {"DiveSystem", "iX3M Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x25}, + {"DiveSystem", "iX3M Pro Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x32}, + {"DiveSystem", "iX3M Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x34}, + {"DiveSystem", "iX3M Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x35}, + {"DiveSystem", "iDive2 Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x40}, + {"DiveSystem", "iDive2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x42}, + {"DiveSystem", "iDive2 Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x44}, + {"DiveSystem", "iDive2 Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x45}, {"Cochran", "Commander", DC_FAMILY_COCHRAN_COMMANDER, 0}, {"Cochran", "EMC-14", DC_FAMILY_COCHRAN_COMMANDER, 1}, {"Cochran", "EMC-16", DC_FAMILY_COCHRAN_COMMANDER, 2}, diff --git a/src/divesystem_idive.c b/src/divesystem_idive.c index d8c02e8..e2a5cda 100644 --- a/src/divesystem_idive.c +++ b/src/divesystem_idive.c @@ -57,6 +57,7 @@ typedef struct divesystem_idive_commands_t { divesystem_idive_command_t range; divesystem_idive_command_t header; divesystem_idive_command_t sample; + unsigned int nsamples; } divesystem_idive_commands_t; typedef struct divesystem_idive_device_t { @@ -86,6 +87,7 @@ static const divesystem_idive_commands_t idive = { {0x98, 0x04}, {0xA0, 0x32}, {0xA8, 0x2A}, + 1, }; static const divesystem_idive_commands_t ix3m = { @@ -93,6 +95,15 @@ static const divesystem_idive_commands_t ix3m = { {0x78, 0x04}, {0x79, 0x36}, {0x7A, 0x36}, + 1, +}; + +static const divesystem_idive_commands_t ix3m_apos4 = { + {0x11, 0x1A}, + {0x78, 0x04}, + {0x79, 0x36}, + {0x7A, 0x40}, + 3, }; dc_status_t @@ -356,7 +367,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb unsigned char packet[MAXPACKET - 2]; const divesystem_idive_commands_t *commands = &idive; - if (device->model >= IX3M_EASY && device->model <= IX3M_REB) { + if (device->model >= IX3M_EASY) { commands = &ix3m; } @@ -372,7 +383,7 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb // Emit a device info event. dc_event_devinfo_t devinfo; devinfo.model = array_uint16_le (packet); - devinfo.firmware = 0; + devinfo.firmware = array_uint32_le (packet + 2); devinfo.serial = array_uint32_le (packet + 6); device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); @@ -382,6 +393,14 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb vendor.size = commands->id.size; device_event_emit (abstract, DC_EVENT_VENDOR, &vendor); + if (device->model >= IX3M_EASY) { + // Detect the APOS4 firmware. + unsigned int apos4 = (devinfo.firmware / 10000000) >= 4; + if (apos4) { + commands = &ix3m_apos4; + } + } + unsigned char cmd_range[] = {commands->range.cmd, 0x8D}; rc = divesystem_idive_transfer (device, cmd_range, sizeof(cmd_range), packet, commands->range.size); if (rc != DC_STATUS_SUCCESS) @@ -429,20 +448,28 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb dc_buffer_reserve(buffer, commands->header.size + commands->sample.size * nsamples); dc_buffer_append(buffer, packet, commands->header.size); - for (unsigned int j = 0; j < nsamples; ++j) { + for (unsigned int j = 0; j < nsamples; j += commands->nsamples) { unsigned int idx = j + 1; unsigned char cmd_sample[] = {commands->sample.cmd, (idx ) & 0xFF, (idx >> 8) & 0xFF}; - rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size); + rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size * commands->nsamples); if (rc != DC_STATUS_SUCCESS) return rc; + // If the number of samples is not an exact multiple of the + // number of samples per packet, then the last packet + // appears to contain garbage data. Ignore those samples. + unsigned int n = commands->nsamples; + if (j + n > nsamples) { + n = nsamples - j; + } + // Update and emit a progress event. - progress.current = i * NSTEPS + STEP(j + 2, nsamples + 1); + progress.current = i * NSTEPS + STEP(j + n + 1, nsamples + 1); device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); - dc_buffer_append(buffer, packet, commands->sample.size); + dc_buffer_append(buffer, packet, commands->sample.size * n); } unsigned char *data = dc_buffer_get_data(buffer); diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index 968765c..473dc57 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -37,6 +37,7 @@ #define SZ_SAMPLE_IDIVE 0x2A #define SZ_HEADER_IX3M 0x36 #define SZ_SAMPLE_IX3M 0x36 +#define SZ_SAMPLE_IX3M_APOS4 0x40 #define NGASMIXES 8 @@ -53,8 +54,8 @@ typedef struct divesystem_idive_parser_t divesystem_idive_parser_t; struct divesystem_idive_parser_t { dc_parser_t base; + unsigned int model; unsigned int headersize; - unsigned int samplesize; // Cached fields. unsigned int cached; unsigned int divemode; @@ -97,12 +98,11 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign } // Set the default values. - if (model >= IX3M_EASY && model <= IX3M_REB) { + parser->model = model; + if (model >= IX3M_EASY) { parser->headersize = SZ_HEADER_IX3M; - parser->samplesize = SZ_SAMPLE_IX3M; } else { parser->headersize = SZ_HEADER_IDIVE; - parser->samplesize = SZ_SAMPLE_IDIVE; } parser->cached = 0; parser->divemode = INVALID; @@ -241,8 +241,27 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba unsigned int mode_previous = INVALID; unsigned int divemode = INVALID; + unsigned int nsamples = array_uint16_le (data + 1); + unsigned int samplesize = SZ_SAMPLE_IDIVE; + if (parser->model >= IX3M_EASY) { + // Detect the APOS4 firmware. + unsigned int firmware = array_uint32_le(data + 0x2A); + unsigned int apos4 = (firmware / 10000000) >= 4; + if (apos4) { + // Dive downloaded and recorded with the APOS4 firmware. + samplesize = SZ_SAMPLE_IX3M_APOS4; + } else if (size == parser->headersize + nsamples * SZ_SAMPLE_IX3M_APOS4) { + // Dive downloaded with the APOS4 firmware, but recorded + // with an older firmware. + samplesize = SZ_SAMPLE_IX3M_APOS4; + } else { + // Dive downloaded and recorded with an older firmware. + samplesize = SZ_SAMPLE_IX3M; + } + } + unsigned int offset = parser->headersize; - while (offset + parser->samplesize <= size) { + while (offset + samplesize <= size) { dc_sample_value_t sample = {0}; // Time (seconds). @@ -328,7 +347,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba sample.cns = cns / 100.0; if (callback) callback (DC_SAMPLE_CNS, sample, userdata); - offset += parser->samplesize; + offset += samplesize; } // Cache the data for later use. diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index b8693cb..e7b7d9e 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -125,6 +125,8 @@ static const unsigned char ostc3_key[16] = { }; static dc_status_t hw_ostc3_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size); +static dc_status_t hw_ostc3_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size); +static dc_status_t hw_ostc3_device_write (dc_device_t *abstract, unsigned int address, const unsigned char data[], unsigned int size); static dc_status_t hw_ostc3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer); static dc_status_t hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); static dc_status_t hw_ostc3_device_close (dc_device_t *abstract); @@ -133,8 +135,8 @@ static const dc_device_vtable_t hw_ostc3_device_vtable = { sizeof(hw_ostc3_device_t), DC_FAMILY_HW_OSTC3, hw_ostc3_device_set_fingerprint, /* set_fingerprint */ - NULL, /* read */ - NULL, /* write */ + hw_ostc3_device_read, /* read */ + hw_ostc3_device_write, /* write */ hw_ostc3_device_dump, /* dump */ hw_ostc3_device_foreach, /* foreach */ hw_ostc3_device_close /* close */ @@ -1181,7 +1183,7 @@ hw_ostc3_firmware_block_read (hw_ostc3_device_t *device, unsigned int addr, unsi } static dc_status_t -hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int addr, unsigned char block[], unsigned int block_size) +hw_ostc3_firmware_block_write (hw_ostc3_device_t *device, unsigned int addr, const unsigned char block[], unsigned int block_size) { unsigned char buffer[3 + SZ_FIRMWARE_BLOCK]; @@ -1446,6 +1448,87 @@ hw_ostc3_device_fwupdate (dc_device_t *abstract, const char *filename) } } +static dc_status_t +hw_ostc3_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size) +{ + dc_status_t status = DC_STATUS_SUCCESS; + hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract; + + if ((address % SZ_FIRMWARE_BLOCK != 0) || + (size % SZ_FIRMWARE_BLOCK != 0)) { + ERROR (abstract->context, "Address or size not aligned to the page size!"); + return DC_STATUS_INVALIDARGS; + } + + // Make sure the device is in service mode. + status = hw_ostc3_device_init (device, SERVICE); + if (status != DC_STATUS_SUCCESS) { + return status; + } + + if (device->hardware == OSTC4) { + return DC_STATUS_UNSUPPORTED; + } + + unsigned int nbytes = 0; + while (nbytes < size) { + // Read a memory page. + status = hw_ostc3_firmware_block_read (device, address + nbytes, data + nbytes, SZ_FIRMWARE_BLOCK); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read block."); + return status; + } + + nbytes += SZ_FIRMWARE_BLOCK; + } + + return DC_STATUS_SUCCESS; +} + +static dc_status_t +hw_ostc3_device_write (dc_device_t *abstract, unsigned int address, const unsigned char data[], unsigned int size) +{ + dc_status_t status = DC_STATUS_SUCCESS; + hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract; + + if ((address % SZ_FIRMWARE_BLOCK != 0) || + (size % SZ_FIRMWARE_BLOCK != 0)) { + ERROR (abstract->context, "Address or size not aligned to the page size!"); + return DC_STATUS_INVALIDARGS; + } + + // Make sure the device is in service mode. + status = hw_ostc3_device_init (device, SERVICE); + if (status != DC_STATUS_SUCCESS) { + return status; + } + + if (device->hardware == OSTC4) { + return DC_STATUS_UNSUPPORTED; + } + + // Erase the memory pages. + status = hw_ostc3_firmware_erase (device, address, size); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to erase blocks."); + return status; + } + + unsigned int nbytes = 0; + while (nbytes < size) { + // Write a memory page. + status = hw_ostc3_firmware_block_write (device, address + nbytes, data + nbytes, SZ_FIRMWARE_BLOCK); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to write block."); + return status; + } + + nbytes += SZ_FIRMWARE_BLOCK; + } + + return DC_STATUS_SUCCESS; +} + static dc_status_t hw_ostc3_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) { diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index 9a2179c..3a73968 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -42,6 +42,7 @@ #define PUCKPRO 0x18 #define NEMOWIDE2 0x19 #define PUCK2 0x1F +#define QUAD 0x29 #define ACK 0xAA #define EOF 0xEA @@ -125,6 +126,7 @@ mares_iconhd_get_model (mares_iconhd_device_t *device) {"Puck Pro", PUCKPRO}, {"Nemo Wide 2", NEMOWIDE2}, {"Puck 2", PUCK2}, + {"Quad", QUAD}, }; // Check the product name in the version packet against the list @@ -292,6 +294,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char * case NEMOWIDE2: case SMART: case SMARTAPNEA: + case QUAD: device->layout = &mares_nemowide2_layout; device->packetsize = 256; break; diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index cccfc4e..da19e7f 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -101,7 +101,6 @@ static const oceanic_common_version_t oceanic_atom2_version[] = { static const oceanic_common_version_t oceanic_atom2a_version[] = { {"MANTA R\0\0 512K"}, - {"WISDOM R\0\0 512K"}, {"INSIGHT2 \0\0 512K"}, {"OCEVEO30 \0\0 512K"}, {"ATMOSAI R\0\0 512K"}, @@ -132,6 +131,10 @@ static const oceanic_common_version_t oceanic_default_version[] = { {"COMPMASK \0\0 512K"}, }; +static const oceanic_common_version_t sherwood_wisdom_version[] = { + {"WISDOM R\0\0 512K"}, +}; + static const oceanic_common_version_t oceanic_proplus3_version[] = { {"PROPLUS3 \0\0 512K"}, }; @@ -288,6 +291,20 @@ static const oceanic_common_layout_t oceanic_atom2c_layout = { 0, /* pt_mode_serial */ }; +static const oceanic_common_layout_t sherwood_wisdom_layout = { + 0xFFF0, /* memsize */ + 0x0000, /* cf_devinfo */ + 0x0040, /* cf_pointers */ + 0x03D0, /* rb_logbook_begin */ + 0x0A40, /* rb_logbook_end */ + 8, /* rb_logbook_entry_size */ + 0x0A40, /* rb_profile_begin */ + 0xFE00, /* rb_profile_end */ + 0, /* pt_mode_global */ + 0, /* pt_mode_logbook */ + 0, /* pt_mode_serial */ +}; + static const oceanic_common_layout_t oceanic_proplus3_layout = { 0x10000, /* memsize */ 0x0000, /* cf_devinfo */ @@ -645,6 +662,8 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char device->base.layout = &oceanic_atom2b_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_atom2c_version)) { device->base.layout = &oceanic_atom2c_layout; + } else if (OCEANIC_COMMON_MATCH (device->base.version, sherwood_wisdom_version)) { + device->base.layout = &sherwood_wisdom_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_proplus3_version)) { device->base.layout = &oceanic_proplus3_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, tusa_zenair_version)) { diff --git a/src/parser.c b/src/parser.c index 57ed568..ebbc6a6 100644 --- a/src/parser.c +++ b/src/parser.c @@ -149,10 +149,10 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa rc = atomics_cobalt_parser_create (&parser, context); break; case DC_FAMILY_SHEARWATER_PREDATOR: - rc = shearwater_predator_parser_create (&parser, context, serial); + rc = shearwater_predator_parser_create (&parser, context, model, serial); break; case DC_FAMILY_SHEARWATER_PETREL: - rc = shearwater_petrel_parser_create (&parser, context, serial); + rc = shearwater_petrel_parser_create (&parser, context, model, serial); break; case DC_FAMILY_DIVERITE_NITEKQ: rc = diverite_nitekq_parser_create (&parser, context); diff --git a/src/shearwater_petrel.h b/src/shearwater_petrel.h index 4d70755..b51361f 100644 --- a/src/shearwater_petrel.h +++ b/src/shearwater_petrel.h @@ -34,7 +34,7 @@ dc_status_t shearwater_petrel_device_open (dc_device_t **device, dc_context_t *context, const char *name); dc_status_t -shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial); +shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial); #ifdef __cplusplus } diff --git a/src/shearwater_predator.h b/src/shearwater_predator.h index 5485477..2b16e92 100644 --- a/src/shearwater_predator.h +++ b/src/shearwater_predator.h @@ -34,7 +34,7 @@ dc_status_t shearwater_predator_device_open (dc_device_t **device, dc_context_t *context, const char *name); dc_status_t -shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial); +shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial); #ifdef __cplusplus } diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 1e42d87..ae7f898 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -54,10 +54,14 @@ #define NGASMIXES 10 +#define PREDATOR 2 +#define PETREL 3 + typedef struct shearwater_predator_parser_t shearwater_predator_parser_t; struct shearwater_predator_parser_t { dc_parser_t base; + unsigned int model; unsigned int petrel; unsigned int samplesize; // Cached fields. @@ -67,6 +71,7 @@ struct shearwater_predator_parser_t { unsigned int ngasmixes; unsigned int oxygen[NGASMIXES]; unsigned int helium[NGASMIXES]; + double calibration[3]; unsigned int serial; dc_divemode_t mode; }; @@ -112,7 +117,7 @@ shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned static dc_status_t -shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int petrel) +shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial, unsigned int petrel) { shearwater_predator_parser_t *parser = NULL; const dc_parser_vtable_t *vtable = NULL; @@ -136,14 +141,11 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig return DC_STATUS_NOMEMORY; } - // Initialize the base class. + // Set the default values. + parser->model = model; parser->petrel = petrel; + parser->samplesize = samplesize; parser->serial = serial; - if (petrel) { - parser->samplesize = SZ_SAMPLE_PETREL; - } else { - parser->samplesize = SZ_SAMPLE_PREDATOR; - } // Set the default values. parser->cached = 0; @@ -163,16 +165,16 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig dc_status_t -shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial) +shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial) { - return shearwater_common_parser_create (out, context, serial, 0); + return shearwater_common_parser_create (out, context, model, serial, 0); } dc_status_t -shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial) +shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial) { - return shearwater_common_parser_create (out, context, serial, 1); + return shearwater_common_parser_create (out, context, model, serial, 1); } @@ -297,6 +299,20 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser) offset += parser->samplesize; } + // Cache sensor calibration for later use + parser->calibration[0] = array_uint16_be(data + 87) / 100000.0; + parser->calibration[1] = array_uint16_be(data + 89) / 100000.0; + parser->calibration[2] = array_uint16_be(data + 91) / 100000.0; + // The Predator expects the mV output of the cells to be within 30mV + // to 70mV in 100% O2 at 1 atmosphere. + // If the calibration value is scaled with a factor 2.2, then the + // sensors lines up and matches the average. + if (parser->model == PREDATOR) { + for (size_t i = 0; i < 3; ++i) { + parser->calibration[i] *= 2.2; + } + } + // Cache the data for later use. parser->headersize = headersize; parser->footersize = footersize; @@ -492,9 +508,22 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal unsigned int status = data[offset + 11]; if ((status & OC) == 0) { - // PPO2 -- only return PPO2 if we are in closed circuit mode + // PPO2 +#ifdef SENSOR_AVERAGE sample.ppo2 = data[offset + 6] / 100.0; if (callback) callback (DC_SAMPLE_PPO2, sample, userdata); +#else + if ((status & PPO2_EXTERNAL) == 0) { + sample.ppo2 = data[offset + 12] * parser->calibration[0]; + if (callback && (data[86] & 0x01)) callback (DC_SAMPLE_PPO2, sample, userdata); + + sample.ppo2 = data[offset + 14] * parser->calibration[1]; + if (callback && (data[86] & 0x02)) callback (DC_SAMPLE_PPO2, sample, userdata); + + sample.ppo2 = data[offset + 15] * parser->calibration[2]; + if (callback && (data[86] & 0x04)) callback (DC_SAMPLE_PPO2, sample, userdata); + } +#endif // Setpoint if (parser->petrel) { diff --git a/src/uwatec_meridian.c b/src/uwatec_meridian.c index 077ec31..d59b855 100644 --- a/src/uwatec_meridian.c +++ b/src/uwatec_meridian.c @@ -228,7 +228,11 @@ uwatec_meridian_device_open (dc_device_t **out, dc_context_t *context, const cha dc_serial_purge (device->port, DC_DIRECTION_ALL); // Perform the handshaking. - uwatec_meridian_handshake (device); + status = uwatec_meridian_handshake (device); + if (status != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to handshake with the device."); + goto error_close; + } *out = (dc_device_t*) device; diff --git a/src/uwatec_smart.c b/src/uwatec_smart.c index 2b94a3b..425e76e 100644 --- a/src/uwatec_smart.c +++ b/src/uwatec_smart.c @@ -191,7 +191,11 @@ uwatec_smart_device_open (dc_device_t **out, dc_context_t *context) } // Perform the handshaking. - uwatec_smart_handshake (device); + status = uwatec_smart_handshake (device); + if (status != DC_STATUS_SUCCESS) { + ERROR (context, "Failed to handshake with the device."); + goto error_close; + } *out = (dc_device_t*) device;