Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update libdivecomputer from Upstream. #71

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/android/Android.mk
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ LOCAL_SRC_FILES := \
src/array.c \
src/atomics_cobalt.c \
src/atomics_cobalt_parser.c \
src/ble.c \
src/bluetooth.c \
src/buffer.c \
src/checksum.c \
1 change: 1 addition & 0 deletions contrib/msvc/libdivecomputer.vcxproj
Original file line number Diff line number Diff line change
@@ -177,6 +177,7 @@
<ClCompile Include="..\..\src\array.c" />
<ClCompile Include="..\..\src\atomics_cobalt.c" />
<ClCompile Include="..\..\src\atomics_cobalt_parser.c" />
<ClCompile Include="..\..\src\ble.c" />
<ClCompile Include="..\..\src\bluetooth.c" />
<ClCompile Include="..\..\src\buffer.c" />
<ClCompile Include="..\..\src\checksum.c" />
4 changes: 2 additions & 2 deletions examples/dctool_timesync.c
Original file line number Diff line number Diff line change
@@ -85,10 +85,10 @@ do_timesync (dc_context_t *context, dc_descriptor_t *descriptor, dc_transport_t
}

// Syncronize the device clock.
message ("Syncronize the device clock.\n");
message ("Synchronize the device clock.\n");
rc = dc_device_timesync (device, datetime);
if (rc != DC_STATUS_SUCCESS) {
ERROR ("Error syncronizing the device clock.");
ERROR ("Error synchronizing the device clock.");
goto cleanup;
}

53 changes: 53 additions & 0 deletions include/libdivecomputer/ble.h
Original file line number Diff line number Diff line change
@@ -48,6 +48,59 @@ extern "C" {
#define DC_IOCTL_BLE_GET_ACCESSCODE DC_IOCTL_IOR('b', 2, DC_IOCTL_SIZE_VARIABLE)
#define DC_IOCTL_BLE_SET_ACCESSCODE DC_IOCTL_IOW('b', 2, DC_IOCTL_SIZE_VARIABLE)

/**
* Perform a BLE characteristic read/write operation.
*
* The UUID of the characteristic must be specified as a #dc_ble_uuid_t
* data structure. If the operation requires additional data as in- or
* output, the buffer must be located immediately after the
* #dc_ble_uuid_t data structure. The size of the ioctl request is the
* total size, including the size of the #dc_ble_uuid_t structure.
*/
#define DC_IOCTL_BLE_CHARACTERISTIC_READ DC_IOCTL_IOR('b', 3, DC_IOCTL_SIZE_VARIABLE)
#define DC_IOCTL_BLE_CHARACTERISTIC_WRITE DC_IOCTL_IOW('b', 3, DC_IOCTL_SIZE_VARIABLE)

/**
* The minimum number of bytes (including the terminating null byte) for
* formatting a bluetooth UUID as a string.
*/
#define DC_BLE_UUID_SIZE 37

/**
* Bluetooth UUID (128 bits).
*/
typedef unsigned char dc_ble_uuid_t[16];

/**
* Convert a bluetooth UUID to a string.
*
* The bluetooth UUID is formatted as
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where each XX pair is a
* hexadecimal number specifying an octet of the UUID.
* The minimum size for the buffer is #DC_BLE_UUID_SIZE bytes.
*
* @param[in] uuid A bluetooth UUID.
* @param[in] str The memory buffer to store the result.
* @param[in] size The size of the memory buffer.
* @returns The null-terminated string on success, or NULL on failure.
*/
char *
dc_ble_uuid2str (const dc_ble_uuid_t uuid, char *str, size_t size);

/**
* Convert a string to a bluetooth UUID.
*
* The string is expected to be in the format
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where each XX pair is a
* hexadecimal number specifying an octet of the UUID.
*
* @param[in] str A null-terminated string.
* @param[in] uuid The memory buffer to store the result.
* @returns Non-zero on success, or zero on failure.
*/
int
dc_ble_str2uuid (const char *str, dc_ble_uuid_t uuid);

#ifdef __cplusplus
}
#endif /* __cplusplus */
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ libdivecomputer_la_SOURCES = \
irda.c \
usb.c \
usbhid.c \
ble.c \
bluetooth.c \
custom.c

