Merge git://github.com/libdivecomputer/libdivecomputer into Subsurface-NG
Sync up with Jef's upstream changes. About half of it was stuff we'd already done: i770R support (together with the Oceanic dive truncation) and the change to the Scubapro G2 BLE protocol. And once again, Jef has taken the work of others (me and Janice) and made pointless changes to it just to make merging harder. And once again, I tried to match up with upstream as much as possible to make future merges easier. But it annoys me. This *may* also get the Aqualung i300C working over bluetooth. I have no real way to test, but the basic parsing support is there thanks to Jef, and Janice implied that the BLE handshaking is the same as the i770R. * 'master' of git://github.com/libdivecomputer/libdivecomputer: Add support for the Aqualung i300C Add support for the Aqualung i770R Fix the Pro Plus X gas mixes Oceanic: fix up dive truncation issues Scubapro G2: update BLE downloading for new 1.4 firmware version Add a workaround for invalid ringbuffer begin pointers
This commit is contained in:
commit
e34e211c3e
@ -220,6 +220,7 @@ static const dc_descriptor_t g_descriptors[] = {
|
|||||||
{"Aqualung", "i450T", DC_FAMILY_OCEANIC_ATOM2, 0x4641, DC_TRANSPORT_SERIAL, NULL},
|
{"Aqualung", "i450T", DC_FAMILY_OCEANIC_ATOM2, 0x4641, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Aqualung", "i550", DC_FAMILY_OCEANIC_ATOM2, 0x4642, DC_TRANSPORT_SERIAL, NULL},
|
{"Aqualung", "i550", DC_FAMILY_OCEANIC_ATOM2, 0x4642, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Aqualung", "i200", DC_FAMILY_OCEANIC_ATOM2, 0x4646, DC_TRANSPORT_SERIAL, NULL},
|
{"Aqualung", "i200", DC_FAMILY_OCEANIC_ATOM2, 0x4646, DC_TRANSPORT_SERIAL, NULL},
|
||||||
|
{"Aqualung", "i300C", DC_FAMILY_OCEANIC_ATOM2, 0x4648, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
|
||||||
{"Aqualung", "i100", DC_FAMILY_OCEANIC_ATOM2, 0x464E, DC_TRANSPORT_SERIAL, NULL},
|
{"Aqualung", "i100", DC_FAMILY_OCEANIC_ATOM2, 0x464E, DC_TRANSPORT_SERIAL, NULL},
|
||||||
{"Aqualung", "i770R", DC_FAMILY_OCEANIC_ATOM2, 0x4651, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
|
{"Aqualung", "i770R", DC_FAMILY_OCEANIC_ATOM2, 0x4651, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, NULL},
|
||||||
/* Mares Nemo */
|
/* Mares Nemo */
|
||||||
|
|||||||
@ -122,6 +122,7 @@ static const oceanic_common_version_t oceanic_atom2b_version[] = {
|
|||||||
{"AQUAI300 \0\0 512K"},
|
{"AQUAI300 \0\0 512K"},
|
||||||
{"HOLLDG03 \0\0 512K"},
|
{"HOLLDG03 \0\0 512K"},
|
||||||
{"AQUAI100 \0\0 512K"},
|
{"AQUAI100 \0\0 512K"},
|
||||||
|
{"AQUA300C \0\0 512K"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const oceanic_common_version_t oceanic_atom2c_version[] = {
|
static const oceanic_common_version_t oceanic_atom2c_version[] = {
|
||||||
@ -487,21 +488,6 @@ static const oceanic_common_layout_t oceanic_proplusx_layout = {
|
|||||||
0, /* pt_mode_serial */
|
0, /* pt_mode_serial */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const oceanic_common_layout_t aeris_a300cs_layout = {
|
|
||||||
0x40000, /* memsize */
|
|
||||||
0, /* highmem */
|
|
||||||
0x0000, /* cf_devinfo */
|
|
||||||
0x0040, /* cf_pointers */
|
|
||||||
0x0900, /* rb_logbook_begin */
|
|
||||||
0x1000, /* rb_logbook_end */
|
|
||||||
16, /* rb_logbook_entry_size */
|
|
||||||
0x1000, /* rb_profile_begin */
|
|
||||||
0x3FE00, /* rb_profile_end */
|
|
||||||
0, /* pt_mode_global */
|
|
||||||
1, /* pt_mode_logbook */
|
|
||||||
0, /* pt_mode_serial */
|
|
||||||
};
|
|
||||||
|
|
||||||
static const oceanic_common_layout_t aqualung_i770r_layout = {
|
static const oceanic_common_layout_t aqualung_i770r_layout = {
|
||||||
0x440000, /* memsize */
|
0x440000, /* memsize */
|
||||||
0x40000, /* highmem */
|
0x40000, /* highmem */
|
||||||
@ -517,6 +503,21 @@ static const oceanic_common_layout_t aqualung_i770r_layout = {
|
|||||||
0, /* pt_mode_serial */
|
0, /* pt_mode_serial */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const oceanic_common_layout_t aeris_a300cs_layout = {
|
||||||
|
0x40000, /* memsize */
|
||||||
|
0, /* highmem */
|
||||||
|
0x0000, /* cf_devinfo */
|
||||||
|
0x0040, /* cf_pointers */
|
||||||
|
0x0900, /* rb_logbook_begin */
|
||||||
|
0x1000, /* rb_logbook_end */
|
||||||
|
16, /* rb_logbook_entry_size */
|
||||||
|
0x1000, /* rb_profile_begin */
|
||||||
|
0x3FE00, /* rb_profile_end */
|
||||||
|
0, /* pt_mode_global */
|
||||||
|
1, /* pt_mode_logbook */
|
||||||
|
0, /* pt_mode_serial */
|
||||||
|
};
|
||||||
|
|
||||||
static const oceanic_common_layout_t aqualung_i450t_layout = {
|
static const oceanic_common_layout_t aqualung_i450t_layout = {
|
||||||
0x40000, /* memsize */
|
0x40000, /* memsize */
|
||||||
0, /* highmem */
|
0, /* highmem */
|
||||||
@ -867,17 +868,9 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, dc_iostream
|
|||||||
memset(device->cache, 0, sizeof(device->cache));
|
memset(device->cache, 0, sizeof(device->cache));
|
||||||
|
|
||||||
// Get the correct baudrate.
|
// Get the correct baudrate.
|
||||||
unsigned int baudrate;
|
unsigned int baudrate = 38400;
|
||||||
switch (model) {
|
if (model == VTX || model == I750TC || model == PROPLUSX || model == I770R) {
|
||||||
case VTX:
|
|
||||||
case I750TC:
|
|
||||||
case PROPLUSX:
|
|
||||||
case I770R:
|
|
||||||
baudrate = 115200;
|
baudrate = 115200;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
baudrate = 38400;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the serial communication protocol (38400 8N1).
|
// Set the serial communication protocol (38400 8N1).
|
||||||
@ -979,12 +972,12 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, dc_iostream
|
|||||||
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_proplusx_version)) {
|
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_proplusx_version)) {
|
||||||
device->base.layout = &oceanic_proplusx_layout;
|
device->base.layout = &oceanic_proplusx_layout;
|
||||||
device->bigpage = 16;
|
device->bigpage = 16;
|
||||||
} else if (OCEANIC_COMMON_MATCH (device->base.version, aeris_a300cs_version)) {
|
|
||||||
device->base.layout = &aeris_a300cs_layout;
|
|
||||||
device->bigpage = 16;
|
|
||||||
} else if (OCEANIC_COMMON_MATCH (device->base.version, aqualung_i770r_version)) {
|
} else if (OCEANIC_COMMON_MATCH (device->base.version, aqualung_i770r_version)) {
|
||||||
device->base.layout = &aqualung_i770r_layout;
|
device->base.layout = &aqualung_i770r_layout;
|
||||||
device->bigpage = 16;
|
device->bigpage = 16;
|
||||||
|
} else if (OCEANIC_COMMON_MATCH (device->base.version, aeris_a300cs_version)) {
|
||||||
|
device->base.layout = &aeris_a300cs_layout;
|
||||||
|
device->bigpage = 16;
|
||||||
} else if (OCEANIC_COMMON_MATCH (device->base.version, aqualung_i450t_version)) {
|
} else if (OCEANIC_COMMON_MATCH (device->base.version, aqualung_i450t_version)) {
|
||||||
device->base.layout = &aqualung_i450t_layout;
|
device->base.layout = &aqualung_i450t_layout;
|
||||||
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_default_version)) {
|
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_default_version)) {
|
||||||
|
|||||||
@ -88,6 +88,7 @@
|
|||||||
#define I450T 0x4641
|
#define I450T 0x4641
|
||||||
#define I550 0x4642
|
#define I550 0x4642
|
||||||
#define I200 0x4646
|
#define I200 0x4646
|
||||||
|
#define I300C 0x4648
|
||||||
#define I100 0x464E
|
#define I100 0x464E
|
||||||
#define I770R 0x4651
|
#define I770R 0x4651
|
||||||
|
|
||||||
@ -162,7 +163,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
|||||||
model == A300 || model == MANTA ||
|
model == A300 || model == MANTA ||
|
||||||
model == INSIGHT2 || model == ZEN ||
|
model == INSIGHT2 || model == ZEN ||
|
||||||
model == I300 || model == I550 ||
|
model == I300 || model == I550 ||
|
||||||
model == I200) {
|
model == I200 || model == I300C) {
|
||||||
parser->headersize -= PAGESIZE;
|
parser->headersize -= PAGESIZE;
|
||||||
} else if (model == VT4 || model == VT41) {
|
} else if (model == VT4 || model == VT41) {
|
||||||
parser->headersize += PAGESIZE;
|
parser->headersize += PAGESIZE;
|
||||||
@ -280,6 +281,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
|
|||||||
case I300:
|
case I300:
|
||||||
case I200:
|
case I200:
|
||||||
case I100:
|
case I100:
|
||||||
|
case I300C:
|
||||||
datetime->year = ((p[3] & 0xE0) >> 1) + (p[4] & 0x0F) + 2000;
|
datetime->year = ((p[3] & 0xE0) >> 1) + (p[4] & 0x0F) + 2000;
|
||||||
datetime->month = (p[4] & 0xF0) >> 4;
|
datetime->month = (p[4] & 0xF0) >> 4;
|
||||||
datetime->day = p[3] & 0x1F;
|
datetime->day = p[3] & 0x1F;
|
||||||
@ -424,7 +426,7 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
|||||||
unsigned int ngasmixes = 0;
|
unsigned int ngasmixes = 0;
|
||||||
unsigned int o2_offset = 0;
|
unsigned int o2_offset = 0;
|
||||||
unsigned int he_offset = 0;
|
unsigned int he_offset = 0;
|
||||||
unsigned int pO2_offset = 1;
|
unsigned int o2_step = 1;
|
||||||
if (mode == FREEDIVE) {
|
if (mode == FREEDIVE) {
|
||||||
ngasmixes = 0;
|
ngasmixes = 0;
|
||||||
} else if (parser->model == DATAMASK || parser->model == COMPUMASK) {
|
} else if (parser->model == DATAMASK || parser->model == COMPUMASK) {
|
||||||
@ -466,7 +468,7 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
|||||||
} else if (parser->model == I770R) {
|
} else if (parser->model == I770R) {
|
||||||
o2_offset = 0x30;
|
o2_offset = 0x30;
|
||||||
ngasmixes = 4;
|
ngasmixes = 4;
|
||||||
pO2_offset = 2;
|
o2_step = 2;
|
||||||
} else {
|
} else {
|
||||||
o2_offset = header + 4;
|
o2_offset = header + 4;
|
||||||
ngasmixes = 3;
|
ngasmixes = 3;
|
||||||
@ -478,8 +480,8 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
|||||||
parser->mode = mode;
|
parser->mode = mode;
|
||||||
parser->ngasmixes = ngasmixes;
|
parser->ngasmixes = ngasmixes;
|
||||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||||
if (data[o2_offset + i*pO2_offset]) {
|
if (data[o2_offset + i * o2_step]) {
|
||||||
parser->oxygen[i] = data[o2_offset + i*pO2_offset];
|
parser->oxygen[i] = data[o2_offset + i * o2_step];
|
||||||
} else {
|
} else {
|
||||||
parser->oxygen[i] = 21;
|
parser->oxygen[i] = 21;
|
||||||
}
|
}
|
||||||
@ -728,7 +730,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == A300 || parser->model == ZEN ||
|
parser->model == A300 || parser->model == ZEN ||
|
||||||
parser->model == GEO || parser->model == GEO20 ||
|
parser->model == GEO || parser->model == GEO20 ||
|
||||||
parser->model == MANTA || parser->model == I300 ||
|
parser->model == MANTA || parser->model == I300 ||
|
||||||
parser->model == I200 || parser->model == I100) {
|
parser->model == I200 || parser->model == I100 ||
|
||||||
|
parser->model == I300C) {
|
||||||
have_pressure = 0;
|
have_pressure = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,7 +886,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == OC1B || parser->model == OC1C ||
|
parser->model == OC1B || parser->model == OC1C ||
|
||||||
parser->model == OCI || parser->model == A300 ||
|
parser->model == OCI || parser->model == A300 ||
|
||||||
parser->model == I450T || parser->model == I300 ||
|
parser->model == I450T || parser->model == I300 ||
|
||||||
parser->model == I200 || parser->model == I100) {
|
parser->model == I200 || parser->model == I100 ||
|
||||||
|
parser->model == I300C) {
|
||||||
temperature = data[offset + 3];
|
temperature = data[offset + 3];
|
||||||
} else if (parser->model == OCS || parser->model == TX1) {
|
} else if (parser->model == OCS || parser->model == TX1) {
|
||||||
temperature = data[offset + 1];
|
temperature = data[offset + 1];
|
||||||
@ -953,7 +957,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
parser->model == OC1B || parser->model == OC1C ||
|
parser->model == OC1B || parser->model == OC1C ||
|
||||||
parser->model == OCI || parser->model == A300 ||
|
parser->model == OCI || parser->model == A300 ||
|
||||||
parser->model == I450T || parser->model == I300 ||
|
parser->model == I450T || parser->model == I300 ||
|
||||||
parser->model == I200 || parser->model == I100)
|
parser->model == I200 || parser->model == I100 ||
|
||||||
|
parser->model == I300C)
|
||||||
depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF;
|
depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF;
|
||||||
else if (parser->model == ATOM1)
|
else if (parser->model == ATOM1)
|
||||||
depth = data[offset + 3] * 16;
|
depth = data[offset + 3] * 16;
|
||||||
@ -1004,7 +1009,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
} else if (parser->model == I200 || parser->model == I300 ||
|
} else if (parser->model == I200 || parser->model == I300 ||
|
||||||
parser->model == OC1A || parser->model == OC1B ||
|
parser->model == OC1A || parser->model == OC1B ||
|
||||||
parser->model == OC1C || parser->model == OCI ||
|
parser->model == OC1C || parser->model == OCI ||
|
||||||
parser->model == I100) {
|
parser->model == I100 || parser->model == I300C) {
|
||||||
decostop = (data[offset + 7] & 0xF0) >> 4;
|
decostop = (data[offset + 7] & 0xF0) >> 4;
|
||||||
decotime = array_uint16_le(data + offset + 6) & 0x0FFF;
|
decotime = array_uint16_le(data + offset + 6) & 0x0FFF;
|
||||||
have_deco = 1;
|
have_deco = 1;
|
||||||
@ -1028,7 +1033,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
|||||||
have_rbt = 1;
|
have_rbt = 1;
|
||||||
} else if (parser->model == I450T || parser->model == OC1A ||
|
} else if (parser->model == I450T || parser->model == OC1A ||
|
||||||
parser->model == OC1B || parser->model == OC1C ||
|
parser->model == OC1B || parser->model == OC1C ||
|
||||||
parser->model == OCI || parser->model == PROPLUSX) {
|
parser->model == OCI || parser->model == PROPLUSX ||
|
||||||
|
parser->model == I770R) {
|
||||||
rbt = array_uint16_le(data + offset + 8) & 0x01FF;
|
rbt = array_uint16_le(data + offset + 8) & 0x01FF;
|
||||||
have_rbt = 1;
|
have_rbt = 1;
|
||||||
} else if (parser->model == VISION || parser->model == XPAIR ||
|
} else if (parser->model == VISION || parser->model == XPAIR ||
|
||||||
|
|||||||
@ -287,16 +287,22 @@ suunto_common2_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
|
|||||||
if (last < layout->rb_profile_begin ||
|
if (last < layout->rb_profile_begin ||
|
||||||
last >= layout->rb_profile_end ||
|
last >= layout->rb_profile_end ||
|
||||||
end < layout->rb_profile_begin ||
|
end < layout->rb_profile_begin ||
|
||||||
end >= layout->rb_profile_end ||
|
end >= layout->rb_profile_end)
|
||||||
begin < layout->rb_profile_begin ||
|
|
||||||
begin >= layout->rb_profile_end)
|
|
||||||
{
|
{
|
||||||
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x 0x%04x %u).", begin, last, end, count);
|
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x 0x%04x %u).", begin, last, end, count);
|
||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the total amount of bytes.
|
// Calculate the total amount of bytes.
|
||||||
unsigned int remaining = RB_PROFILE_DISTANCE (layout, begin, end, count != 0);
|
unsigned int remaining = 0;
|
||||||
|
if (begin < layout->rb_profile_begin || begin >= layout->rb_profile_end) {
|
||||||
|
// Fall back to downloading the entire ringbuffer as workaround
|
||||||
|
// for an invalid begin pointer!
|
||||||
|
ERROR (abstract->context, "Invalid ringbuffer pointer detected (0x%04x 0x%04x 0x%04x %u).", begin, last, end, count);
|
||||||
|
remaining = layout->rb_profile_end - layout->rb_profile_begin;
|
||||||
|
} else {
|
||||||
|
remaining = RB_PROFILE_DISTANCE (layout, begin, end, count != 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Update and emit a progress event.
|
// Update and emit a progress event.
|
||||||
progress.maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - remaining;
|
progress.maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - remaining;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user