diff --git a/examples/universal.c b/examples/universal.c index 03d615d..1e0307b 100644 --- a/examples/universal.c +++ b/examples/universal.c @@ -243,7 +243,7 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata) "none", "deco", "rbt", "ascent", "ceiling", "workload", "transmitter", "violation", "bookmark", "surface", "safety stop", "gaschange", "safety stop (voluntary)", "safety stop (mandatory)", "deepstop", - "ceiling (safety stop)", "unknown", "divetime", "maxdepth", + "ceiling (safety stop)", "floor", "divetime", "maxdepth", "OLF", "PO2", "airtime", "rgbm", "heading", "tissue level warning", "gaschange2"}; static const char *decostop[] = { diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index a92e653..16ca2b3 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -73,7 +73,7 @@ typedef enum parser_sample_event_t { SAMPLE_EVENT_SAFETYSTOP_MANDATORY, SAMPLE_EVENT_DEEPSTOP, SAMPLE_EVENT_CEILING_SAFETYSTOP, - SAMPLE_EVENT_UNKNOWN, + SAMPLE_EVENT_FLOOR, SAMPLE_EVENT_DIVETIME, SAMPLE_EVENT_MAXDEPTH, SAMPLE_EVENT_OLF, @@ -87,6 +87,9 @@ typedef enum parser_sample_event_t { respectively the low and high part. */ } parser_sample_event_t; +/* For backwards compatibility */ +#define SAMPLE_EVENT_UNKNOWN SAMPLE_EVENT_FLOOR + typedef enum parser_sample_flags_t { SAMPLE_FLAGS_NONE = 0, SAMPLE_FLAGS_BEGIN = (1 << 0), diff --git a/src/cressi_edy.c b/src/cressi_edy.c index 0de977a..d5c5482 100644 --- a/src/cressi_edy.c +++ b/src/cressi_edy.c @@ -83,6 +83,9 @@ cressi_edy_transfer (cressi_edy_device_t *device, const unsigned char command[], assert (asize >= csize); + if (device_is_cancelled (abstract)) + return DC_STATUS_CANCELLED; + // Flush the serial input buffer. int rc = serial_flush (device->port, SERIAL_QUEUE_INPUT); if (rc == -1) { diff --git a/src/cressi_leonardo_parser.c b/src/cressi_leonardo_parser.c index 0291366..470a4fa 100644 --- a/src/cressi_leonardo_parser.c +++ b/src/cressi_leonardo_parser.c @@ -162,7 +162,7 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac dc_sample_value_t sample = {0}; unsigned int value = array_uint16_le (data + offset); - unsigned int depth = value & 0x3FFF; + unsigned int depth = value & 0x07FF; // Time (seconds). time += interval; diff --git a/src/descriptor.c b/src/descriptor.c index ee63ca1..1340d65 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -99,6 +99,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Uwatec", "Aladin 2G", DC_FAMILY_UWATEC_SMART, 0x13}, {"Subgear","XP-10", DC_FAMILY_UWATEC_SMART, 0x13}, {"Uwatec", "Smart Com", DC_FAMILY_UWATEC_SMART, 0x14}, + {"Uwatec", "Aladin 2G", DC_FAMILY_UWATEC_SMART, 0x15}, {"Uwatec", "Smart Tec", DC_FAMILY_UWATEC_SMART, 0x18}, {"Uwatec", "Galileo Trimix",DC_FAMILY_UWATEC_SMART, 0x19}, {"Uwatec", "Smart Z", DC_FAMILY_UWATEC_SMART, 0x1C}, @@ -163,7 +164,9 @@ static const dc_descriptor_t g_descriptors[] = { {"Oceanic", "Atom 3.1", DC_FAMILY_OCEANIC_ATOM2, 0x4456}, {"Aeris", "A300 AI", DC_FAMILY_OCEANIC_ATOM2, 0x4457}, {"Sherwood", "Wisdom 3", DC_FAMILY_OCEANIC_ATOM2, 0x4458}, + {"Sherwood", "Amphos", DC_FAMILY_OCEANIC_ATOM2, 0x4545}, {"Oceanic", "Pro Plus 3", DC_FAMILY_OCEANIC_ATOM2, 0x4548}, + {"Oceanic", "OCi", DC_FAMILY_OCEANIC_ATOM2, 0x454B}, /* Mares Nemo */ {"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0}, {"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0}, @@ -186,6 +189,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Mares", "Icon HD Net Ready", DC_FAMILY_MARES_ICONHD , 0x15}, {"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}, /* Heinrichs Weikamp */ {"Heinrichs Weikamp", "OSTC", DC_FAMILY_HW_OSTC, 0}, {"Heinrichs Weikamp", "OSTC Mk2", DC_FAMILY_HW_OSTC, 1}, @@ -201,6 +205,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Zeagle", "N2iTiON3", DC_FAMILY_ZEAGLE_N2ITION3, 0}, {"Apeks", "Quantum X", DC_FAMILY_ZEAGLE_N2ITION3, 0}, {"Dive Rite", "NiTek Trio", DC_FAMILY_ZEAGLE_N2ITION3, 0}, + {"Scubapro", "XTender 5", DC_FAMILY_ZEAGLE_N2ITION3, 0}, /* Atomic Aquatics Cobalt */ #ifdef HAVE_LIBUSB {"Atomic Aquatics", "Cobalt", DC_FAMILY_ATOMICS_COBALT, 0}, diff --git a/src/device.c b/src/device.c index 22cea50..41738a5 100644 --- a/src/device.c +++ b/src/device.c @@ -322,6 +322,10 @@ dc_device_close (dc_device_t *device) if (device->vtable->close == NULL) return DC_STATUS_UNSUPPORTED; + // Disable the cancellation callback. + device->cancel_callback = NULL; + device->cancel_userdata = NULL; + return device->vtable->close (device); } diff --git a/src/hw_frog.c b/src/hw_frog.c index bda09b7..ec760ac 100644 --- a/src/hw_frog.c +++ b/src/hw_frog.c @@ -111,6 +111,9 @@ hw_frog_transfer (hw_frog_device_t *device, { dc_device_t *abstract = (dc_device_t *) device; + if (device_is_cancelled (abstract)) + return DC_STATUS_CANCELLED; + // Send the command. unsigned char command[1] = {cmd}; int n = serial_write (device->port, command, sizeof (command)); diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 3b19c03..1bcc73f 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -108,6 +108,9 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, { dc_device_t *abstract = (dc_device_t *) device; + if (device_is_cancelled (abstract)) + return DC_STATUS_CANCELLED; + // Send the command. unsigned char command[1] = {cmd}; int n = serial_write (device->port, command, sizeof (command)); @@ -392,8 +395,13 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi unsigned int idx = (latest + RB_LOGBOOK_COUNT - i) % RB_LOGBOOK_COUNT; unsigned int offset = idx * RB_LOGBOOK_SIZE; + // Get the firmware version. + unsigned int firmware = array_uint16_be (header + offset + 0x30); + // Calculate the profile length. unsigned int length = RB_LOGBOOK_SIZE + array_uint24_le (header + offset + 9) - 6; + if (firmware >= 93) + length += 3; // Check the fingerprint data. if (memcmp (header + offset + 12, device->fingerprint, sizeof (device->fingerprint)) == 0) @@ -428,8 +436,13 @@ hw_ostc3_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, voi unsigned int idx = (latest + RB_LOGBOOK_COUNT - i) % RB_LOGBOOK_COUNT; unsigned int offset = idx * RB_LOGBOOK_SIZE; + // Get the firmware version. + unsigned int firmware = array_uint16_be (header + offset + 0x30); + // Calculate the profile length. unsigned int length = RB_LOGBOOK_SIZE + array_uint24_le (header + offset + 9) - 6; + if (firmware >= 93) + length += 3; // Download the dive. unsigned char number[1] = {idx}; diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index 576afdf..b007377 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -482,6 +482,8 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call unsigned int nbits = 0; unsigned int events = 0; while (data[offset - 1] & 0x80) { + if (nbits && version != 0x23) + break; if (offset + 1 > size) return DC_STATUS_DATAFORMAT; events |= data[offset] << nbits; @@ -594,13 +596,27 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call } } - // SetPoint Change - if ((events & 0x40) && (version != 0x23)) { - if (offset + 1 > size) - return DC_STATUS_DATAFORMAT; - sample.setpoint = data[offset] / 100.0; - if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata); - offset++; + if (version != 0x23) { + // SetPoint Change + if (events & 0x40) { + if (offset + 1 > size) + return DC_STATUS_DATAFORMAT; + sample.setpoint = data[offset] / 100.0; + if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata); + offset++; + } + + // Bailout Event + if (events & 0x80) { + if (offset + 2 > size) + return DC_STATUS_DATAFORMAT; + sample.event.type = SAMPLE_EVENT_GASCHANGE2; + sample.event.time = 0; + sample.event.flags = 0; + sample.event.value = data[offset] | (data[offset + 1] << 16); + if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + offset += 2; + } } } diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index af628ed..5e09ea3 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -48,6 +48,7 @@ #define ICONHDNET 0x15 #define PUCKPRO 0x18 #define NEMOWIDE2 0x19 +#define PUCK2 0x1F #define ACK 0xAA #define EOF 0xEA @@ -89,10 +90,16 @@ static const mares_iconhd_layout_t mares_iconhd_layout = { 0x100000, /* rb_profile_end */ }; +static const mares_iconhd_layout_t mares_iconhdnet_layout = { + 0x100000, /* memsize */ + 0x00E000, /* rb_profile_begin */ + 0x100000, /* rb_profile_end */ +}; + static const mares_iconhd_layout_t mares_matrix_layout = { 0x40000, /* memsize */ 0x0A000, /* rb_profile_begin */ - 0x40000, /* rb_profile_end */ + 0x3E000, /* rb_profile_end */ }; static unsigned int @@ -121,6 +128,9 @@ mares_iconhd_transfer (mares_iconhd_device_t *device, assert (csize >= 2); + if (device_is_cancelled (abstract)) + return DC_STATUS_CANCELLED; + // Send the command header to the dive computer. int n = serial_write (device->port, command, 2); if (n != 2) { @@ -261,9 +271,12 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char * device->port = NULL; memset (device->fingerprint, 0, sizeof (device->fingerprint)); memset (device->version, 0, sizeof (device->version)); - if (model == NEMOWIDE2 || model == MATRIX || model == PUCKPRO) { + if (model == NEMOWIDE2 || model == MATRIX || model == PUCKPRO || model == PUCK2) { device->layout = &mares_matrix_layout; device->packetsize = 64; + } else if (model == ICONHDNET) { + device->layout = &mares_iconhdnet_layout; + device->packetsize = 0; } else { device->layout = &mares_iconhd_layout; device->packetsize = 0; @@ -278,7 +291,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, const char * } // Set the serial communication protocol (256000 8N1). - if (model == NEMOWIDE2 || model == MATRIX || model == PUCKPRO) { + if (model == NEMOWIDE2 || model == MATRIX || model == PUCKPRO || model == PUCK2) { rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_EVEN, 1, SERIAL_FLOWCONTROL_NONE); } else { rc = serial_configure (device->port, BAUDRATE, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE); diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 0c8668a..078d14f 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -55,6 +55,27 @@ static const dc_parser_vtable_t mares_iconhd_parser_vtable = { }; +/* Find how many gas mixes are in use */ +static unsigned int +mares_iconhd_parser_count_active_gas_mixes (const unsigned char *p, unsigned int air) +{ + if (air) { + return 1; + } else { + // Count the number of active gas mixes. The active gas + // mixes are always first, so we stop counting as soon + // as the first gas marked as disabled is found. + unsigned int i = 0; + while (i < 3) { + if (p[0x14 + i * 4 + 1] & 0x80) + break; + i++; + } + return i; + } +} + + dc_status_t mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model) { @@ -163,20 +184,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = array_uint16_le (p + 0x04) / 10.0; break; case DC_FIELD_GASMIX_COUNT: - if (air) { - *((unsigned int *) value) = 1; - } else { - // Count the number of active gas mixes. The active gas - // mixes are always first, so we stop counting as soon - // as the first gas marked as disabled is found. - unsigned int i = 0; - while (i < 3) { - if (p[0x14 + i * 4 + 1] & 0x80) - break; - i++; - } - *((unsigned int *) value) = i; - } + *((unsigned int *) value) = mares_iconhd_parser_count_active_gas_mixes (p, air); break; case DC_FIELD_GASMIX: if (air) @@ -186,6 +194,10 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi gasmix->helium = 0.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; + case DC_FIELD_ATMOSPHERIC: + // Pressure (1/8 millibar) + *((double *) value) = array_uint16_le (p + 0x26) / 8000.0; + break; default: return DC_STATUS_UNSUPPORTED; } @@ -215,6 +227,10 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t if (abstract->size < length || length < header + 4) return DC_STATUS_DATAFORMAT; + const unsigned char *p = abstract->data + length - header; + + unsigned int air = (p[0] & 0x02) == 0; + const unsigned char *data = abstract->data; unsigned int size = length - header; @@ -223,6 +239,11 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t unsigned int offset = 4; unsigned int nsamples = 0; + + // Previous gas mix - initialize with impossible value + unsigned int gasmix_previous = 0xFFFFFFFF; + unsigned int ngasmixes = mares_iconhd_parser_count_active_gas_mixes (p, air); + while (offset + samplesize <= size) { dc_sample_value_t sample = {0}; @@ -237,10 +258,28 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); // Temperature (1/10 °C). - unsigned int temperature = array_uint16_le (data + offset + 2); + unsigned int temperature = array_uint16_le (data + offset + 2) & 0x0FFF; sample.temperature = temperature / 10.0; if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); + // Current gas mix + unsigned int gasmix = (data[offset + 3] & 0xF0) >> 4; + if (gasmix >= ngasmixes) { + return DC_STATUS_DATAFORMAT; + } + if (gasmix != gasmix_previous) { + unsigned int o2 = 0; + if (air) + o2 = 21; + else + o2 = p[0x14 + gasmix * 4]; + sample.event.type = SAMPLE_EVENT_GASCHANGE; + sample.event.time = 0; + sample.event.value = o2; + if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + gasmix_previous = gasmix; + } + offset += samplesize; nsamples++; diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 858345e..2f30721 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -108,16 +108,27 @@ static const oceanic_common_version_t oceanic_default_version[] = { static const oceanic_common_version_t tusa_zenair_version[] = { {"TUZENAIR \0\0 512K"}, + {"AMPHOSSW \0\0 512K"}, }; static const oceanic_common_version_t oceanic_oc1_version[] = { {"OCWATCH R\0\0 1024"}, - {"OCEANVT4 \0\0 1024"}, {"OC1WATCH \0\0 1024"}, - {"OCEATOM3 \0\0 1024"}, {"OCSWATCH \0\0 1024"}, - {"OCEAVT41 \0\0 1024"}, +}; + +static const oceanic_common_version_t oceanic_oci_version[] = { + {"OCEANOCI \0\0 1024"}, +}; + +static const oceanic_common_version_t oceanic_atom3_version[] = { + {"OCEATOM3 \0\0 1024"}, {"ATOM31 \0\0 1024"}, +}; + +static const oceanic_common_version_t oceanic_vt4_version[] = { + {"OCEANVT4 \0\0 1024"}, + {"OCEAVT41 \0\0 1024"}, {"AERISAIR \0\0 1024"}, }; @@ -234,6 +245,45 @@ static const oceanic_common_layout_t oceanic_oc1_layout = { 1 /* pt_mode_logbook */ }; +static const oceanic_common_layout_t oceanic_oci_layout = { + 0x20000, /* memsize */ + 0x0000, /* cf_devinfo */ + 0x0040, /* cf_pointers */ + 0x10C0, /* rb_logbook_begin */ + 0x1400, /* rb_logbook_end */ + 8, /* rb_logbook_entry_size */ + 0x1400, /* rb_profile_begin */ + 0x1FE00, /* rb_profile_end */ + 0, /* pt_mode_global */ + 1 /* pt_mode_logbook */ +}; + +static const oceanic_common_layout_t oceanic_atom3_layout = { + 0x20000, /* memsize */ + 0x0000, /* cf_devinfo */ + 0x0040, /* cf_pointers */ + 0x0400, /* rb_logbook_begin */ + 0x0A40, /* rb_logbook_end */ + 8, /* rb_logbook_entry_size */ + 0x0A40, /* rb_profile_begin */ + 0x1FE00, /* rb_profile_end */ + 0, /* pt_mode_global */ + 1 /* pt_mode_logbook */ +}; + +static const oceanic_common_layout_t oceanic_vt4_layout = { + 0x20000, /* memsize */ + 0x0000, /* cf_devinfo */ + 0x0040, /* cf_pointers */ + 0x0420, /* rb_logbook_begin */ + 0x0A40, /* rb_logbook_end */ + 8, /* rb_logbook_entry_size */ + 0x0A40, /* rb_profile_begin */ + 0x1FE00, /* rb_profile_end */ + 0, /* pt_mode_global */ + 1 /* pt_mode_logbook */ +}; + static const oceanic_common_layout_t oceanic_veo1_layout = { 0x0400, /* memsize */ 0x0000, /* cf_devinfo */ @@ -434,6 +484,12 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char device->base.layout = &tusa_zenair_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_oc1_version)) { device->base.layout = &oceanic_oc1_layout; + } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_oci_version)) { + device->base.layout = &oceanic_oci_layout; + } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_atom3_version)) { + device->base.layout = &oceanic_atom3_layout; + } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_vt4_version)) { + device->base.layout = &oceanic_vt4_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_veo1_version)) { device->base.layout = &oceanic_veo1_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_reactpro_version)) { diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index de5e116..a3cd39c 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -45,6 +45,7 @@ #define VEO20 0x4359 #define VEO30 0x435A #define ZENAIR 0x4442 +#define ATMOSAI2 0x4443 #define PROPLUS21 0x4444 #define GEO20 0x4446 #define VT4 0x4447 @@ -57,7 +58,9 @@ #define EPICB 0x4453 #define ATOM31 0x4456 #define A300AI 0x4457 +#define AMPHOS 0x4545 #define PROPLUS3 0x4548 +#define OCI 0x454B typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t; @@ -166,6 +169,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim case ATOM3: case ATOM31: case A300AI: + case OCI: datetime->year = ((p[5] & 0xE0) >> 5) + ((p[7] & 0xE0) >> 2) + 2000; datetime->month = (p[3] & 0x0F); datetime->day = ((p[0] & 0x80) >> 3) + ((p[3] & 0xF0) >> 4); @@ -175,7 +179,6 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim case VT3: case VEO20: case VEO30: - case GEO20: case DG03: datetime->year = ((p[3] & 0xE0) >> 1) + (p[4] & 0x0F) + 2000; datetime->month = (p[4] & 0xF0) >> 4; @@ -184,6 +187,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim datetime->minute = bcd2dec (p[0]); break; case ZENAIR: + case AMPHOS: datetime->year = (p[3] & 0x0F) + 2000; datetime->month = (p[7] & 0xF0) >> 4; datetime->day = ((p[3] & 0x80) >> 3) + ((p[5] & 0xF0) >> 4); @@ -201,7 +205,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim default: datetime->year = bcd2dec (((p[3] & 0xC0) >> 2) + (p[4] & 0x0F)) + 2000; datetime->month = (p[4] & 0xF0) >> 4; - if (parser->model == T3) + if (parser->model == T3 || parser->model == GEO20) datetime->day = p[3] & 0x3F; else datetime->day = bcd2dec (p[3] & 0x3F); @@ -394,14 +398,15 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ } unsigned int samplesize = PAGESIZE / 2; - if (parser->model == OC1A || parser->model == OC1B || parser->model == OC1C) + if (parser->model == OC1A || parser->model == OC1B || + parser->model == OC1C || parser->model == OCI) samplesize = PAGESIZE; else if (parser->model == F10) samplesize = 2; unsigned int have_temperature = 1, have_pressure = 1; if (parser->model == VEO30 || parser->model == OCS || - parser->model == ELEMENT2) { + parser->model == ELEMENT2 || parser->model == VEO20) { have_pressure = 0; } else if (parser->model == F10) { have_temperature = 0; @@ -504,7 +509,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ temperature = data[offset + 6]; } else if (parser->model == GEO20 || parser->model == VEO20 || parser->model == VEO30 || parser->model == OC1A || - parser->model == OC1B || parser->model == OC1C) { + parser->model == OC1B || parser->model == OC1C || + parser->model == OCI) { temperature = data[offset + 3]; } else if (parser->model == OCS) { temperature = data[offset + 1]; @@ -515,7 +521,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ if (parser->model == DG03 || parser->model == PROPLUS3) sign = (~data[offset + 5] & 0x04) >> 2; else if (parser->model == ATOM2 || parser->model == PROPLUS21 || - parser->model == EPICA || parser->model == EPICB) + parser->model == EPICA || parser->model == EPICB || + parser->model == ATMOSAI2 || parser->model == AMPHOS) sign = (data[offset + 0] & 0x80) >> 7; else sign = (~data[offset + 0] & 0x80) >> 7; @@ -530,7 +537,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ // Tank Pressure (psi) if (have_pressure) { - if (parser->model == OC1A || parser->model == OC1B || parser->model == OC1C) + if (parser->model == OC1A || parser->model == OC1B || + parser->model == OC1C || parser->model == OCI) pressure = (data[offset + 10] + (data[offset + 11] << 8)) & 0x0FFF; else if (parser->model == VT4 || parser->model == VT41|| parser->model == ATOM3 || parser->model == ATOM31 || @@ -548,7 +556,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int depth; if (parser->model == GEO20 || parser->model == VEO20 || parser->model == VEO30 || parser->model == OC1A || - parser->model == OC1B || parser->model == OC1C) + parser->model == OC1B || parser->model == OC1C || + parser->model == OCI) depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF; else if (parser->model == ATOM1) depth = data[offset + 3] * 16; diff --git a/src/shearwater_common.c b/src/shearwater_common.c index 8e4f493..b809a3c 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -148,6 +148,8 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned const unsigned char end[] = {END}; const unsigned char esc_end[] = {ESC, ESC_END}; const unsigned char esc_esc[] = {ESC, ESC_ESC}; + unsigned char buffer[32]; + unsigned int nbytes = 0; #if 0 // Send an initial END character to flush out any data that may have @@ -179,15 +181,28 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned break; } - n = serial_write (device->port, seq, len); - if (n != len) { - return EXITCODE(n); + // Flush the buffer if necessary. + if (nbytes + len + sizeof(end) > sizeof(buffer)) { + n = serial_write (device->port, buffer, nbytes); + if (n != nbytes) { + return EXITCODE(n); + } + + nbytes = 0; } + + // Append the escaped character. + memcpy(buffer + nbytes, seq, len); + nbytes += len; } - // Send the END character to indicate the end of the packet. - n = serial_write (device->port, end, sizeof (end)); - if (n != sizeof (end)) { + // Append the END character to indicate the end of the packet. + memcpy(buffer + nbytes, end, sizeof(end)); + nbytes += sizeof(end); + + // Flush the buffer. + n = serial_write (device->port, buffer, nbytes); + if (n != nbytes) { return EXITCODE(n); } @@ -266,6 +281,9 @@ shearwater_common_transfer (shearwater_common_device_t *device, const unsigned c if (isize > SZ_PACKET || osize > SZ_PACKET) return DC_STATUS_INVALIDARGS; + if (device_is_cancelled (abstract)) + return DC_STATUS_CANCELLED; + // Setup the request packet. packet[0] = 0xFF; packet[1] = 0x01; diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 43c44b5..320a00c 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -88,7 +88,7 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig // Initialize the base class. parser->petrel = petrel; if (petrel) { - parser_init (&parser->base, context, &shearwater_predator_parser_vtable); + parser_init (&parser->base, context, &shearwater_petrel_parser_vtable); } else { parser_init (&parser->base, context, &shearwater_predator_parser_vtable); } diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 11c7d0f..65e7e87 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -482,8 +482,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca case 0x06: // Mandatory Safety Stop Ceiling Error sample.event.type = SAMPLE_EVENT_CEILING_SAFETYSTOP; break; - case 0x07: // Unknown (Deco related) - sample.event.type = SAMPLE_EVENT_UNKNOWN; + case 0x07: // Below Deco Floor + sample.event.type = SAMPLE_EVENT_FLOOR; break; case 0x08: // Dive Time sample.event.type = SAMPLE_EVENT_DIVETIME; diff --git a/src/suunto_eon.c b/src/suunto_eon.c index 31a1eda..de7d2aa 100644 --- a/src/suunto_eon.c +++ b/src/suunto_eon.c @@ -105,7 +105,7 @@ suunto_eon_device_open (dc_device_t **out, dc_context_t *context, const char *na } // Set the timeout for receiving data (1000ms). - if (serial_set_timeout (device->port, -1) == -1) { + if (serial_set_timeout (device->port, 1000) == -1) { ERROR (context, "Failed to set the timeout."); serial_close (device->port); free (device); @@ -170,16 +170,34 @@ suunto_eon_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) } // Receive the answer. + unsigned int nbytes = 0; unsigned char answer[SZ_MEMORY + 1] = {0}; - rc = serial_read (device->port, answer, sizeof (answer)); - if (rc != sizeof (answer)) { - ERROR (abstract->context, "Failed to receive the answer."); - return EXITCODE (rc); - } + while (nbytes < sizeof(answer)) { + // Set the minimum packet size. + unsigned int len = 64; - // Update and emit a progress event. - progress.current += sizeof (answer); - device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + // Increase the packet size if more data is immediately available. + int available = serial_get_received (device->port); + if (available > len) + len = available; + + // Limit the packet size to the total size. + if (nbytes + len > sizeof(answer)) + len = sizeof(answer) - nbytes; + + // Read the packet. + int n = serial_read (device->port, answer + nbytes, len); + if (n != len) { + ERROR (abstract->context, "Failed to receive the answer."); + return EXITCODE (n); + } + + // Update and emit a progress event. + progress.current += len; + device_event_emit (abstract, DC_EVENT_PROGRESS, &progress); + + nbytes += len; + } // Verify the checksum of the package. unsigned char crc = answer[sizeof (answer) - 1]; diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 97f6ae1..b4d7508 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -39,6 +39,7 @@ #define ALADINTEC 0x12 #define ALADINTEC2G 0x13 #define SMARTCOM 0x14 +#define ALADIN2G 0x15 #define SMARTTEC 0x18 #define GALILEOTRIMIX 0x19 #define SMARTZ 0x1C @@ -207,6 +208,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi break; case GALILEO: case GALILEOTRIMIX: + case ALADIN2G: case MERIDIAN: header = 152; if (data[43] & 0x80) { @@ -456,6 +458,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t break; case GALILEO: case GALILEOTRIMIX: + case ALADIN2G: case MERIDIAN: header = 152; if (data[43] & 0x80) { @@ -522,7 +525,8 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Process the type bits in the bitstream. unsigned int id = 0; - if (parser->model == GALILEO || parser->model == GALILEOTRIMIX || parser->model == MERIDIAN) { + if (parser->model == GALILEO || parser->model == GALILEOTRIMIX || + parser->model == ALADIN2G || parser->model == MERIDIAN) { // Uwatec Galileo id = uwatec_galileo_identify (data[offset]); } else { diff --git a/src/zeagle_n2ition3.c b/src/zeagle_n2ition3.c index 4d6db49..1e19d49 100644 --- a/src/zeagle_n2ition3.c +++ b/src/zeagle_n2ition3.c @@ -79,6 +79,9 @@ zeagle_n2ition3_packet (zeagle_n2ition3_device_t *device, const unsigned char co assert (asize >= csize + 5); + if (device_is_cancelled (abstract)) + return DC_STATUS_CANCELLED; + // Send the command to the device. int n = serial_write (device->port, command, csize); if (n != csize) {