97 changes: 97 additions & 0 deletions src/ble.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* libdivecomputer
*
* Copyright (C) 2024 Jef Driesen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>

#include <libdivecomputer/ble.h>

#include "platform.h"

char *
dc_ble_uuid2str (const dc_ble_uuid_t uuid, char *str, size_t size)
{
if (str == NULL || size < DC_BLE_UUID_SIZE)
return NULL;

int n = dc_platform_snprintf(str, size,
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid[0], uuid[1], uuid[2], uuid[3],
uuid[4], uuid[5],
uuid[6], uuid[7],
uuid[8], uuid[9],
uuid[10], uuid[11], uuid[12],
uuid[13], uuid[14], uuid[15]);
if (n < 0 || (size_t) n >= size)
return NULL;

return str;
}

int
dc_ble_str2uuid (const char *str, dc_ble_uuid_t uuid)
{
dc_ble_uuid_t tmp = {0};

if (str == NULL || uuid == NULL)
return 0;

unsigned int i = 0;
unsigned char c = 0;
while ((c = *str++) != '\0') {
if (c == '-') {
if (i != 8 && i != 12 && i != 16 && i != 20) {
return 0; /* Invalid character! */
}
continue;
} else if (c >= '0' && c <= '9') {
c -= '0';
} else if (c >= 'A' && c <= 'F') {
c -= 'A' - 10;
} else if (c >= 'a' && c <= 'f') {
c -= 'a' - 10;
} else {
return 0; /* Invalid character! */
}

if ((i & 1) == 0) {
c <<= 4;
}

if (i >= 2 * sizeof(tmp)) {
return 0; /* Too many characters! */
}

tmp[i / 2] |= c;
i++;
}

if (i != 2 * sizeof(tmp)) {
return 0; /* Not enough characters! */
}

memcpy (uuid, tmp, sizeof(tmp));

return 1;
}
411 changes: 322 additions & 89 deletions src/cressi_goa.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/cressi_goa.h
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ dc_status_t
cressi_goa_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);

dc_status_t
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);

#ifdef __cplusplus
}
496 changes: 380 additions & 116 deletions src/cressi_goa_parser.c

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions src/deepsix_excursion_parser.c
Original file line number Diff line number Diff line change
@@ -334,6 +334,9 @@ deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
case 2:
*((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE;
break;
case 3:
*((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
break;
default:
return DC_STATUS_DATAFORMAT;
}
@@ -550,6 +553,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
return DC_STATUS_DATAFORMAT;
}
break;
case EVENT_CHANGE_SETPOINT:
if (event_info[i].size != 4 && event_info[i].size != 2) {
ERROR(abstract->context, "Unexpected event size (%u).", event_info[i].size);
return DC_STATUS_DATAFORMAT;
}
break;
case EVENT_SAMPLES_MISSED:
if (event_info[i].size != 6) {
ERROR(abstract->context, "Unexpected event size (%u).", event_info[i].size);
@@ -670,6 +679,14 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
sample.gasmix = mix_idx;
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
break;
case EVENT_CHANGE_SETPOINT:
// Ignore the 4 byte variant because it's not
// supposed to be present in the sample data.
if (event_info[i].size == 2) {
sample.setpoint = data[offset + event_offset] / 10.0;
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
}
break;
case EVENT_SAMPLES_MISSED:
count = array_uint16_le(data + offset + event_offset);
timestamp = array_uint32_le(data + offset + event_offset + 2);
78 changes: 72 additions & 6 deletions src/descriptor.c
Original file line number Diff line number Diff line change
@@ -59,6 +59,7 @@ static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transp
static int dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_cressi (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);

// Not merged upstream yet
static int dc_filter_garmin (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
@@ -149,6 +150,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Uwatec", "Galileo Terra", DC_FAMILY_UWATEC_SMART, 0x11, DC_TRANSPORT_IRDA, dc_filter_uwatec},
{"Uwatec", "Aladin Tec", DC_FAMILY_UWATEC_SMART, 0x12, DC_TRANSPORT_IRDA, dc_filter_uwatec},
{"Uwatec", "Aladin Prime", DC_FAMILY_UWATEC_SMART, 0x12, DC_TRANSPORT_IRDA, dc_filter_uwatec},
{"Uwatec", "Aladin One", DC_FAMILY_UWATEC_SMART, 0x12, DC_TRANSPORT_IRDA, dc_filter_uwatec},
{"Uwatec", "Aladin Tec 2G", DC_FAMILY_UWATEC_SMART, 0x13, DC_TRANSPORT_IRDA, dc_filter_uwatec},
{"Uwatec", "Aladin 2G", DC_FAMILY_UWATEC_SMART, 0x13, DC_TRANSPORT_IRDA, dc_filter_uwatec},
{"Subgear", "XP-10", DC_FAMILY_UWATEC_SMART, 0x13, DC_TRANSPORT_IRDA, dc_filter_uwatec},
@@ -273,14 +275,16 @@ static const dc_descriptor_t g_descriptors[] = {
{"Sherwood", "Amphos Air 2.0", DC_FAMILY_OCEANIC_ATOM2, 0x4658, DC_TRANSPORT_SERIAL, NULL},
{"Sherwood", "Beacon", DC_FAMILY_OCEANIC_ATOM2, 0x4742, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
{"Aqualung", "i470TC", DC_FAMILY_OCEANIC_ATOM2, 0x4743, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
{"Aqualung", "i200Cv2", DC_FAMILY_OCEANIC_ATOM2, 0x4749, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
{"Aqualung", "i100", DC_FAMILY_OCEANIC_ATOM2, 0x4745, DC_TRANSPORT_SERIAL, NULL},
{"Aqualung", "i200C", DC_FAMILY_OCEANIC_ATOM2, 0x4749, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
{"Oceanic", "Geo Air", DC_FAMILY_OCEANIC_ATOM2, 0x474B, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_oceanic},
/* Pelagic I330R */
// The pairing sequence for these was intentionally broken by Pelagic Pressure Systems
// so they won't work without a custom pairing dialogue provided by the app
// Pelagic should fix this on their side if they want their customers to be able to use Subsurface
//{"Apeks", "DSX", DC_FAMILY_PELAGIC_I330R, 0x4741, DC_TRANSPORT_BLE, dc_filter_oceanic},
//{"Aqualung", "i330R", DC_FAMILY_PELAGIC_I330R, 0x4744, DC_TRANSPORT_BLE, dc_filter_oceanic},
//{"Aqualung", "i330R Console", DC_FAMILY_PELAGIC_I330R, 0x474D, DC_TRANSPORT_BLE, dc_filter_oceanic},
/* Mares Nemo */
{"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
{"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0, DC_TRANSPORT_SERIAL, NULL},
@@ -344,11 +348,13 @@ static const dc_descriptor_t g_descriptors[] = {
{"Cressi", "Newton", DC_FAMILY_CRESSI_LEONARDO, 5, DC_TRANSPORT_SERIAL, NULL},
{"Cressi", "Drake", DC_FAMILY_CRESSI_LEONARDO, 6, DC_TRANSPORT_SERIAL, NULL},
/* Cressi Goa */
{"Cressi", "Cartesio", DC_FAMILY_CRESSI_GOA, 1, DC_TRANSPORT_SERIAL, NULL},
{"Cressi", "Goa", DC_FAMILY_CRESSI_GOA, 2, DC_TRANSPORT_SERIAL, NULL},
{"Cressi", "Donatello", DC_FAMILY_CRESSI_GOA, 4, DC_TRANSPORT_SERIAL, NULL},
{"Cressi", "Michelangelo", DC_FAMILY_CRESSI_GOA, 5, DC_TRANSPORT_SERIAL, NULL},
{"Cressi", "Neon", DC_FAMILY_CRESSI_GOA, 9, DC_TRANSPORT_SERIAL, NULL},
{"Cressi", "Cartesio", DC_FAMILY_CRESSI_GOA, 1, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
{"Cressi", "Goa", DC_FAMILY_CRESSI_GOA, 2, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
{"Cressi", "Leonardo 2.0", DC_FAMILY_CRESSI_GOA, 3, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
{"Cressi", "Donatello", DC_FAMILY_CRESSI_GOA, 4, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
{"Cressi", "Michelangelo", DC_FAMILY_CRESSI_GOA, 5, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
{"Cressi", "Neon", DC_FAMILY_CRESSI_GOA, 9, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
{"Cressi", "Nepto", DC_FAMILY_CRESSI_GOA, 10, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_cressi},
/* Zeagle N2iTiON3 */
{"Zeagle", "N2iTiON3", DC_FAMILY_ZEAGLE_N2ITION3, 0, DC_TRANSPORT_SERIAL, NULL},
{"Apeks", "Quantum X", DC_FAMILY_ZEAGLE_N2ITION3, 0, DC_TRANSPORT_SERIAL, NULL},
@@ -559,6 +565,31 @@ dc_match_number_with_prefix (const void *key, const void *value)
return 1;
}

static int
dc_match_hex_with_prefix (const void *key, const void *value)
{
const char *str = (const char *) key;
const char *prefix = *(const char * const *) value;

size_t n = strlen (prefix);

if (strncmp (str, prefix, n) != 0) {
return 0;
}

while (str[n] != 0) {
const char c = str[n];
if ((c < '0' || c > '9') &&
(c < 'A' || c > 'F') &&
(c < 'a' || c > 'f')) {
return 0;
}
n++;
}

return 1;
}

static int
dc_match_oceanic (const void *key, const void *value)
{
@@ -575,6 +606,20 @@ dc_match_oceanic (const void *key, const void *value)
return dc_match_number_with_prefix (key, &p);
}

static int
dc_match_cressi (const void *key, const void *value)
{
unsigned int model = *(const unsigned int *) value;

char prefix[16] = {0};

dc_platform_snprintf(prefix, sizeof(prefix), "%u_", model);

const char *p = prefix;

return dc_match_hex_with_prefix (key, &p);
}

static int
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match)
{
@@ -777,6 +822,7 @@ dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const
0x4744, // Aqualung i330R
0x4749, // Aqualung i200C (newer model)
0x474B, // Oceanic Geo Air
0x474D, // Aqualung i330R Console
};

if (transport == DC_TRANSPORT_BLE) {
@@ -876,6 +922,26 @@ dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const
return 1;
}

static int
dc_filter_cressi (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const unsigned int model[] = {
1, // Cartesio
2, // Goa
3, // Leonardo 2.0
4, // Donatello
5, // Michelangelo
9, // Neon
10, // Nepto
};

if (transport == DC_TRANSPORT_BLE) {
return DC_FILTER_INTERNAL (userdata, model, 0, dc_match_cressi);
}

return 1;
}

dc_status_t
dc_descriptor_iterator (dc_iterator_t **out)
{
3 changes: 3 additions & 0 deletions src/libdivecomputer.symbols
Original file line number Diff line number Diff line change
@@ -66,6 +66,9 @@ dc_bluetooth_device_free
dc_bluetooth_iterator_new
dc_bluetooth_open

dc_ble_uuid2str
dc_ble_str2uuid

dc_irda_device_get_address
dc_irda_device_get_name
dc_irda_device_free
1 change: 1 addition & 0 deletions src/oceanic_atom2.c
Original file line number Diff line number Diff line change
@@ -513,6 +513,7 @@ static const oceanic_common_version_t versions[] = {
{"AERISAIR \0\0 1024", 0, A300AI, &oceanic_vt4_layout},
{"SWVISION \0\0 1024", 0, VISION, &oceanic_vt4_layout},
{"XPSUBAIR \0\0 1024", 0, XPAIR, &oceanic_vt4_layout},
{"AQUAI100 \0\0 1024", 0, I100V2, &oceanic_vt4_layout},

{"HOLLDG04 \0\0 2048", 0, TX1, &hollis_tx1_layout},

47 changes: 26 additions & 21 deletions src/oceanic_atom2_parser.c
Original file line number Diff line number Diff line change
@@ -145,9 +145,9 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const uns
} else if (model == PROPLUSX) {
parser->headersize = 3 * PAGESIZE;
} else if (model == I550C || model == WISDOM4 ||
model == I200CV2) {
model == I200CV2|| model == I100V2) {
parser->headersize = 5 * PAGESIZE / 2;
} else if (model == I330R) {
} else if (model == I330R || model == I330R_C) {
parser->logbooksize = 64;
parser->headersize = parser->logbooksize + 80;
parser->footersize = 48;
@@ -199,6 +199,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim

switch (parser->model) {
case I330R:
case I330R_C:
case DSX:
datetime->year = p[7] + 2000;
datetime->month = p[6];
@@ -225,6 +226,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
case I470TC:
case I200CV2:
case GEOAIR:
case I100V2:
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);
@@ -395,7 +397,7 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
} else if (parser->model == VEO20 || parser->model == VEO30 ||
parser->model == OCS) {
mode = (data[1] & 0x60) >> 5;
} else if (parser->model == I330R) {
} else if (parser->model == I330R || parser->model == I330R_C) {
mode = data[2];
} else if (parser->model == DSX) {
mode = data[45];
@@ -456,7 +458,7 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
} else if (parser->model == WISDOM4) {
o2_offset = header + 4;
ngasmixes = 1;
} else if (parser->model == I330R) {
} else if (parser->model == I330R || parser->model == I330R_C) {
ngasmixes = 3;
o2_offset = parser->logbooksize + 16;
} else if (parser->model == DSX) {
@@ -481,7 +483,8 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
if (data[o2_offset + i * o2_step]) {
parser->oxygen[i] = data[o2_offset + i * o2_step];
// The i330R uses 20 as "Air" and 21 as 21% Nitrox
if (parser->model == I330R && parser->oxygen[i] == 20) {
if ((parser->model == I330R || parser->model == I330R_C) &&
parser->oxygen[i] == 20) {
parser->oxygen[i] = 21;
}
} else {
@@ -545,13 +548,13 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
parser->model == F11A || parser->model == F11B ||
parser->model == MUNDIAL2 || parser->model == MUNDIAL3)
*((double *) value) = array_uint16_le (data + 4) / 16.0 * FEET;
else if (parser->model == I330R || parser->model == DSX)
else if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX)
*((double *) value) = array_uint16_le (data + parser->footer + 10) / 10.0 * FEET;
else
*((double *) value) = (array_uint16_le (data + parser->footer + 4) & 0x0FFF) / 16.0 * FEET;
break;
case DC_FIELD_AVGDEPTH:
if (parser->model == I330R || parser->model == DSX) {
if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
*((double *) value) = array_uint16_le (data + parser->footer + 12) / 10.0 * FEET;
} else {
return DC_STATUS_UNSUPPORTED;
@@ -575,7 +578,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
water->type = DC_WATER_SALT;
}
water->density = 0.0;
} else if (parser->model == I330R || parser->model == DSX) {
} else if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
unsigned int settings = array_uint32_le (data + parser->logbooksize + 12);
if (settings & 0x10000) {
water->type = DC_WATER_FRESH;
@@ -693,7 +696,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
unsigned int time = 0;
unsigned int interval = 1000;
if (!is_freedive (parser->mode, parser->model)) {
if (parser->model == I330R || parser->model == DSX) {
if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
interval = data[parser->logbooksize + 36] * 1000;
} else {
unsigned int offset = 0x17;
@@ -728,7 +731,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == I750TC || parser->model == PROPLUSX ||
parser->model == I770R || parser->model == I470TC ||
parser->model == SAGE || parser->model == BEACON ||
parser->model == GEOAIR || parser->model == I330R) {
parser->model == GEOAIR || parser->model == I330R ||
parser->model == I330R_C) {
samplesize = PAGESIZE;
} else if (parser->model == DSX) {
samplesize = 32;
@@ -747,7 +751,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == I300C || parser->model == TALIS ||
parser->model == I200C || parser->model == I200CV2 ||
parser->model == GEO40 || parser->model == VEO40 ||
parser->model == I330R) {
parser->model == I330R || parser->model == I330R_C ||
parser->model == I100V2) {
have_pressure = 0;
}

@@ -902,7 +907,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == I300C || parser->model == I200C ||
parser->model == GEO40 || parser->model == VEO40 ||
parser->model == I470TC || parser->model == I200CV2 ||
parser->model == GEOAIR) {
parser->model == GEOAIR || parser->model == I100V2) {
temperature = data[offset + 3];
} else if (parser->model == OCS || parser->model == TX1) {
temperature = data[offset + 1];
@@ -916,7 +921,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == I770R|| parser->model == SAGE ||
parser->model == BEACON) {
temperature = data[offset + 11];
} else if (parser->model == I330R || parser->model == DSX) {
} else if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
temperature = array_uint16_le(data + offset + 10);
} else {
unsigned int sign;
@@ -940,7 +945,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
else
temperature += (data[offset + 7] & 0x0C) >> 2;
}
if (parser->model == I330R || parser->model == DSX) {
if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
sample.temperature = ((temperature / 10.0) - 32.0) * (5.0 / 9.0);
} else {
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
@@ -995,15 +1000,15 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == I300C || parser->model == I200C ||
parser->model == GEO40 || parser->model == VEO40 ||
parser->model == I470TC || parser->model == I200CV2 ||
parser->model == GEOAIR)
parser->model == GEOAIR || parser->model == I100V2)
depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF;
else if (parser->model == I330R || parser->model == DSX)
else if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX)
depth = array_uint16_le (data + offset + 2);
else if (parser->model == ATOM1)
depth = data[offset + 3] * 16;
else
depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF;
if (parser->model == I330R || parser->model == DSX) {
if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
sample.depth = depth / 10.0 * FEET;
} else {
sample.depth = depth / 16.0 * FEET;
@@ -1062,11 +1067,11 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == I450T || parser->model == I200C ||
parser->model == GEO40 || parser->model == VEO40 ||
parser->model == I470TC || parser->model == I200CV2 ||
parser->model == GEOAIR) {
parser->model == GEOAIR || parser->model == I100V2) {
decostop = (data[offset + 7] & 0xF0) >> 4;
decotime = array_uint16_le(data + offset + 6) & 0x0FFF;
have_deco = 1;
} else if (parser->model == I330R || parser->model == DSX) {
} else if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
decostop = data[offset + 8];
if (decostop) {
// Deco time
@@ -1080,7 +1085,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
if (have_deco) {
if (decostop) {
sample.deco.type = DC_DECO_DECOSTOP;
if (parser->model == I330R || parser->model == DSX) {
if (parser->model == I330R || parser->model == I330R_C || parser->model == DSX) {
sample.deco.depth = decostop * FEET;
} else {
sample.deco.depth = decostop * 10 * FEET;
@@ -1119,7 +1124,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
}

// PPO2
if (parser->model == I330R) {
if (parser->model == I330R || parser->model == I330R_C) {
sample.ppo2.sensor = DC_SENSOR_NONE;
sample.ppo2.value = data[offset + 9] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
2 changes: 2 additions & 0 deletions src/oceanic_common.h
Original file line number Diff line number Diff line change
@@ -122,12 +122,14 @@ extern "C" {
#define AMPHOSAIR2 0x4658
#define BEACON 0x4742
#define I470TC 0x4743
#define I100V2 0x4745
#define I200CV2 0x4749
#define GEOAIR 0x474B

// i330r
#define DSX 0x4741
#define I330R 0x4744
#define I330R_C 0x474D

#define PAGESIZE 0x10
#define FPMAXSIZE 0x200
2 changes: 1 addition & 1 deletion src/parser.c
Original file line number Diff line number Diff line change
@@ -158,7 +158,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned
rc = cressi_leonardo_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_CRESSI_GOA:
rc = cressi_goa_parser_create (&parser, context, data, size, model);
rc = cressi_goa_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_ATOMICS_COBALT:
rc = atomics_cobalt_parser_create (&parser, context, data, size);
1 change: 1 addition & 0 deletions src/shearwater_common.c
Original file line number Diff line number Diff line change
@@ -738,6 +738,7 @@ dc_status_t shearwater_common_get_model(shearwater_common_device_t *device, unsi
*model = PERDIXAI;
break;
case 0xC407:
case 0xC964:
*model = PERDIX2;
break;
case 0x0F0F: