Merge remote-tracking branch 'libdivecomputer/master' into update_libdivecomputer_202402

This commit is contained in:
Michael Keller 2024-02-02 17:40:41 +13:00
commit d37cb91734
120 changed files with 1553 additions and 1959 deletions

View File

@ -1,6 +1,6 @@
# Versioning.
m4_define([dc_version_major],[0])
m4_define([dc_version_minor],[8])
m4_define([dc_version_minor],[9])
m4_define([dc_version_micro],[0])
m4_define([dc_version_suffix],[devel-Subsurface-NG])
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))

View File

@ -331,7 +331,6 @@
<ClInclude Include="..\..\src\cressi_leonardo.h" />
<ClInclude Include="..\..\src\deepblu_cosmiq.h" />
<ClInclude Include="..\..\src\deepsix_excursion.h" />
<ClInclude Include="..\..\src\descriptor-private.h" />
<ClInclude Include="..\..\src\device-private.h" />
<ClInclude Include="..\..\src\diverite_nitekq.h" />
<ClInclude Include="..\..\src\divesoft_freedom.h" />

View File

@ -32,7 +32,6 @@ MANPAGES = \
dc_parser_get_field.3 \
dc_parser_new.3 \
dc_parser_samples_foreach.3 \
dc_parser_set_data.3 \
dc_bluetooth_open.3 \
dc_bluetooth_iterator_new.3 \
dc_bluetooth_device_get_address.3 \

View File

@ -53,7 +53,7 @@ with
Each dive invokes
.Fa callback
with the dive data, which should be parsed with
.Xr dc_parser_set_data 3 ,
.Xr dc_parser_new 3 ,
and the binary fingerprint of the dive.
The fingerprint can be used to record the newest dive and stop
processing (on subsequent invocations) when the same dive fingerprint is
@ -72,7 +72,7 @@ If
returns zero, this will not be reflected in the return value (usually
.Dv DC_STATUS_SUCCESS ) .
.Sh SEE ALSO
.Xr dc_parser_set_data 3
.Xr dc_parser_new 3
.Sh AUTHORS
The
.Lb libdivecomputer

View File

@ -37,7 +37,7 @@
Extract the date and time of a dive,
.Fa parser ,
previously initialised with
.Xr dc_parser_set_data 3 .
.Xr dc_parser_new 3 .
This returns the broken-down time-stamp of the dive in the local time of
the dive.
.Pp
@ -57,7 +57,7 @@ messages on further failure.
.Sh SEE ALSO
.Xr dc_datetime_gmtime 3 ,
.Xr dc_datetime_localtime 3 ,
.Xr dc_parser_set_data 3
.Xr dc_parser_new 3
.Sh AUTHORS
The
.Lb libdivecomputer

View File

@ -39,7 +39,7 @@
Extract a field from a dive,
.Fa parser ,
previously initialised with
.Xr dc_parser_set_data 3 .
.Xr dc_parser_new 3 .
The
.Fa value
field type depends upon the
@ -187,7 +187,7 @@ if the field was retrieved,
if the field is not supported by the device, or other error messages on
further failure.
.Sh SEE ALSO
.Xr dc_parser_set_data 3
.Xr dc_parser_new 3
.Sh AUTHORS
The
.Lb libdivecomputer

View File

@ -39,8 +39,6 @@
.Fa "dc_parser_t **parser"
.Fa "dc_context_t *context"
.Fa "dc_descriptor_t *descriptor"
.Fa "unsigned int devtime"
.Fa "dc_ticks_t systime"
.Fc
.Sh DESCRIPTION
Creates a parser for a single dive extracted from the dive computer with
@ -55,10 +53,6 @@ parameter; and
.Nm dc_parser_new2 ,
which is given device values (model, etc.) directly.
.Pp
After filling in the
.Fa parser
parameter, one usually sets parser data with
.Xr dc_parser_set_data 3 .
The pointer must later be freed with
.Xr dc_parser_destroy 3 .
.Sh RETURN VALUES

View File

@ -31,7 +31,7 @@
.Ft "typedef void"
.Fo "(*dc_sample_callback_t)"
.Fa "dc_sample_type_t type"
.Fa "dc_sample_value_t value"
.Fa "const dc_sample_value_t *value"
.Fa "void *userdata"
.Fc
.Ft dc_status_t
@ -42,7 +42,7 @@
.Fc
.Sh DESCRIPTION
Extract the samples taken during a dive as previously initialised with
.Xr dc_parser_set_data 3 .
.Xr dc_parser_new 3 .
Each sample is passed to
.Fa callback
with the
@ -63,7 +63,7 @@ closed.
The following sample types may be raised:
.Bl -tag -width Ds
.It Dv DC_SAMPLE_TIME
The time of the sample taken in seconds after the dive began.
The time of the sample taken in milliseconds after the dive began.
Set in the
.Fa time
field.
@ -184,7 +184,7 @@ Returns
.Dv DC_STATUS_OK
on success and another code on failure.
.Sh SEE ALSO
.Xr dc_parser_set_data 3
.Xr dc_parser_new 3
.Sh AUTHORS
The
.Lb libdivecomputer

View File

@ -1,65 +0,0 @@
.\"
.\" libdivecomputer
.\"
.\" Copyright (C) 2017 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
.\" 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
.\"
.Dd January 5, 2017
.Dt DC_PARSER_SET_DATA 3
.Os
.Sh NAME
.Nm dc_parser_set_data
.Nd assigns parse data to a dive parser
.Sh LIBRARY
.Lb libdivecomputer
.Sh SYNOPSIS
.In libdivecomputer/parser.h
.Ft dc_status_t
.Fo dc_parser_set_data
.Fa "dc_parser_t *parser"
.Fa "const unsigned char *data"
.Fa "unsigned int size"
.Fc
.Sh DESCRIPTION
Assigns the binary sequence
.Fa data
of length
.Fa size
bytes to
.Fa parser ,
which was created with
.Xr dc_parser_new 3 .
How the data is parsed depends upon the values provided to
.Xr dc_parser_new 3 .
The data usually comes from the callback assigned to
.Xr dc_device_foreach 3 .
.Sh RETURN VALUES
Returns
.Dv DC_STATUS_OK
on success and another code on failure.
.Sh SEE ALSO
.Xr dc_device_foreach 3 ,
.Xr dc_parser_new 3
.Sh AUTHORS
The
.Lb libdivecomputer
library was written by
.An Jef Driesen ,
.Mt jef@libdivecomputer.org .
The manpages were written by
.An Kristaps Dzonsons ,
.Mt kristaps@bsd.lv .

View File

@ -82,9 +82,7 @@ Iterate over all dives with
.Xr dc_device_foreach 3 .
.It
For each iterated dive, create a new parser with
.Xr dc_parser_new 3
and set the parsed data with
.Xr dc_parser_set_data 3 .
.Xr dc_parser_new 3 .
.It
Get attributes of the parsed dive with
.Xr dc_parser_get_field 3 .

View File

@ -80,20 +80,12 @@ dive_cb (const unsigned char *data, unsigned int size, const unsigned char *fing
// Create the parser.
message ("Creating the parser.\n");
rc = dc_parser_new (&parser, divedata->device);
rc = dc_parser_new (&parser, divedata->device, data, size);
if (rc != DC_STATUS_SUCCESS) {
ERROR ("Error creating the parser.");
goto cleanup;
}
// Register the data.
message ("Registering the data.\n");
rc = dc_parser_set_data (parser, data, size);
if (rc != DC_STATUS_SUCCESS) {
ERROR ("Error registering the data.");
goto cleanup;
}
// Parse the dive data.
message ("Parsing the dive data.\n");
rc = dctool_output_write (divedata->output, parser, data, size, fingerprint, fsize);

View File

@ -54,17 +54,17 @@ parse (dc_buffer_t *buffer, dc_context_t *context, dc_descriptor_t *descriptor,
// Create the parser.
message ("Creating the parser.\n");
rc = dc_parser_new2 (&parser, context, descriptor, devtime, systime);
rc = dc_parser_new2 (&parser, context, descriptor, data, size);
if (rc != DC_STATUS_SUCCESS) {
ERROR ("Error creating the parser.");
goto cleanup;
}
// Register the data.
message ("Registering the data.\n");
rc = dc_parser_set_data (parser, data, size);
if (rc != DC_STATUS_SUCCESS) {
ERROR ("Error registering the data.");
// Set the clock.
message ("Setting the clock.\n");
rc = dc_parser_set_clock (parser, devtime, systime);
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
ERROR ("Error setting the clock.");
goto cleanup;
}

View File

@ -90,7 +90,7 @@ convert_volume (double value, dctool_units_t units)
}
static void
sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
sample_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata)
{
static const char *events[] = {
"none", "deco", "rbt", "ascent", "ceiling", "workload", "transmitter",
@ -104,64 +104,80 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
sample_data_t *sampledata = (sample_data_t *) userdata;
unsigned int seconds = 0, milliseconds = 0;
switch (type) {
case DC_SAMPLE_TIME:
seconds = value->time / 1000;
milliseconds = value->time % 1000;
if (sampledata->nsamples++)
fprintf (sampledata->ostream, "</sample>\n");
fprintf (sampledata->ostream, "<sample>\n");
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", value.time / 60, value.time % 60);
if (milliseconds) {
fprintf (sampledata->ostream, " <time>%02u:%02u.%03u</time>\n", seconds / 60, seconds % 60, milliseconds);
} else {
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", seconds / 60, seconds % 60);
}
break;
case DC_SAMPLE_DEPTH:
fprintf (sampledata->ostream, " <depth>%.2f</depth>\n",
convert_depth(value.depth, sampledata->units));
convert_depth(value->depth, sampledata->units));
break;
case DC_SAMPLE_PRESSURE:
fprintf (sampledata->ostream, " <pressure tank=\"%u\">%.2f</pressure>\n",
value.pressure.tank,
convert_pressure(value.pressure.value, sampledata->units));
value->pressure.tank,
convert_pressure(value->pressure.value, sampledata->units));
break;
case DC_SAMPLE_TEMPERATURE:
fprintf (sampledata->ostream, " <temperature>%.2f</temperature>\n",
convert_temperature(value.temperature, sampledata->units));
convert_temperature(value->temperature, sampledata->units));
break;
case DC_SAMPLE_EVENT:
if (value.event.type != SAMPLE_EVENT_GASCHANGE && value.event.type != SAMPLE_EVENT_GASCHANGE2) {
if (value->event.type != SAMPLE_EVENT_GASCHANGE && value->event.type != SAMPLE_EVENT_GASCHANGE2) {
fprintf (sampledata->ostream, " <event type=\"%u\" time=\"%u\" flags=\"%u\" value=\"%u\">%s</event>\n",
value.event.type, value.event.time, value.event.flags, value.event.value, events[value.event.type]);
value->event.type, value->event.time, value->event.flags, value->event.value, events[value->event.type]);
}
break;
case DC_SAMPLE_RBT:
fprintf (sampledata->ostream, " <rbt>%u</rbt>\n", value.rbt);
fprintf (sampledata->ostream, " <rbt>%u</rbt>\n", value->rbt);
break;
case DC_SAMPLE_HEARTBEAT:
fprintf (sampledata->ostream, " <heartbeat>%u</heartbeat>\n", value.heartbeat);
fprintf (sampledata->ostream, " <heartbeat>%u</heartbeat>\n", value->heartbeat);
break;
case DC_SAMPLE_BEARING:
fprintf (sampledata->ostream, " <bearing>%u</bearing>\n", value.bearing);
fprintf (sampledata->ostream, " <bearing>%u</bearing>\n", value->bearing);
break;
case DC_SAMPLE_VENDOR:
fprintf (sampledata->ostream, " <vendor type=\"%u\" size=\"%u\">", value.vendor.type, value.vendor.size);
for (unsigned int i = 0; i < value.vendor.size; ++i)
fprintf (sampledata->ostream, "%02X", ((const unsigned char *) value.vendor.data)[i]);
fprintf (sampledata->ostream, " <vendor type=\"%u\" size=\"%u\">", value->vendor.type, value->vendor.size);
for (unsigned int i = 0; i < value->vendor.size; ++i)
fprintf (sampledata->ostream, "%02X", ((const unsigned char *) value->vendor.data)[i]);
fprintf (sampledata->ostream, "</vendor>\n");
break;
case DC_SAMPLE_SETPOINT:
fprintf (sampledata->ostream, " <setpoint>%.2f</setpoint>\n", value.setpoint);
fprintf (sampledata->ostream, " <setpoint>%.2f</setpoint>\n", value->setpoint);
break;
case DC_SAMPLE_PPO2:
fprintf (sampledata->ostream, " <ppo2>%.2f</ppo2>\n", value.ppo2);
if (value->ppo2.sensor != DC_SENSOR_NONE) {
fprintf (sampledata->ostream, " <ppo2 sensor=\"%u\">%.2f</ppo2>\n", value->ppo2.sensor, value->ppo2.value);
} else {
fprintf (sampledata->ostream, " <ppo2>%.2f</ppo2>\n", value->ppo2.value);
}
break;
case DC_SAMPLE_CNS:
fprintf (sampledata->ostream, " <cns>%.1f</cns>\n", value.cns * 100.0);
fprintf (sampledata->ostream, " <cns>%.1f</cns>\n", value->cns * 100.0);
break;
case DC_SAMPLE_DECO:
fprintf (sampledata->ostream, " <deco time=\"%u\" depth=\"%.2f\">%s</deco>\n",
value.deco.time,
convert_depth(value.deco.depth, sampledata->units),
decostop[value.deco.type]);
value->deco.time,
convert_depth(value->deco.depth, sampledata->units),
decostop[value->deco.type]);
if (value->deco.tts) {
fprintf (sampledata->ostream, " <tts>%u</tts>\n",
value->deco.tts);
}
break;
case DC_SAMPLE_GASMIX:
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value.gasmix);
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value->gasmix);
break;
default:
break;
@ -322,11 +338,19 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
"<gasmix>\n"
" <he>%.1f</he>\n"
" <o2>%.1f</o2>\n"
" <n2>%.1f</n2>\n"
"</gasmix>\n",
" <n2>%.1f</n2>\n",
gasmix.helium * 100.0,
gasmix.oxygen * 100.0,
gasmix.nitrogen * 100.0);
if (gasmix.usage) {
const char *usage[] = {"none", "oxygen", "diluent", "sidemount"};
fprintf (output->ostream,
" <usage>%s</usage>\n",
usage[gasmix.usage]);
}
fprintf (output->ostream,
"</gasmix>\n");
}
// Parse the tanks.
@ -354,6 +378,12 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
" <gasmix>%u</gasmix>\n",
tank.gasmix);
}
if (tank.usage) {
const char *usage[] = {"none", "oxygen", "diluent", "sidemount"};
fprintf (output->ostream,
" <usage>%s</usage>\n",
usage[tank.usage]);
}
if (tank.type != DC_TANKVOLUME_NONE) {
fprintf (output->ostream,
" <type>%s</type>\n"
@ -420,8 +450,14 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
}
if (status != DC_STATUS_UNSUPPORTED) {
fprintf (output->ostream, "<salinity type=\"%u\">%.1f</salinity>\n",
salinity.type, salinity.density);
const char *names[] = {"fresh", "salt"};
if (salinity.density) {
fprintf (output->ostream, "<salinity density=\"%.1f\">%s</salinity>\n",
salinity.density, names[salinity.type]);
} else {
fprintf (output->ostream, "<salinity>%s</salinity>\n",
names[salinity.type]);
}
}
// Parse the atmospheric pressure.

View File

@ -36,9 +36,6 @@ atomics_cobalt_device_version (dc_device_t *device, unsigned char data[], unsign
dc_status_t
atomics_cobalt_device_set_simulation (dc_device_t *device, unsigned int simulation);
dc_status_t
atomics_cobalt_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -29,29 +29,96 @@
extern "C" {
#endif /* __cplusplus */
/**
* Opaque object representing a supported dive computer.
*/
typedef struct dc_descriptor_t dc_descriptor_t;
/**
* Create an iterator to enumerate the supported dive computers.
*
* @param[out] iterator A location to store the iterator.
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
* on failure.
*/
dc_status_t
dc_descriptor_iterator (dc_iterator_t **iterator);
/**
* Free the device descriptor.
*
* @param[in] descriptor A valid device descriptor.
*/
void
dc_descriptor_free (dc_descriptor_t *descriptor);
/**
* Get the vendor name of the dive computer.
*
* @param[in] descriptor A valid device descriptor.
* @returns The vendor name of the dive computer on success, or NULL on failure.
*/
const char *
dc_descriptor_get_vendor (dc_descriptor_t *descriptor);
/**
* Get the product name of the dive computer.
*
* @param[in] descriptor A valid device descriptor.
* @returns The product name of the dive computer on success, or NULL on
* failure.
*/
const char *
dc_descriptor_get_product (dc_descriptor_t *descriptor);
/**
* Get the family type of the dive computer.
*
* @param[in] descriptor A valid device descriptor.
* @returns The family type of the dive computer on success, or DC_FAMILY_NULL
* on failure.
*/
dc_family_t
dc_descriptor_get_type (dc_descriptor_t *descriptor);
/**
* Get the model number of the dive computer.
*
* @param[in] descriptor A valid device descriptor.
* @returns The model number of the dive computer on success, or zero on
* failure.
*/
unsigned int
dc_descriptor_get_model (dc_descriptor_t *descriptor);
/**
* Get all transports supported by the dive computer.
*
* @param[in] descriptor A valid device descriptor.
* @returns A bitmask with all the transports supported by the dive computer on
* success, or DC_TRANSPORT_NONE on failure.
*/
unsigned int
dc_descriptor_get_transports (dc_descriptor_t *descriptor);
/**
* Check if a low-level I/O device matches a supported dive computer.
*
* @param[in] descriptor A valid device descriptor.
* @param[in] transport The transport type of the I/O device.
* @param[in] userdata A pointer to a transport specific data structure:
* - DC_TRANSPORT_SERIAL: Name of the device node (string)
* - DC_TRANSPORT_USB: USB VID/PID (#dc_usb_desc_t)
* - DC_TRANSPORT_USBHID: USB VID/PID (#dc_usbhid_desc_t)
* - DC_TRANSPORT_IRDA: IrDA device name (string)
* - DC_TRANSPORT_BLUETOOTH: Bluetooth device name (string)
* - DC_TRANSPORT_BLE: Bluetooth device name (string)
* @returns Non-zero if the device matches a supported dive computer, or zero if
* there is no match.
*/
int
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -173,12 +173,21 @@ typedef struct dc_salinity_t {
double density;
} dc_salinity_t;
typedef enum dc_usage_t {
DC_USAGE_NONE,
DC_USAGE_OXYGEN,
DC_USAGE_DILUENT,
DC_USAGE_SIDEMOUNT,
} dc_usage_t;
typedef struct dc_gasmix_t {
double helium;
double oxygen;
double nitrogen;
dc_usage_t usage;
} dc_gasmix_t;
#define DC_SENSOR_NONE 0xFFFFFFFF
#define DC_GASMIX_UNKNOWN 0xFFFFFFFF
typedef unsigned int dc_tankinfo_t;
@ -222,6 +231,7 @@ typedef struct dc_tank_t {
double workpressure; /* Work pressure (bar) */
double beginpressure; /* Begin pressure (bar) */
double endpressure; /* End pressure (bar) */
dc_usage_t usage;
} dc_tank_t;
typedef enum dc_decomodel_type_t {
@ -267,7 +277,7 @@ typedef struct dc_field_string_t {
} dc_field_string_t;
typedef union dc_sample_value_t {
unsigned int time;
unsigned int time; /* Milliseconds */
double depth;
struct {
unsigned int tank;
@ -290,25 +300,29 @@ typedef union dc_sample_value_t {
const void *data;
} vendor;
double setpoint;
double ppo2;
struct {
unsigned int sensor;
double value;
} ppo2;
double cns;
struct {
unsigned int type;
unsigned int time;
double depth;
unsigned int tts;
} deco;
unsigned int gasmix; /* Gas mix index */
} dc_sample_value_t;
typedef struct dc_parser_t dc_parser_t;
typedef void (*dc_sample_callback_t) (dc_sample_type_t type, dc_sample_value_t value, void *userdata);
typedef void (*dc_sample_callback_t) (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata);
dc_status_t
dc_parser_new (dc_parser_t **parser, dc_device_t *device);
dc_parser_new (dc_parser_t **parser, dc_device_t *device, const unsigned char data[], size_t size);
dc_status_t
dc_parser_new2 (dc_parser_t **parser, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime);
dc_parser_new2 (dc_parser_t **parser, dc_context_t *context, dc_descriptor_t *descriptor, const unsigned char data[], size_t size);
dc_family_t
dc_parser_get_type (dc_parser_t *parser);
@ -322,9 +336,6 @@ dc_parser_set_atmospheric (dc_parser_t *parser, double atmospheric);
dc_status_t
dc_parser_set_density (dc_parser_t *parser, double density);
dc_status_t
dc_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size);
dc_status_t
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);

View File

@ -35,9 +35,6 @@ extern "C" {
dc_status_t
reefnet_sensus_device_get_handshake (dc_device_t *device, unsigned char data[], unsigned int size);
dc_status_t
reefnet_sensus_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -38,9 +38,6 @@ reefnet_sensuspro_device_get_handshake (dc_device_t *device, unsigned char data[
dc_status_t
reefnet_sensuspro_device_write_interval (dc_device_t *device, unsigned char interval);
dc_status_t
reefnet_sensuspro_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -56,9 +56,6 @@ reefnet_sensusultra_device_write_parameter (dc_device_t *device, reefnet_sensusu
dc_status_t
reefnet_sensusultra_device_sense (dc_device_t *device, unsigned char data[], unsigned int size);
dc_status_t
reefnet_sensusultra_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -86,6 +86,14 @@ typedef enum dc_usb_recipient_t {
DC_USB_RECIPIENT_OTHER = 0x03,
} dc_usb_recipient_t;
/**
* USB device descriptor.
*/
typedef struct dc_usb_desc_t {
unsigned short vid;
unsigned short pid;
} dc_usb_desc_t;
/**
* Opaque object representing a USB device.
*/

View File

@ -32,6 +32,14 @@
extern "C" {
#endif /* __cplusplus */
/**
* USB HID device descriptor.
*/
typedef struct dc_usbhid_desc_t {
unsigned short vid;
unsigned short pid;
} dc_usbhid_desc_t;
/**
* Opaque object representing a USB HID device.
*/

View File

@ -16,7 +16,7 @@ endif
libdivecomputer_la_SOURCES = \
version.c \
descriptor-private.h descriptor.c \
descriptor.c \
iostream-private.h iostream.c \
iterator-private.h iterator.c \
common-private.h common.c \

View File

@ -404,3 +404,14 @@ signextend (unsigned int value, unsigned int nbits)
else
return value & mask;
}
unsigned int
popcount (unsigned int value)
{
unsigned int count = 0;
while (value) {
value &= value - 1;
count++;
}
return count;
}

View File

@ -126,6 +126,9 @@ dec2bcd (unsigned char value);
unsigned int
signextend (unsigned int value, unsigned int nbits);
unsigned int
popcount (unsigned int value);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -41,6 +41,8 @@
#define FP_OFFSET 20
#define SZ_HEADER 228
#define SZ_MEMORY1 (29 * 64 * 1024) // Cobalt 1
#define SZ_MEMORY2 (41 * 64 * 1024) // Cobalt 2
#define SZ_VERSION 14
@ -347,6 +349,12 @@ atomics_cobalt_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
return DC_STATUS_SUCCESS;
}
if (size < SZ_HEADER) {
ERROR (abstract->context, "Dive header is too small (%u).", size);
dc_buffer_free (buffer);
return DC_STATUS_DATAFORMAT;
}
if (memcmp (data + FP_OFFSET, device->fingerprint, sizeof (device->fingerprint)) == 0) {
dc_buffer_free (buffer);
return DC_STATUS_SUCCESS;

View File

@ -36,7 +36,7 @@ dc_status_t
atomics_cobalt_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
atomics_cobalt_parser_create (dc_parser_t **parser, dc_context_t *context);
atomics_cobalt_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -49,7 +49,6 @@ struct atomics_cobalt_parser_t {
double hydrostatic;
};
static dc_status_t atomics_cobalt_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density);
static dc_status_t atomics_cobalt_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
@ -58,7 +57,6 @@ static dc_status_t atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract,
static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
sizeof(atomics_cobalt_parser_t),
DC_FAMILY_ATOMICS_COBALT,
atomics_cobalt_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
atomics_cobalt_parser_set_density, /* set_density */
@ -70,7 +68,7 @@ static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
dc_status_t
atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
atomics_cobalt_parser_t *parser = NULL;
@ -78,7 +76,7 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (atomics_cobalt_parser_t *) dc_parser_allocate (context, &atomics_cobalt_parser_vtable);
parser = (atomics_cobalt_parser_t *) dc_parser_allocate (context, &atomics_cobalt_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -93,27 +91,6 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
}
static dc_status_t
atomics_cobalt_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
dc_status_t
atomics_cobalt_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
{
atomics_cobalt_parser_t *parser = (atomics_cobalt_parser_t*) abstract;
if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
parser->hydrostatic = hydrostatic;
return DC_STATUS_SUCCESS;
}
static dc_status_t
atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density)
{
@ -182,6 +159,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
*((unsigned int *) value) = p[0x2a];
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = p[SZ_HEADER + SZ_GASMIX * flags + 5] / 100.0;
gasmix->oxygen = p[SZ_HEADER + SZ_GASMIX * flags + 4] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -213,6 +191,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
tank->gasmix = flags;
tank->beginpressure = array_uint16_le(p + 6) * PSI / BAR;
tank->endpressure = array_uint16_le(p + 14) * PSI / BAR;
tank->usage = DC_USAGE_NONE;
break;
case DC_FIELD_DIVEMODE:
switch(p[0x24]) {
@ -310,19 +289,19 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/1000 bar).
unsigned int depth = array_uint16_le (data + offset + 0);
sample.depth = (signed int)(depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Pressure (1 psi).
unsigned int pressure = array_uint16_le (data + offset + 2);
sample.pressure.tank = tank;
sample.pressure.value = pressure * PSI / BAR;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
// Current gas mix
unsigned int gasmix = data[offset + 4];
@ -338,14 +317,14 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
// Temperature (1 °F).
unsigned int temperature = data[offset + 8];
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// violation status
sample.event.type = 0;
@ -355,15 +334,15 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
unsigned int violation = data[offset + 11];
if (violation & 0x01) {
sample.event.type = SAMPLE_EVENT_ASCENT;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
if (violation & 0x04) {
sample.event.type = SAMPLE_EVENT_CEILING;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
if (violation & 0x08) {
sample.event.type = SAMPLE_EVENT_PO2;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
// NDL & deco
@ -378,7 +357,8 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
sample.deco.type = DC_DECO_NDL;
sample.deco.time = ndl;
sample.deco.depth = 0.0;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
offset += SZ_SEGMENT;
}

View File

@ -51,7 +51,6 @@
#include "context-private.h"
#include "iostream-private.h"
#include "iterator-private.h"
#include "descriptor-private.h"
#include "platform.h"
#ifdef _WIN32
@ -455,7 +454,7 @@ dc_bluetooth_iterator_next (dc_iterator_t *abstract, void *out)
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s",
address, name ? name : "");
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name, NULL)) {
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name)) {
continue;
}

View File

@ -31,6 +31,8 @@
#define ISINSTANCE(device) dc_device_isinstance((device), &citizen_aqualand_device_vtable)
#define SZ_HEADER 32
typedef struct citizen_aqualand_device_t {
dc_device_t base;
dc_iostream_t *iostream;
@ -200,6 +202,12 @@ citizen_aqualand_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
unsigned char *data = dc_buffer_get_data (buffer);
unsigned int size = dc_buffer_get_size (buffer);
if (size < SZ_HEADER) {
ERROR (abstract->context, "Dive header is too small (%u).", size);
dc_buffer_free (buffer);
return DC_STATUS_DATAFORMAT;
}
if (callback && memcmp (data + 0x05, device->fingerprint, sizeof (device->fingerprint)) != 0) {
callback (data, size, data + 0x05, sizeof (device->fingerprint), userdata);
}

View File

@ -35,7 +35,7 @@ dc_status_t
citizen_aqualand_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
citizen_aqualand_parser_create (dc_parser_t **parser, dc_context_t *context);
citizen_aqualand_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -36,7 +36,6 @@ typedef struct citizen_aqualand_parser_t {
dc_parser_t base;
} citizen_aqualand_parser_t;
static dc_status_t citizen_aqualand_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t citizen_aqualand_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -44,7 +43,6 @@ static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstrac
static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
sizeof(citizen_aqualand_parser_t),
DC_FAMILY_CITIZEN_AQUALAND,
citizen_aqualand_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -56,7 +54,7 @@ static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
dc_status_t
citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
citizen_aqualand_parser_t *parser = NULL;
@ -64,7 +62,7 @@ citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (citizen_aqualand_parser_t *) dc_parser_allocate (context, &citizen_aqualand_parser_vtable);
parser = (citizen_aqualand_parser_t *) dc_parser_allocate (context, &citizen_aqualand_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -76,13 +74,6 @@ citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
}
static dc_status_t
citizen_aqualand_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -241,15 +232,15 @@ citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
// Time
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth
if (metric)
sample.depth = depth / 10.0;
else
sample.depth = depth * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature
if (time % 300 == 0) {
@ -260,7 +251,7 @@ citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.temperature = temperature / 10.0;
else
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
}
}

View File

@ -35,7 +35,7 @@ dc_status_t
cochran_commander_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
cochran_commander_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
cochran_commander_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -99,7 +99,6 @@ typedef struct cochran_commander_parser_t {
unsigned int nevents;
} cochran_commander_parser_t ;
static dc_status_t cochran_commander_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size);
static dc_status_t cochran_commander_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
static dc_status_t cochran_commander_parser_get_field (dc_parser_t *parser, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
@ -107,7 +106,6 @@ static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser
static const dc_parser_vtable_t cochran_commander_parser_vtable = {
sizeof(cochran_commander_parser_t),
DC_FAMILY_COCHRAN_COMMANDER,
cochran_commander_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -315,7 +313,7 @@ cochran_commander_handle_event (cochran_commander_parser_t *parser, unsigned cha
sample.event.time = 0;
sample.event.value = 0;
sample.event.flags = event->flag;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
}
@ -352,7 +350,7 @@ cochran_commander_backparse(cochran_commander_parser_t *parser, const unsigned c
dc_status_t
cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
cochran_commander_parser_t *parser = NULL;
dc_status_t status = DC_STATUS_SUCCESS;
@ -361,7 +359,7 @@ cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, unsig
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (cochran_commander_parser_t *) dc_parser_allocate (context, &cochran_commander_parser_vtable);
parser = (cochran_commander_parser_t *) dc_parser_allocate (context, &cochran_commander_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -407,13 +405,6 @@ error_free:
}
static dc_status_t
cochran_commander_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
cochran_commander_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -514,6 +505,7 @@ cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
// Gas percentages are decimal and encoded as
// highbyte = integer portion
// lowbyte = decimal portion, divide by 256 to get decimal value
gasmix->usage = DC_USAGE_NONE;
gasmix->oxygen = array_uint16_le (data + layout->oxygen + 2 * flags) / 256.0 / 100;
if (layout->helium == UNSUPPORTED) {
gasmix->helium = 0;
@ -578,26 +570,26 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
unsigned int temp = samples[0]; // Half degrees F
unsigned int depth = samples[1]; // Half feet
last_sample_time = sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
last_sample_time = sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
sample.depth = (depth / 2.0) * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
sample.gasmix = 0;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
while (offset < size) {
const unsigned char *s = samples + offset;
sample.time = time;
sample.time = time * 1000;
if (last_sample_time != sample.time) {
// We haven't issued this time yet.
last_sample_time = sample.time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
}
if (*s & 0x80) {
@ -615,7 +607,8 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
sample.deco.type = DC_DECO_DECOSTOP;
sample.deco.time = 60; // We don't know the duration
sample.deco.depth = deco_ceiling * FEET;
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
break;
case 0xAD: // Increment ceiling (shallower)
deco_ceiling -= 10; // feet
@ -623,7 +616,8 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
sample.deco.type = DC_DECO_DECOSTOP;
sample.deco.depth = deco_ceiling * FEET;
sample.deco.time = 60; // We don't know the duration
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
break;
default:
cochran_commander_handle_event(parser, s[0], callback, userdata);
@ -636,7 +630,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
else
temp += (*s & 0x0f);
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
offset++;
@ -650,7 +644,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
depth += s[0] & 0x3f;
sample.depth = (depth / 2.0) * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset++;
time += sample_interval;
@ -714,27 +708,27 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
start_depth = array_uint16_le (data + layout->start_depth) / 256.0;
}
last_sample_time = sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
last_sample_time = sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
sample.depth = start_depth * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
sample.temperature = (data[layout->start_temp] - 32.0) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
sample.gasmix = 0;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
unsigned int last_gasmix = sample.gasmix;
while (offset < size) {
const unsigned char *s = samples + offset;
sample.time = time;
sample.time = time * 1000;
if (last_sample_time != sample.time) {
// We haven't issued this time yet.
last_sample_time = sample.time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
}
// If corrupt_dive end before offset
@ -774,7 +768,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
sample.deco.type = DC_DECO_DECOSTOP;
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
sample.deco.depth = deco_ceiling * FEET;
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
break;
case 0xAD: // Increment ceiling (shallower)
deco_ceiling -= 10; // feet
@ -782,7 +777,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
sample.deco.type = DC_DECO_DECOSTOP;
sample.deco.depth = deco_ceiling * FEET;
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
break;
case 0xC0: // Switched to FO2 21% mode (surface)
// Event seen upon surfacing
@ -791,14 +787,14 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
case 0xEF: // Switched to gas blend 2
if (last_gasmix != 1) {
sample.gasmix = 1;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
last_gasmix = sample.gasmix;
}
break;
case 0xF3: // Switched to gas blend 1
if (last_gasmix != 0) {
sample.gasmix = 0;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
last_gasmix = sample.gasmix;
}
break;
@ -818,7 +814,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
depth += (s[0] & 0x3f);
sample.depth = (start_depth + depth / 4.0) * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Ascent rate is logged in the 0th sample, temp in the 1st, repeat.
if (time % 2 == 0) {
@ -834,7 +830,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
double temperature = s[1] / 2.0 + 20.0;
sample.temperature = (temperature - 32.0) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
// Cochran EMC models store NDL and deco stop time
@ -855,7 +851,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
sample.deco.type = DC_DECO_NDL;
sample.deco.time = deco_time * 60;
sample.deco.depth = 0;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
}
break;
case 23:
@ -865,7 +862,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
sample.deco.type = DC_DECO_DECOSTOP;
sample.deco.depth = deco_ceiling * FEET;
sample.deco.time = deco_time * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
}
break;
}

View File

@ -38,6 +38,8 @@
#define SZ_PACKET 0x80
#define SZ_PAGE (SZ_PACKET / 4)
#define SZ_HEADER 32
#define IQ700 0x05
#define EDY 0x08
@ -522,6 +524,13 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
return rc;
}
if (length < SZ_HEADER) {
ERROR (abstract->context, "Dive header is too small (%u).", length);
dc_rbstream_free (rbstream);
free (buffer);
return DC_STATUS_DATAFORMAT;
}
unsigned char *p = buffer + offset;
if (memcmp (p, device->fingerprint, sizeof (device->fingerprint)) == 0)

View File

@ -35,7 +35,7 @@ dc_status_t
cressi_edy_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
cressi_edy_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
cressi_edy_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -31,6 +31,8 @@
#define IQ700 0x05
#define EDY 0x08
#define SZ_HEADER 32
typedef struct cressi_edy_parser_t cressi_edy_parser_t;
struct cressi_edy_parser_t {
@ -38,7 +40,6 @@ struct cressi_edy_parser_t {
unsigned int model;
};
static dc_status_t cressi_edy_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -46,7 +47,6 @@ static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_
static const dc_parser_vtable_t cressi_edy_parser_vtable = {
sizeof(cressi_edy_parser_t),
DC_FAMILY_CRESSI_EDY,
cressi_edy_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -73,7 +73,7 @@ cressi_edy_parser_count_gasmixes (const unsigned char *data)
}
dc_status_t
cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
cressi_edy_parser_t *parser = NULL;
@ -81,7 +81,7 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (cressi_edy_parser_t *) dc_parser_allocate (context, &cressi_edy_parser_vtable);
parser = (cressi_edy_parser_t *) dc_parser_allocate (context, &cressi_edy_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -96,17 +96,10 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
}
static dc_status_t
cressi_edy_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
if (abstract->size < 32)
if (abstract->size < SZ_HEADER)
return DC_STATUS_DATAFORMAT;
const unsigned char *p = abstract->data;
@ -130,7 +123,7 @@ cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
{
cressi_edy_parser_t *parser = (cressi_edy_parser_t *) abstract;
if (abstract->size < 32)
if (abstract->size < SZ_HEADER)
return DC_STATUS_DATAFORMAT;
const unsigned char *p = abstract->data;
@ -152,6 +145,7 @@ cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
*((unsigned int *) value) = cressi_edy_parser_count_gasmixes(p);
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
gasmix->oxygen = bcd2dec (p[0x17 - flags]) / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -188,7 +182,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
unsigned int ngasmixes = cressi_edy_parser_count_gasmixes(data);
unsigned int gasmix = 0xFFFFFFFF;
unsigned int offset = 32;
unsigned int offset = SZ_HEADER;
while (offset + 2 <= size) {
dc_sample_value_t sample = {0};
@ -201,13 +195,13 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
unsigned int depth = bcd2dec (data[offset + 0] & 0x0F) * 100 + bcd2dec (data[offset + 1]);
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Current gasmix
if (ngasmixes) {
@ -220,7 +214,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
}
if (idx != gasmix) {
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix = idx;
}
}

View File

@ -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, unsigned int model);
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -62,7 +62,6 @@ typedef struct cressi_goa_layout_t {
unsigned int temperature;
} cressi_goa_layout_t;
static dc_status_t cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -70,7 +69,6 @@ static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_
static const dc_parser_vtable_t cressi_goa_parser_vtable = {
sizeof(cressi_goa_parser_t),
DC_FAMILY_CRESSI_GOA,
cressi_goa_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -128,7 +126,7 @@ static const cressi_goa_layout_t layouts[] = {
};
dc_status_t
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
cressi_goa_parser_t *parser = NULL;
@ -136,7 +134,7 @@ cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (cressi_goa_parser_t *) dc_parser_allocate (context, &cressi_goa_parser_vtable);
parser = (cressi_goa_parser_t *) dc_parser_allocate (context, &cressi_goa_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -149,12 +147,6 @@ cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
return DC_STATUS_SUCCESS;
}
static dc_status_t
cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -250,6 +242,7 @@ cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
*((unsigned int *) value) = ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
gasmix->oxygen = data[layout->gasmix + 2 * flags + 1] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -329,25 +322,25 @@ cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
if (complete) {
// Time (seconds).
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Temperature (1/10 °C).
if (have_temperature) {
sample.temperature = temperature / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
have_temperature = 0;
}
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Gas change
if (divemode == SCUBA || divemode == NITROX) {
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
}

View File

@ -35,7 +35,7 @@ dc_status_t
cressi_leonardo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -39,7 +39,6 @@ struct cressi_leonardo_parser_t {
unsigned int model;
};
static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -47,7 +46,6 @@ static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract
static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
sizeof(cressi_leonardo_parser_t),
DC_FAMILY_CRESSI_LEONARDO,
cressi_leonardo_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -59,7 +57,7 @@ static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
dc_status_t
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
cressi_leonardo_parser_t *parser = NULL;
@ -67,7 +65,7 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigne
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (cressi_leonardo_parser_t *) dc_parser_allocate (context, &cressi_leonardo_parser_vtable);
parser = (cressi_leonardo_parser_t *) dc_parser_allocate (context, &cressi_leonardo_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -81,13 +79,6 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigne
}
static dc_status_t
cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -146,6 +137,7 @@ cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
}
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
gasmix->oxygen = data[0x19] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -196,12 +188,12 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
// Time (seconds).
time += surftime;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
sample.depth = 0.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 4;
} else {
@ -211,17 +203,17 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Gas change.
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
@ -235,8 +227,7 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
else
sample.event.flags = 0;
sample.event.value = ascent;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
offset += 2;

View File

@ -36,7 +36,7 @@ dc_status_t
deepblu_cosmiq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
deepblu_cosmiq_parser_create (dc_parser_t **parser, dc_context_t *context);
deepblu_cosmiq_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -41,7 +41,6 @@ typedef struct deepblu_cosmiq_parser_t {
double hydrostatic;
} deepblu_cosmiq_parser_t;
static dc_status_t deepblu_cosmiq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density);
static dc_status_t deepblu_cosmiq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
@ -50,7 +49,6 @@ static dc_status_t deepblu_cosmiq_parser_samples_foreach (dc_parser_t *abstract,
static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
sizeof(deepblu_cosmiq_parser_t),
DC_FAMILY_DEEPBLU_COSMIQ,
deepblu_cosmiq_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
deepblu_cosmiq_parser_set_density, /* set_density */
@ -61,7 +59,7 @@ static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
};
dc_status_t
deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
deepblu_cosmiq_parser_t *parser = NULL;
@ -69,7 +67,7 @@ deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (deepblu_cosmiq_parser_t *) dc_parser_allocate (context, &deepblu_cosmiq_parser_vtable);
parser = (deepblu_cosmiq_parser_t *) dc_parser_allocate (context, &deepblu_cosmiq_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -83,12 +81,6 @@ deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
}
static dc_status_t
deepblu_cosmiq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density)
{
@ -151,6 +143,7 @@ deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
*((unsigned int *) value) = mode == SCUBA;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->oxygen = data[3] / 100.0;
gasmix->helium = 0.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -204,14 +197,14 @@ deepblu_cosmiq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
offset += SZ_SAMPLE;
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
sample.depth = (signed int) (depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
sample.temperature = temperature / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
return DC_STATUS_SUCCESS;

View File

@ -35,7 +35,7 @@ dc_status_t
deepsix_excursion_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
deepsix_excursion_parser_create (dc_parser_t **parser, dc_context_t *context);
deepsix_excursion_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -112,7 +112,6 @@ typedef struct deepsix_excursion_parser_t {
deepsix_excursion_gasmix_t gasmix[MAX_GASMIXES];
} deepsix_excursion_parser_t;
static dc_status_t deepsix_excursion_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t deepsix_excursion_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -122,7 +121,6 @@ static dc_status_t deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abs
static const dc_parser_vtable_t deepsix_parser_vtable = {
sizeof(deepsix_excursion_parser_t),
DC_FAMILY_DEEPSIX_EXCURSION,
deepsix_excursion_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -185,7 +183,7 @@ deepsix_excursion_find_gasmix(deepsix_excursion_parser_t *parser, unsigned int o
}
dc_status_t
deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
deepsix_excursion_parser_t *parser = NULL;
@ -193,7 +191,7 @@ deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (deepsix_excursion_parser_t *) dc_parser_allocate (context, &deepsix_parser_vtable);
parser = (deepsix_excursion_parser_t *) dc_parser_allocate (context, &deepsix_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -213,23 +211,6 @@ deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
}
static dc_status_t
deepsix_excursion_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
deepsix_excursion_parser_t *parser = (deepsix_excursion_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < MAX_GASMIXES; ++i) {
parser->gasmix[i].id = 0;
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
}
return DC_STATUS_SUCCESS;
}
static dc_status_t
deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -322,6 +303,7 @@ deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -423,11 +405,11 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
if (type == TEMPERATURE) {
time += interval;
sample.time = time;
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
sample.depth = pressure_to_depth(depth, atmospheric, DENSITY);
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
}
if (type == ALARM) {
@ -440,11 +422,11 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
length = 8;
} else if (temperature >= 10) {
sample.temperature = temperature / 10.0;
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
} else {
sample.temperature = temperature / 10.0;
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
} else if (type == DECO) {
unsigned int deco = array_uint16_le(data + offset + 4);
@ -454,7 +436,7 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
} else if (type == CNS) {
unsigned int cns = array_uint16_le(data + offset + 4);
sample.cns = cns / 100.0;
if (callback) callback(DC_SAMPLE_CNS, sample, userdata);
if (callback) callback(DC_SAMPLE_CNS, &sample, userdata);
}
offset += length;
@ -591,12 +573,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
// Time (seconds).
time += samplerate;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
unsigned int depth = array_uint16_le (data + offset);
sample.depth = pressure_to_depth(depth, atmospheric, density);
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 2;
// event info
@ -664,7 +646,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
break;
}
if (sample.event.type != SAMPLE_EVENT_NONE) {
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
}
break;
@ -686,7 +668,7 @@ 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);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
break;
case EVENT_SAMPLES_MISSED:
count = array_uint16_le(data + offset + event_offset);
@ -727,12 +709,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
case SAMPLE_TEMPERATURE:
value = array_uint16_le(data + offset);
sample.temperature = value / 10.0;
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
break;
case SAMPLE_CNS:
value = array_uint16_le(data + offset);
sample.cns = value / 10000.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
break;
case SAMPLE_DECO_NDL:
deco_flags = data[offset];
@ -752,7 +734,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
sample.deco.depth = 0;
sample.deco.time = deco_ndl_tts;
}
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
break;
default:
break;

View File

@ -1,51 +0,0 @@
/*
* libdivecomputer
*
* Copyright (C) 2017 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
*/
#ifndef DC_DESCRIPTOR_PRIVATE_H
#define DC_DESCRIPTOR_PRIVATE_H
#include <libdivecomputer/descriptor.h>
// Oh joy. Windows is some truly horrendously broken crap
#undef interface
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct dc_usb_desc_t {
unsigned short vid;
unsigned short pid;
} dc_usb_desc_t;
typedef struct dc_usb_params_t {
unsigned int interface;
unsigned char endpoint_in;
unsigned char endpoint_out;
} dc_usb_params_t;
int
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DC_DESCRIPTOR_PRIVATE_H */

View File

@ -23,7 +23,10 @@
#include <stdlib.h>
#include <string.h>
#include "descriptor-private.h"
#include <libdivecomputer/descriptor.h>
#include <libdivecomputer/usbhid.h>
#include <libdivecomputer/usb.h>
#include "iterator-private.h"
#include "platform.h"
@ -36,36 +39,26 @@
values, \
C_ARRAY_SIZE(values) - isnullterminated, \
C_ARRAY_ITEMSIZE(values), \
match, \
NULL, NULL, 0)
#define DC_FILTER_INTERNAL_WITH_PARAMS(key, values, isnullterminated, match, params_dst, params_src) \
dc_filter_internal( \
key, \
values, \
C_ARRAY_SIZE(values) - isnullterminated, \
C_ARRAY_ITEMSIZE(values), \
match, \
params_dst, params_src, sizeof *(params_src))
match)
typedef int (*dc_match_t)(const void *, const void *);
typedef int (*dc_filter_t) (dc_transport_t transport, const void *userdata, void *params);
typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_mclean (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params);
static int dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_mclean (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
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);
// Not merged upstream yet
static int dc_filter_garmin (dc_transport_t transport, const void *userdata, void *params);
@ -180,7 +173,10 @@ static const dc_descriptor_t g_descriptors[] = {
{"Scubapro", "G2 TEK", DC_FAMILY_UWATEC_SMART, 0x31, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
{"Scubapro", "G2", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
{"Scubapro", "G2 Console", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
{"Scubapro", "G3", DC_FAMILY_UWATEC_SMART, 0x34, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
{"Scubapro", "G2 HUD", DC_FAMILY_UWATEC_SMART, 0x42, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
{"Scubapro", "Luna 2.0 AI", DC_FAMILY_UWATEC_SMART, 0x50, DC_TRANSPORT_BLE, dc_filter_uwatec},
{"Scubapro", "Luna 2.0", DC_FAMILY_UWATEC_SMART, 0x51, DC_TRANSPORT_BLE, dc_filter_uwatec},
/* Reefnet */
{"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1, DC_TRANSPORT_SERIAL, NULL},
{"Reefnet", "Sensus Pro", DC_FAMILY_REEFNET_SENSUSPRO, 2, DC_TRANSPORT_SERIAL, NULL},
@ -364,6 +360,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Shearwater", "Peregrine", DC_FAMILY_SHEARWATER_PETREL, 9, DC_TRANSPORT_BLE, dc_filter_shearwater},
{"Shearwater", "Petrel 3", DC_FAMILY_SHEARWATER_PETREL, 10, DC_TRANSPORT_BLE, dc_filter_shearwater},
{"Shearwater", "Perdix 2", DC_FAMILY_SHEARWATER_PETREL, 11, DC_TRANSPORT_BLE, dc_filter_shearwater},
{"Shearwater", "Tern", DC_FAMILY_SHEARWATER_PETREL, 12, DC_TRANSPORT_BLE, dc_filter_shearwater},
/* Dive Rite NiTek Q */
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0, DC_TRANSPORT_SERIAL, NULL},
/* Citizen Hyper Aqualand */
@ -417,6 +414,20 @@ static const dc_descriptor_t g_descriptors[] = {
{"Ratio", "iX3M 2021 Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x73, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M 2021 Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x74, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iX3M 2021 Pro Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x75, DC_TRANSPORT_SERIAL, NULL},
{"Ratio", "iDive 2 Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x80, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iDive 2 Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x81, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iDive 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x82, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iDive 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x83, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iDive 2 Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x84, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iDive 2 Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x85, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iDive 2 Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x86, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 GPS Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x90, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 GPS Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x91, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 GPS Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x92, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 GPS Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x93, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 GPS Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x94, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 GPS Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x95, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "ATOM", DC_FAMILY_DIVESYSTEM_IDIVE, 0x96, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x100, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x101, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
{"Ratio", "iX3M 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x102, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
@ -446,7 +457,6 @@ static const dc_descriptor_t g_descriptors[] = {
{"Deep Six", "Excursion", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
{"Crest", "CR-4", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
{"Genesis", "Centauri", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
{"Tusa", "TC1", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
{"Scorpena", "Alpha", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
/* Seac Screen */
{"Seac", "Screen", DC_FAMILY_SEAC_SCREEN, 0, DC_TRANSPORT_SERIAL, NULL},
@ -504,6 +514,15 @@ dc_match_usb (const void *key, const void *value)
return k->vid == v->vid && k->pid == v->pid;
}
static int
dc_match_usbhid (const void *key, const void *value)
{
const dc_usbhid_desc_t *k = (const dc_usbhid_desc_t *) key;
const dc_usbhid_desc_t *v = (const dc_usbhid_desc_t *) value;
return k->vid == v->vid && k->pid == v->pid;
}
static int
dc_match_number_with_prefix (const void *key, const void *value)
{
@ -544,16 +563,13 @@ dc_match_oceanic (const void *key, const void *value)
}
static int
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match, void *params_dst, const void *params_src, size_t params_size)
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match)
{
if (key == NULL)
return 1;
for (size_t i = 0; i < count; ++i) {
if (match (key, (const unsigned char *) values + i * size)) {
if (params_src && params_dst) {
memcpy (params_dst, params_src, params_size);
}
return 1;
}
}
@ -568,7 +584,8 @@ static const char * const rfcomm[] = {
NULL
};
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const irda[] = {
"Aladin Smart Com",
@ -579,7 +596,7 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi
"UWATEC Galileo",
"UWATEC Galileo Sol",
};
static const dc_usb_desc_t usbhid[] = {
static const dc_usbhid_desc_t usbhid[] = {
{0x2e6c, 0x3201}, // G2, G2 TEK
{0x2e6c, 0x3211}, // G2 Console
{0x2e6c, 0x4201}, // G2 HUD
@ -592,12 +609,15 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi
"A1",
"A2",
"G2 TEK",
"Galileo 3",
"Luna 2.0 AI",
"Luna 2.0",
};
if (transport == DC_TRANSPORT_IRDA) {
return DC_FILTER_INTERNAL (userdata, irda, 0, dc_match_name);
} else if (transport == DC_TRANSPORT_USBHID) {
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid);
} else if (transport == DC_TRANSPORT_BLE) {
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
}
@ -605,9 +625,10 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi
return 1;
}
static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const dc_usb_desc_t usbhid[] = {
static const dc_usbhid_desc_t usbhid[] = {
{0x1493, 0x0030}, // Eon Steel
{0x1493, 0x0033}, // Eon Core
{0x1493, 0x0035}, // D5
@ -621,7 +642,7 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata, voi
};
if (transport == DC_TRANSPORT_USBHID) {
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid);
} else if (transport == DC_TRANSPORT_BLE) {
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
}
@ -629,7 +650,8 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata, voi
return 1;
}
static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"OSTC",
@ -645,7 +667,8 @@ static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *p
return 1;
}
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"Predator",
@ -657,6 +680,7 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata,
"Perdix 2",
"Teric",
"Peregrine",
"Tern"
};
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
@ -668,7 +692,8 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata,
return 1;
}
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"DiveComputer",
@ -683,7 +708,8 @@ static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata,
return 1;
}
static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"Mares bluelink pro",
@ -697,11 +723,13 @@ static int dc_filter_mares (dc_transport_t transport, const void *userdata, void
return 1;
}
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"DS",
"IX5M",
"RATIO-",
};
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
@ -711,7 +739,8 @@ static int dc_filter_divesystem (dc_transport_t transport, const void *userdata,
return 1;
}
static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const unsigned int model[] = {
0x4552, // Oceanic Pro Plus X
@ -738,7 +767,8 @@ static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, vo
return 1;
}
static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"McLean Extreme",
@ -753,30 +783,27 @@ static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void
return 1;
}
static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const dc_usb_desc_t usb[] = {
{0x0471, 0x0888}, // Atomic Aquatics Cobalt
};
static const dc_usb_params_t usb_params = {
0, 0x82, 0x02
};
if (transport == DC_TRANSPORT_USB) {
return DC_FILTER_INTERNAL_WITH_PARAMS (userdata, usb, 0, dc_match_usb, params, &usb_params);
return DC_FILTER_INTERNAL (userdata, usb, 0, dc_match_usb);
}
return 1;
}
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"EXCURSION",
"Crest-CR4",
"CENTAURI",
"TC1",
"ALPHA",
};
@ -787,7 +814,8 @@ static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, vo
return 1;
}
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"COSMIQ",
@ -800,7 +828,8 @@ static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, vo
return 1;
}
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"S1",
@ -813,7 +842,8 @@ static int dc_filter_oceans (dc_transport_t transport, const void *userdata, voi
return 1;
}
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params)
static int
dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
static const char * const bluetooth[] = {
"Freedom",
@ -933,10 +963,10 @@ dc_descriptor_get_transports (dc_descriptor_t *descriptor)
}
int
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params)
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
{
if (descriptor == NULL || descriptor->filter == NULL || userdata == NULL)
return 1;
return descriptor->filter (transport, userdata, params);
return descriptor->filter (descriptor, transport, userdata);
}

View File

@ -35,7 +35,7 @@ dc_status_t
diverite_nitekq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
diverite_nitekq_parser_create (dc_parser_t **parser, dc_context_t *context);
diverite_nitekq_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -49,7 +49,6 @@ struct diverite_nitekq_parser_t {
double maxdepth;
};
static dc_status_t diverite_nitekq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -57,7 +56,6 @@ static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract
static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
sizeof(diverite_nitekq_parser_t),
DC_FAMILY_DIVERITE_NITEKQ,
diverite_nitekq_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -69,7 +67,7 @@ static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
dc_status_t
diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
diverite_nitekq_parser_t *parser = NULL;
@ -77,7 +75,7 @@ diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (diverite_nitekq_parser_t *) dc_parser_allocate (context, &diverite_nitekq_parser_vtable);
parser = (diverite_nitekq_parser_t *) dc_parser_allocate (context, &diverite_nitekq_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -101,13 +99,6 @@ diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
}
static dc_status_t
diverite_nitekq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -161,6 +152,7 @@ diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = parser->he[flags] / 100.0;
gasmix->oxygen = parser->o2[flags] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -264,13 +256,13 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Gas change
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
@ -282,7 +274,7 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
sample.depth = depth / 10.0;
else
sample.depth = depth * FEET / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 2;
if (type == 3) {
@ -293,8 +285,9 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
if (offset + 1 > size)
return DC_STATUS_DATAFORMAT;
unsigned int ppo2 = data[offset];
sample.ppo2 = ppo2 / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = DC_SENSOR_NONE;
sample.ppo2.value = ppo2 / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
offset++;
}
} else {

View File

@ -35,7 +35,7 @@ dc_status_t
divesoft_freedom_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context);
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -254,7 +254,6 @@ typedef struct divesoft_freedom_parser_t {
unsigned int calibrated;
} divesoft_freedom_parser_t;
static dc_status_t divesoft_freedom_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -262,7 +261,6 @@ static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstrac
static const dc_parser_vtable_t divesoft_freedom_parser_vtable = {
sizeof(divesoft_freedom_parser_t),
DC_FAMILY_DIVESOFT_FREEDOM,
divesoft_freedom_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -643,7 +641,7 @@ divesoft_freedom_cache (divesoft_freedom_parser_t *parser)
}
dc_status_t
divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
divesoft_freedom_parser_t *parser = NULL;
@ -651,7 +649,7 @@ divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (divesoft_freedom_parser_t *) dc_parser_allocate (context, &divesoft_freedom_parser_vtable);
parser = (divesoft_freedom_parser_t *) dc_parser_allocate (context, &divesoft_freedom_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -698,50 +696,6 @@ divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
}
static dc_status_t
divesoft_freedom_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
divesoft_freedom_parser_t *parser = (divesoft_freedom_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->version = 0;
parser->headersize = 0;
parser->divetime = 0;
parser->divemode = 0;
parser->temperature_min = 0;
parser->maxdepth = 0;
parser->atmospheric = 0;
parser->avgdepth = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
parser->gasmix[i].type = 0;
parser->gasmix[i].id = 0;
}
parser->diluent = UNDEFINED;
parser->ntanks = 0;
for (unsigned int i = 0; i < NTANKS; ++i) {
parser->tank[i].volume = 0;
parser->tank[i].workpressure = 0;
parser->tank[i].beginpressure = 0;
parser->tank[i].endpressure = 0;
parser->tank[i].transmitter = 0;
parser->tank[i].active = 0;
}
parser->vpm = 0;
parser->gf_lo = 0;
parser->gf_hi = 0;
parser->seawater = 0;
for (unsigned int i = 0; i < NSENSORS; ++i) {
parser->calibration[i] = 0;
}
parser->calibrated = 0;
return DC_STATUS_SUCCESS;
}
static dc_status_t
divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -838,6 +792,13 @@ divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
if (parser->gasmix[flags].type == OXYGEN) {
gasmix->usage = DC_USAGE_OXYGEN;
} else if (parser->gasmix[flags].type == DILUENT) {
gasmix->usage = DC_USAGE_DILUENT;
} else {
gasmix->usage = DC_USAGE_NONE;
}
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -859,6 +820,7 @@ divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
tank->beginpressure = parser->tank[flags].beginpressure * 2.0;
tank->endpressure = parser->tank[flags].endpressure * 2.0;
tank->gasmix = flags;
tank->usage = DC_USAGE_NONE;
break;
case DC_FIELD_DECOMODEL:
if (parser->vpm) {
@ -924,15 +886,15 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
continue;
}
time = timestamp;
sample.time = time;
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
}
// Initial diluent.
if (!initial) {
if (parser->diluent != UNDEFINED) {
sample.gasmix = parser->diluent;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
}
initial = 1;
}
@ -943,18 +905,19 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
unsigned int ppo2 = array_uint16_le (data + offset + 6);
sample.depth = depth / 100.0;
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
if (ppo2) {
sample.ppo2 = ppo2 * 10.0 / BAR;
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = DC_SENSOR_NONE;
sample.ppo2.value = ppo2 * 10.0 / BAR;
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
}
if (id == POINT_2) {
unsigned int orientation = array_uint32_le (data + offset + 8);
unsigned int heading = orientation & 0x1FF;
sample.bearing = heading;
if (callback) callback (DC_SAMPLE_BEARING, sample, userdata);
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
} else if (id == POINT_1 || id == POINT_1_OLD) {
unsigned int misc = array_uint32_le (data + offset + 8);
unsigned int ceiling = array_uint16_le (data + offset + 12);
@ -965,7 +928,7 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
// Temperature
sample.temperature = (signed int) signextend (temp, 10) / 10.0;
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Deco / NDL
if (ceiling) {
@ -977,12 +940,13 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.deco.time = ndl * 60;
sample.deco.depth = 0.0;
}
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = tts * 60;
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
// Setpoint
if (setpoint) {
sample.setpoint = setpoint / 100.0;
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
}
}
} else if ((type >= LREC_MANIPULATION && type <= LREC_ACTIVITY) || type == LREC_INFO) {
@ -994,7 +958,7 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback(DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback(DC_SAMPLE_EVENT, &sample, userdata);
} else if (event == EVENT_MIX_CHANGED || event == EVENT_DILUENT || event == EVENT_CHANGE_MODE) {
unsigned int o2 = data[offset + 6];
unsigned int he = data[offset + 7];
@ -1014,13 +978,13 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
} else if (event == EVENT_CNS) {
sample.cns = array_uint16_le (data + offset + 6) / 100.0;
if (callback) callback(DC_SAMPLE_CNS, sample, userdata);
if (callback) callback(DC_SAMPLE_CNS, &sample, userdata);
} else if (event == EVENT_SETPOINT_MANUAL || event == EVENT_SETPOINT_AUTO) {
sample.setpoint = data[6] / 100.0;
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
}
} else if (type == LREC_MEASURE) {
// Measurement record.
@ -1038,25 +1002,27 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.pressure.tank = idx;
sample.pressure.value = pressure * 2.0;
if (callback) callback(DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback(DC_SAMPLE_PRESSURE, &sample, userdata);
}
} else if (id == MEASURE_ID_OXYGEN) {
for (unsigned int i = 0; i < NSENSORS; ++i) {
unsigned int ppo2 = array_uint16_le (data + offset + 4 + i * 2);
if (ppo2 == 0 || ppo2 == 0xFFFF)
continue;
sample.ppo2 = ppo2 * 10.0 / BAR;
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = i;
sample.ppo2.value = ppo2 * 10.0 / BAR;
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
}
} else if (id == MEASURE_ID_OXYGEN_MV) {
for (unsigned int i = 0; i < NSENSORS; ++i) {
unsigned int value = array_uint16_le (data + offset + 4 + i * 2);
unsigned int state = data[offset + 12 + i];
if (!parser->calibrated || state == SENSTAT_UNCALIBRATED ||
state == SENSTAT_NOT_EXIST)
if (!parser->calibrated || parser->calibration[i] == 0 ||
state == SENSTAT_UNCALIBRATED || state == SENSTAT_NOT_EXIST)
continue;
sample.ppo2 = value / 100.0 * parser->calibration[i] / BAR;
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = i;
sample.ppo2.value = value / 100.0 * parser->calibration[i] / BAR;
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
}
}
} else if (type == LREC_STATE) {

View File

@ -36,7 +36,7 @@ dc_status_t
divesystem_idive_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
dc_status_t
divesystem_idive_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
divesystem_idive_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -58,6 +58,9 @@
#define IX3M2_ZHL16C 2
#define IX3M2_VPM 3
#define REC_SAMPLE 0
#define REC_INFO 1
typedef struct divesystem_idive_parser_t divesystem_idive_parser_t;
typedef struct divesystem_idive_gasmix_t {
@ -89,7 +92,6 @@ struct divesystem_idive_parser_t {
unsigned int gf_high;
};
static dc_status_t divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -97,7 +99,6 @@ static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstrac
static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
sizeof(divesystem_idive_parser_t),
DC_FAMILY_DIVESYSTEM_IDIVE,
divesystem_idive_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -109,7 +110,7 @@ static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
dc_status_t
divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
divesystem_idive_parser_t *parser = NULL;
@ -117,7 +118,7 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (divesystem_idive_parser_t *) dc_parser_allocate (context, &divesystem_idive_parser_vtable);
parser = (divesystem_idive_parser_t *) dc_parser_allocate (context, &divesystem_idive_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -156,35 +157,6 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
}
static dc_status_t
divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
divesystem_idive_parser_t *parser = (divesystem_idive_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->divemode = INVALID;
parser->divetime = 0;
parser->maxdepth = 0;
parser->ngasmixes = 0;
parser->ntanks = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
}
for (unsigned int i = 0; i < NTANKS; ++i) {
parser->tank[i].id = 0;
parser->tank[i].beginpressure = 0;
parser->tank[i].endpressure = 0;
}
parser->algorithm = INVALID;
parser->gf_low = INVALID;
parser->gf_high = INVALID;
return DC_STATUS_SUCCESS;
}
static dc_status_t
divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -317,6 +289,7 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -331,6 +304,7 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
tank->beginpressure = parser->tank[flags].beginpressure;
tank->endpressure = parser->tank[flags].endpressure;
tank->gasmix = DC_GASMIX_UNKNOWN;
tank->usage = DC_USAGE_NONE;
break;
case DC_FIELD_ATMOSPHERIC:
if (ISIX3M(parser->model)) {
@ -439,6 +413,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
unsigned int algorithm_previous = INVALID;
unsigned int gf_low = INVALID;
unsigned int gf_high = INVALID;
unsigned int have_bearing = 0;
unsigned int firmware = 0;
unsigned int apos4 = 0;
@ -467,27 +442,37 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
while (offset + samplesize <= size) {
dc_sample_value_t sample = {0};
// Get the record type.
unsigned int type = ISIX3M(parser->model) ?
array_uint16_le (data + offset + 52) :
REC_SAMPLE;
if (type != REC_SAMPLE) {
// Skip non-sample records.
offset += samplesize;
continue;
}
// Time (seconds).
unsigned int timestamp = array_uint32_le (data + offset + 2);
if (timestamp <= time) {
ERROR (abstract->context, "Timestamp moved backwards.");
if (timestamp <= time && time != 0) {
ERROR (abstract->context, "Timestamp moved backwards (%u %u).", timestamp, time);
return DC_STATUS_DATAFORMAT;
}
time = timestamp;
sample.time = timestamp;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = timestamp * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
unsigned int depth = array_uint16_le (data + offset + 6);
if (maxdepth < depth)
maxdepth = depth;
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (Celsius).
signed int temperature = (signed short) array_uint16_le (data + offset + 8);
sample.temperature = temperature / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Dive mode
unsigned int mode = data[offset + 18];
@ -521,7 +506,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
if (mode == SCR || mode == CCR) {
unsigned int setpoint = array_uint16_le (data + offset + 19);
sample.setpoint = setpoint / 1000.0;
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
}
// Gaschange.
@ -548,7 +533,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
}
sample.gasmix = i;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
o2_previous = o2;
he_previous = he;
}
@ -566,18 +551,20 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
if (decostop) {
sample.deco.type = DC_DECO_DECOSTOP;
sample.deco.depth = decostop / 10.0;
sample.deco.time = apos4 ? decotime : tts;
sample.deco.time = decotime;
sample.deco.tts = tts;
} else {
sample.deco.type = DC_DECO_NDL;
sample.deco.depth = 0.0;
sample.deco.time = tts;
sample.deco.tts = 0;
}
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
// CNS
unsigned int cns = array_uint16_le (data + offset + 29);
sample.cns = cns / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
// Tank Pressure
if (samplesize == SZ_SAMPLE_IX3M_APOS4) {
@ -598,7 +585,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
} else {
// Get the index of the tank.
if (id != tank_previous) {
@ -628,10 +615,20 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
if (tank_idx < ntanks) {
sample.pressure.tank = tank_idx;
sample.pressure.value = pressure;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
tank[tank_idx].endpressure = pressure;
}
}
// Compass bearing
unsigned int bearing = array_uint16_le (data + offset + 50);
if (bearing != 0) {
have_bearing = 1; // Stop ignoring zero values.
}
if (have_bearing && bearing != 0xFFFF) {
sample.bearing = bearing;
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
}
}
offset += samplesize;

View File

@ -26,6 +26,7 @@ typedef struct dc_field_cache {
// dc_tank_t TANK[MAXGASES]
// but that's for later
dc_tankinfo_t tankinfo[MAXGASES];
dc_usage_t tankusage[MAXGASES];
double tanksize[MAXGASES];
double tankworkingpressure[MAXGASES];

View File

@ -36,7 +36,7 @@ dc_status_t
hw_ostc_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial);
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -240,7 +240,7 @@ hw_ostc3_write (hw_ostc3_device_t *device, dc_event_progress_t *progress, const
size_t nbytes = 0;
while (nbytes < size) {
// Set the maximum packet size.
size_t length = 64;
size_t length = (device->hardware == OSTC4) ? 64 : 1024;
// Limit the packet size to the total size.
if (nbytes + length > size)

View File

@ -36,7 +36,7 @@ dc_status_t
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int model);
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -43,10 +43,6 @@
#define UNDEFINED 0xFFFFFFFF
#define ALL 0
#define FIXED 1
#define MANUAL 2
#define HEADER 1
#define PROFILE 2
@ -117,10 +113,12 @@ typedef struct hw_ostc_layout_t {
} hw_ostc_layout_t;
typedef struct hw_ostc_gasmix_t {
unsigned int id;
unsigned int oxygen;
unsigned int helium;
unsigned int type;
unsigned int enabled;
unsigned int active;
unsigned int diluent;
} hw_ostc_gasmix_t;
@ -136,6 +134,7 @@ typedef struct hw_ostc_parser_t {
const hw_ostc_layout_t *layout;
unsigned int ngasmixes;
unsigned int nfixed;
unsigned int ndisabled;
unsigned int initial;
unsigned int initial_setpoint;
unsigned int initial_cns;
@ -143,15 +142,15 @@ typedef struct hw_ostc_parser_t {
unsigned int current_divemode_ccr;
} hw_ostc_parser_t;
static dc_status_t hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
static dc_status_t hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
static const dc_parser_vtable_t hw_ostc_parser_vtable = {
sizeof(hw_ostc_parser_t),
DC_FAMILY_HW_OSTC,
hw_ostc_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -216,15 +215,10 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
};
static unsigned int
hw_ostc_find_gasmix (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil, unsigned int type)
hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil)
{
unsigned int offset = 0;
unsigned int offset = parser->nfixed - parser->ndisabled;
unsigned int count = parser->ngasmixes;
if (type == FIXED) {
count = parser->nfixed;
} else if (type == MANUAL) {
offset = parser->nfixed;
}
unsigned int i = offset;
while (i < count) {
@ -236,6 +230,22 @@ hw_ostc_find_gasmix (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he,
return i;
}
static unsigned int
hw_ostc_find_gasmix_fixed (hw_ostc_parser_t *parser, unsigned int id)
{
unsigned int offset = 0;
unsigned int count = parser->nfixed - parser->ndisabled;
unsigned int i = offset;
while (i < count) {
if (id == parser->gasmix[i].id)
break;
i++;
}
return i;
}
static unsigned int
hw_ostc_is_ccr (unsigned int divemode, unsigned int version)
{
@ -317,19 +327,23 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
initial = data[31];
}
for (unsigned int i = 0; i < ngasmixes; ++i) {
gasmix[i].id = i + 1;
gasmix[i].oxygen = data[25 + 2 * i];
gasmix[i].helium = 0;
gasmix[i].type = 0;
gasmix[i].enabled = 1;
gasmix[i].active = 0;
gasmix[i].diluent = 0;
}
} else if (version == 0x23 || version == 0x24) {
ngasmixes = 5;
for (unsigned int i = 0; i < ngasmixes; ++i) {
gasmix[i].id = i + 1;
gasmix[i].oxygen = data[28 + 4 * i + 0];
gasmix[i].helium = data[28 + 4 * i + 1];
gasmix[i].type = data[28 + 4 * i + 3];
gasmix[i].enabled = gasmix[i].type != 0;
gasmix[i].active = 0;
gasmix[i].diluent = ccr;
// Find the first gas marked as the initial gas.
if (initial == UNDEFINED && data[28 + 4 * i + 3] == 1) {
@ -348,6 +362,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
initial = data[31];
}
for (unsigned int i = 0; i < ngasmixes; ++i) {
gasmix[i].id = i + 1;
gasmix[i].oxygen = data[19 + 2 * i + 0];
gasmix[i].helium = data[19 + 2 * i + 1];
gasmix[i].type = 0;
@ -356,6 +371,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
} else {
gasmix[i].enabled = 1;
}
gasmix[i].active = 0;
gasmix[i].diluent = ccr;
}
}
@ -364,7 +380,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
ERROR(abstract->context, "Invalid initial gas mix.");
return DC_STATUS_DATAFORMAT;
}
initial--; /* Convert to a zero based index. */
} else {
WARNING(abstract->context, "No initial gas mix available.");
}
@ -375,6 +390,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
parser->layout = layout;
parser->ngasmixes = ngasmixes;
parser->nfixed = ngasmixes;
parser->ndisabled = 0;
parser->initial = initial;
parser->initial_setpoint = initial_setpoint;
parser->initial_cns = initial_cns;
@ -387,7 +403,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
}
static dc_status_t
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int hwos, unsigned int model)
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int hwos, unsigned int model, unsigned int serial)
{
hw_ostc_parser_t *parser = NULL;
@ -395,7 +411,7 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (hw_ostc_parser_t *) dc_parser_allocate (context, &hw_ostc_parser_vtable);
parser = (hw_ostc_parser_t *) dc_parser_allocate (context, &hw_ostc_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -410,14 +426,17 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
parser->layout = NULL;
parser->ngasmixes = 0;
parser->nfixed = 0;
parser->ndisabled = 0;
parser->initial = 0;
parser->initial_setpoint = 0;
parser->initial_cns = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].id = 0;
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
parser->gasmix[i].type = 0;
parser->gasmix[i].enabled = 0;
parser->gasmix[i].active = 0;
parser->gasmix[i].diluent = 0;
}
parser->serial = serial;
@ -429,44 +448,17 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
dc_status_t
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial)
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int serial)
{
return hw_ostc_parser_create_internal (out, context, serial, 0, 0);
return hw_ostc_parser_create_internal (out, context, data, size, 0, 0, serial);
}
dc_status_t
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int model)
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
{
return hw_ostc_parser_create_internal (out, context, serial, 1, model);
return hw_ostc_parser_create_internal (out, context, data, size, 1, model, serial);
}
static dc_status_t
hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->version = 0;
parser->header = 0;
parser->layout = NULL;
parser->ngasmixes = 0;
parser->nfixed = 0;
parser->initial = 0;
parser->initial_setpoint = 0;
parser->initial_cns = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
parser->gasmix[i].type = 0;
parser->gasmix[i].enabled = 0;
parser->gasmix[i].diluent = 0;
}
return DC_STATUS_SUCCESS;
}
static dc_status_t
hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -542,7 +534,7 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
// Cache the profile data.
if (parser->cached < PROFILE) {
rc = hw_ostc_parser_samples_foreach (abstract, NULL, NULL);
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
if (rc != DC_STATUS_SUCCESS)
return rc;
}
@ -582,6 +574,8 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
return DC_STATUS_UNSUPPORTED;
}
gasmix->usage = parser->gasmix[flags].diluent ?
DC_USAGE_DILUENT : DC_USAGE_NONE;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -839,7 +833,7 @@ static void hw_ostc_notify_bailout(hw_ostc_parser_t *parser, const unsigned char
}
if (callback) {
callback(DC_SAMPLE_EVENT, sample, userdata);
callback(DC_SAMPLE_EVENT, &sample, userdata);
}
parser->current_divemode_ccr = parser->gasmix[index].diluent;
@ -847,17 +841,12 @@ static void hw_ostc_notify_bailout(hw_ostc_parser_t *parser, const unsigned char
}
static dc_status_t
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata)
{
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
dc_parser_t *abstract = (dc_parser_t *) parser;
const unsigned char *data = abstract->data;
unsigned int size = abstract->size;
// Cache the parser data.
dc_status_t rc = hw_ostc_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
return rc;
unsigned int version = parser->version;
unsigned int header = parser->header;
const hw_ostc_layout_t *layout = parser->layout;
@ -964,7 +953,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
unsigned int time = 0;
unsigned int nsamples = 0;
unsigned int tank = parser->initial != UNDEFINED ? parser->initial : 0;
unsigned int tank = parser->initial != UNDEFINED ? parser->initial - 1 : 0;
unsigned int offset = header;
if (version == 0x23 || version == 0x24)
@ -976,31 +965,33 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
// Time (seconds).
time += samplerate;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Initial gas mix.
if (time == samplerate && parser->initial != UNDEFINED) {
sample.gasmix = parser->initial;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, parser->initial);
parser->gasmix[idx].active = 1;
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
}
// Initial setpoint (mbar).
if (time == samplerate && parser->initial_setpoint != UNDEFINED) {
sample.setpoint = parser->initial_setpoint / 100.0;
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
}
// Initial CNS (%).
if (time == samplerate && parser->initial_cns != UNDEFINED) {
sample.cns = parser->initial_cns / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
}
// Depth (1/100 m).
unsigned int depth = array_uint16_le (data + offset);
sample.depth = depth / 100.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 2;
// Extended sample info.
@ -1059,7 +1050,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
break;
}
if (sample.event.type && callback)
callback (DC_SAMPLE_EVENT, sample, userdata);
callback (DC_SAMPLE_EVENT, &sample, userdata);
// Manual Gas Set & Change
if (events & 0x10) {
@ -1076,22 +1067,24 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
diluent = ccr;
}
unsigned int he = data[offset + 1];
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, diluent, MANUAL);
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, diluent);
if (idx >= parser->ngasmixes) {
if (idx >= NGASMIXES) {
ERROR (abstract->context, "Maximum number of gas mixes reached.");
return DC_STATUS_NOMEMORY;
}
parser->gasmix[idx].id = 0;
parser->gasmix[idx].oxygen = o2;
parser->gasmix[idx].helium = he;
parser->gasmix[idx].type = 0;
parser->gasmix[idx].enabled = 1;
parser->gasmix[idx].active = 1;
parser->gasmix[idx].diluent = diluent;
parser->ngasmixes = idx + 1;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
@ -1105,19 +1098,20 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
ERROR (abstract->context, "Buffer overflow detected!");
return DC_STATUS_DATAFORMAT;
}
unsigned int idx = data[offset];
if (idx > parser->nfixed && idx <= parser->nfixed + OSTC4_CC_DILUENT_GAS_OFFSET) {
unsigned int id = data[offset];
if (id > parser->nfixed && id <= parser->nfixed + OSTC4_CC_DILUENT_GAS_OFFSET) {
// OSTC4 reports gas changes to another diluent with an offset
idx -= OSTC4_CC_DILUENT_GAS_OFFSET;
id -= OSTC4_CC_DILUENT_GAS_OFFSET;
}
if (idx < 1 || idx > parser->nfixed) {
ERROR(abstract->context, "Invalid gas mix (%u).", idx);
if (id < 1 || id > parser->nfixed) {
ERROR(abstract->context, "Invalid gas mix (%u).", id);
return DC_STATUS_DATAFORMAT;
}
idx--; /* Convert to a zero based index. */
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, id);
parser->gasmix[idx].active = 1;
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
tank = idx;
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
tank = id - 1;
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
@ -1133,7 +1127,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
return DC_STATUS_DATAFORMAT;
}
sample.setpoint = data[offset] / 100.0;
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
offset++;
length--;
}
@ -1147,22 +1141,24 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
unsigned int o2 = data[offset];
unsigned int he = data[offset + 1];
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, 0, MANUAL);
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, 0);
if (idx >= parser->ngasmixes) {
if (idx >= NGASMIXES) {
ERROR (abstract->context, "Maximum number of gas mixes reached.");
return DC_STATUS_NOMEMORY;
}
parser->gasmix[idx].id = 0;
parser->gasmix[idx].oxygen = o2;
parser->gasmix[idx].helium = he;
parser->gasmix[idx].type = 0;
parser->gasmix[idx].enabled = 1;
parser->gasmix[idx].active = 1;
parser->gasmix[idx].diluent = 0;
parser->ngasmixes = idx + 1;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
@ -1197,7 +1193,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
case TEMPERATURE:
value = array_uint16_le (data + offset);
sample.temperature = value / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
break;
case DECO:
// Due to a firmware bug, the deco/ndl info is incorrect for
@ -1212,7 +1208,8 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
sample.deco.depth = 0.0;
}
sample.deco.time = data[offset + 1] * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
break;
case PPO2:
for (unsigned int j = 0; j < 3; ++j) {
@ -1226,8 +1223,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
}
if (count) {
for (unsigned int j = 0; j < 3; ++j) {
sample.ppo2 = ppo2[j] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = i;
sample.ppo2.value = ppo2[j] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
}
}
break;
@ -1236,7 +1234,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
sample.cns = array_uint16_le (data + offset) / 100.0;
else
sample.cns = data[offset] / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
break;
case TANK:
value = array_uint16_le (data + offset);
@ -1249,7 +1247,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
(firmware >= OSTC3FW(10,40) && firmware <= OSTC3FW(10,50))) {
sample.pressure.value /= 10.0;
}
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
break;
default: // Not yet used.
@ -1269,7 +1267,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
return DC_STATUS_DATAFORMAT;
}
sample.setpoint = data[offset] / 100.0;
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
offset++;
length--;
}
@ -1283,22 +1281,24 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
unsigned int o2 = data[offset];
unsigned int he = data[offset + 1];
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, 0, MANUAL);
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, 0);
if (idx >= parser->ngasmixes) {
if (idx >= NGASMIXES) {
ERROR (abstract->context, "Maximum number of gas mixes reached.");
return DC_STATUS_NOMEMORY;
}
parser->gasmix[idx].id = 0;
parser->gasmix[idx].oxygen = o2;
parser->gasmix[idx].helium = he;
parser->gasmix[idx].type = 0;
parser->gasmix[idx].enabled = 1;
parser->gasmix[idx].active = 1;
parser->gasmix[idx].diluent = 0;
parser->ngasmixes = idx + 1;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
@ -1319,7 +1319,50 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
return DC_STATUS_DATAFORMAT;
}
// Remove the disabled gas mixes from the fixed gas mixes.
unsigned int ndisabled = 0, nenabled = 0;
unsigned int count = parser->nfixed - parser->ndisabled;
for (unsigned int i = 0; i < count; ++i) {
if (parser->gasmix[i].enabled || parser->gasmix[i].active) {
// Move the fixed gas mix.
parser->gasmix[nenabled] = parser->gasmix[i];
nenabled++;
} else {
ndisabled++;
}
}
// Move all the manual gas mixes.
memmove (parser->gasmix + nenabled, parser->gasmix + count,
(parser->ngasmixes - count) * sizeof (hw_ostc_gasmix_t));
memset (parser->gasmix + parser->ngasmixes - ndisabled, 0,
ndisabled * sizeof (hw_ostc_gasmix_t));
// Adjust the counts.
parser->ngasmixes -= ndisabled;
parser->ndisabled += ndisabled;
parser->cached = PROFILE;
return DC_STATUS_SUCCESS;
}
static dc_status_t
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
{
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
// Cache the header data.
dc_status_t rc = hw_ostc_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
return rc;
// Cache the profile data.
if (parser->cached < PROFILE) {
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
if (rc != DC_STATUS_SUCCESS)
return rc;
}
return hw_ostc_parser_internal_foreach (parser, callback, userdata);
}

View File

@ -47,7 +47,6 @@
#include "context-private.h"
#include "iostream-private.h"
#include "iterator-private.h"
#include "descriptor-private.h"
#include "array.h"
#include "platform.h"
@ -226,7 +225,7 @@ dc_irda_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_
INFO (context, "Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
address, name, charset, hints);
if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name, NULL)) {
if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name)) {
continue;
}

View File

@ -34,6 +34,7 @@ dc_descriptor_get_product
dc_descriptor_get_type
dc_descriptor_get_model
dc_descriptor_get_transports
dc_descriptor_filter
dc_iostream_get_transport
dc_iostream_set_timeout
@ -93,17 +94,11 @@ dc_parser_set_clock
dc_parser_set_atmospheric
dc_parser_set_density
dc_parser_get_type
dc_parser_set_data
dc_parser_get_datetime
dc_parser_get_field
dc_parser_samples_foreach
dc_parser_destroy
reefnet_sensus_parser_set_calibration
reefnet_sensuspro_parser_set_calibration
reefnet_sensusultra_parser_set_calibration
atomics_cobalt_parser_set_calibration
dc_device_open
dc_device_close
dc_device_dump

View File

@ -35,7 +35,7 @@ dc_status_t
liquivision_lynx_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
liquivision_lynx_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
liquivision_lynx_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -117,7 +117,6 @@ struct liquivision_lynx_parser_t {
liquivision_lynx_tank_t tank[NTANKS];
};
static dc_status_t liquivision_lynx_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -125,7 +124,6 @@ static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstrac
static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
sizeof(liquivision_lynx_parser_t),
DC_FAMILY_LIQUIVISION_LYNX,
liquivision_lynx_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -137,7 +135,7 @@ static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
dc_status_t
liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
liquivision_lynx_parser_t *parser = NULL;
@ -145,7 +143,7 @@ liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsign
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (liquivision_lynx_parser_t *) dc_parser_allocate (context, &liquivision_lynx_parser_vtable);
parser = (liquivision_lynx_parser_t *) dc_parser_allocate (context, &liquivision_lynx_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -173,29 +171,6 @@ liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsign
}
static dc_status_t
liquivision_lynx_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
liquivision_lynx_parser_t *parser = (liquivision_lynx_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->ngasmixes = 0;
parser->ntanks = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
}
for (unsigned int i = 0; i < NTANKS; ++i) {
parser->tank[i].id = 0;
parser->tank[i].beginpressure = 0;
parser->tank[i].endpressure = 0;
}
return DC_STATUS_SUCCESS;
}
static dc_status_t
liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -315,6 +290,7 @@ liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -329,6 +305,7 @@ liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
tank->beginpressure = parser->tank[flags].beginpressure / 100.0;
tank->endpressure = parser->tank[flags].endpressure / 100.0;
tank->gasmix = DC_GASMIX_UNKNOWN;
tank->usage = DC_USAGE_NONE;
break;
default:
return DC_STATUS_UNSUPPORTED;
@ -545,29 +522,29 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/100 m).
sample.depth = value / 100.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (1/10 °C).
int temperature = (signed short) array_uint16_le (data + offset);
sample.temperature = temperature / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Gas mix
if (have_gasmix) {
sample.gasmix = gasmix_idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
have_gasmix = 0;
}
// Setpoint (1/10 bar).
if (have_setpoint) {
sample.setpoint = setpoint / 10.0;
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
have_setpoint = 0;
}
@ -577,7 +554,7 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
if (have_pressure & (1 << i)) {
sample.pressure.tank = i;
sample.pressure.value = pressure[i] / 100.0;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
}
have_pressure = 0;
@ -593,7 +570,8 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
sample.deco.depth = 0.0;
}
sample.deco.time = 0;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
have_deco = 0;
}

View File

@ -35,7 +35,7 @@ dc_status_t
mares_darwin_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
dc_status_t
mares_darwin_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
mares_darwin_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -47,7 +47,6 @@ struct mares_darwin_parser_t {
unsigned int samplesize;
};
static dc_status_t mares_darwin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -55,7 +54,6 @@ static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, d
static const dc_parser_vtable_t mares_darwin_parser_vtable = {
sizeof(mares_darwin_parser_t),
DC_FAMILY_MARES_DARWIN,
mares_darwin_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -67,7 +65,7 @@ static const dc_parser_vtable_t mares_darwin_parser_vtable = {
dc_status_t
mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
mares_darwin_parser_t *parser = NULL;
@ -75,7 +73,7 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (mares_darwin_parser_t *) dc_parser_allocate (context, &mares_darwin_parser_vtable);
parser = (mares_darwin_parser_t *) dc_parser_allocate (context, &mares_darwin_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -97,13 +95,6 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
}
static dc_status_t
mares_darwin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -159,6 +150,7 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
}
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
if (mode == NITROX) {
gasmix->oxygen = p[0x0E] / 100.0;
@ -185,6 +177,7 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
tank->gasmix = 0;
tank->beginpressure = array_uint16_be (p + 0x17);
tank->endpressure = array_uint16_be (p + 0x19);
tank->usage = DC_USAGE_NONE;
} else {
return DC_STATUS_UNSUPPORTED;
}
@ -242,17 +235,17 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Surface Time (seconds).
time += 20;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Gas change.
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
@ -262,7 +255,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = ascent;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
// Deco violation
@ -271,7 +264,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
// Deco stop
@ -282,7 +275,8 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
}
sample.deco.time = 0;
sample.deco.depth = 0.0;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
if (parser->samplesize == 3) {
unsigned int type = (time / 20 + 2) % 3;
@ -291,7 +285,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
pressure -= abstract->data[offset + 2];
sample.pressure.tank = 0;
sample.pressure.value = pressure;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
}

View File

@ -21,7 +21,6 @@
#include <string.h> // memcpy, memcmp
#include <stdlib.h> // malloc, free
#include <assert.h> // assert
#include "mares_iconhd.h"
#include "context-private.h"
@ -94,7 +93,6 @@ typedef struct mares_iconhd_device_t {
unsigned char version[140];
unsigned int model;
unsigned int packetsize;
unsigned int splitcommand;
} mares_iconhd_device_t;
static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
@ -179,27 +177,35 @@ mares_iconhd_get_model (mares_iconhd_device_t *device)
static dc_status_t
mares_iconhd_packet (mares_iconhd_device_t *device,
const unsigned char command[], unsigned int csize,
unsigned char cmd,
const unsigned char data[], unsigned int size,
unsigned char answer[], unsigned int asize)
{
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
unsigned int split_csize;
assert (csize >= 2);
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
split_csize = device->splitcommand ? 2 : csize;
// Send the command header to the dive computer.
status = dc_iostream_write (device->iostream, command, split_csize, NULL);
const unsigned char command[2] = {
cmd, cmd ^ XOR,
};
status = dc_iostream_write (device->iostream, command, sizeof(command), NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
// Send the command payload to the dive computer.
if (size) {
status = dc_iostream_write (device->iostream, data, size, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
}
// Receive the header byte.
unsigned char header[1] = {0};
status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
@ -214,15 +220,6 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
return DC_STATUS_PROTOCOL;
}
// Send any remaining command payload to the dive computer.
if (csize > split_csize) {
status = dc_iostream_write (device->iostream, command + split_csize, csize - split_csize, NULL);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
return status;
}
}
// Read the packet.
status = dc_iostream_read (device->iostream, answer, asize, NULL);
if (status != DC_STATUS_SUCCESS) {
@ -248,11 +245,11 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
}
static dc_status_t
mares_iconhd_transfer (mares_iconhd_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
mares_iconhd_transfer (mares_iconhd_device_t *device, unsigned char cmd, const unsigned char data[], unsigned int size, unsigned char answer[], unsigned int asize)
{
unsigned int nretries = 0;
dc_status_t rc = DC_STATUS_SUCCESS;
while ((rc = mares_iconhd_packet (device, command, csize, answer, asize)) != DC_STATUS_SUCCESS) {
while ((rc = mares_iconhd_packet (device, cmd, data, size, answer, asize)) != DC_STATUS_SUCCESS) {
// Automatically discard a corrupted packet,
// and request a new one.
if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT)
@ -287,23 +284,21 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
// Transfer the init packet.
unsigned char rsp_init[16];
unsigned char cmd_init[18] = {
CMD_OBJ_INIT,
CMD_OBJ_INIT ^ XOR,
unsigned char cmd_init[16] = {
0x40,
(index >> 0) & 0xFF,
(index >> 8) & 0xFF,
subindex & 0xFF
};
memset (cmd_init + 6, 0x00, sizeof(cmd_init) - 6);
status = mares_iconhd_transfer (device, cmd_init, sizeof (cmd_init), rsp_init, sizeof (rsp_init));
status = mares_iconhd_transfer (device, CMD_OBJ_INIT, cmd_init, sizeof (cmd_init), rsp_init, sizeof (rsp_init));
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to transfer the init packet.");
return status;
}
// Verify the packet header.
if (memcmp (cmd_init + 3, rsp_init + 1, 3) != 0) {
if (memcmp (cmd_init + 1, rsp_init + 1, 3) != 0) {
ERROR (abstract->context, "Unexpected packet header.");
return DC_STATUS_PROTOCOL;
}
@ -351,8 +346,7 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
// Transfer the segment packet.
unsigned char rsp_segment[1 + 504];
unsigned char cmd_segment[] = {cmd, cmd ^ XOR};
status = mares_iconhd_transfer (device, cmd_segment, sizeof (cmd_segment), rsp_segment, len + 1);
status = mares_iconhd_transfer (device, cmd, NULL, 0, rsp_segment, len + 1);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to transfer the segment packet.");
return status;
@ -419,15 +413,6 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
device->iostream = iostream;
}
/*
* At least the Mares Matrix needs the command to be split into
* base and argument, with a wait for the ACK byte in between.
*
* See commit 59bfb0f3189b ("Add support for the Mares Matrix")
* for details.
*/
device->splitcommand = 1;
// Set the serial communication protocol (115200 8E1).
status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
if (status != DC_STATUS_SUCCESS) {
@ -460,8 +445,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
// Send the version command.
unsigned char command[] = {CMD_VERSION, CMD_VERSION ^ XOR};
status = mares_iconhd_transfer (device, command, sizeof (command),
status = mares_iconhd_transfer (device, CMD_VERSION, NULL, 0,
device->version, sizeof (device->version));
if (status != DC_STATUS_SUCCESS) {
goto error_free_iostream;
@ -473,9 +457,8 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
// Read the size of the flash memory.
unsigned int memsize = 0;
if (device->model == QUAD) {
unsigned char cmd_flash[] = {CMD_FLASHSIZE, CMD_FLASHSIZE ^ XOR};
unsigned char rsp_flash[4] = {0};
status = mares_iconhd_transfer (device, cmd_flash, sizeof (cmd_flash), rsp_flash, sizeof (rsp_flash));
status = mares_iconhd_transfer (device, CMD_FLASHSIZE, NULL, 0, rsp_flash, sizeof (rsp_flash));
if (status != DC_STATUS_SUCCESS) {
WARNING (context, "Failed to read the flash memory size.");
} else {
@ -538,14 +521,6 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
*/
if (device->packetsize > 128)
device->packetsize = 128;
/*
* With BLE, don't wait for ACK before sending the arguments
* to a command.
*
* There is some timing issue that makes that take too long
* and causes the command to be aborted.
*/
device->splitcommand = 0;
}
*out = (dc_device_t *) device;
@ -608,7 +583,7 @@ mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned
len = device->packetsize;
// Read the packet.
unsigned char command[] = {CMD_READ, CMD_READ ^ XOR,
unsigned char command[] = {
(address ) & 0xFF,
(address >> 8) & 0xFF,
(address >> 16) & 0xFF,
@ -617,7 +592,7 @@ mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned
(len >> 8) & 0xFF,
(len >> 16) & 0xFF,
(len >> 24) & 0xFF};
rc = mares_iconhd_transfer (device, command, sizeof (command), data, len);
rc = mares_iconhd_transfer (device, CMD_READ, command, sizeof (command), data, len);
if (rc != DC_STATUS_SUCCESS)
return rc;

View File

@ -35,7 +35,7 @@ dc_status_t
mares_iconhd_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
mares_iconhd_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
mares_iconhd_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -267,7 +267,6 @@ static const mares_iconhd_layout_t horizon = {
0x54 + 8, /* tanks */
};
static dc_status_t mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -275,7 +274,6 @@ static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, d
static const dc_parser_vtable_t mares_iconhd_parser_vtable = {
sizeof(mares_iconhd_parser_t),
DC_FAMILY_MARES_ICONHD,
mares_iconhd_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -404,12 +402,12 @@ mares_iconhd_cache (mares_iconhd_parser_t *parser)
unsigned int samplerate = 0;
if (parser->model == SMARTAPNEA) {
unsigned int idx = (settings & 0x0600) >> 9;
interval = 1;
samplerate = 1 << idx;
interval = 1000 / samplerate;
} else {
const unsigned int intervals[] = {1, 5, 10, 20};
unsigned int idx = (settings & 0x0C00) >> 10;
interval = intervals[idx];
interval = intervals[idx] * 1000;
samplerate = 1;
}
@ -628,7 +626,7 @@ mares_genius_cache (mares_iconhd_parser_t *parser)
parser->headersize = headersize;
parser->settings = settings;
parser->surftime = surftime * 60;
parser->interval = 5;
parser->interval = 5000;
parser->samplerate = 1;
parser->ntanks = ntanks;
parser->ngasmixes = ngasmixes;
@ -659,7 +657,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
}
dc_status_t
mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
{
mares_iconhd_parser_t *parser = NULL;
@ -667,7 +665,7 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (mares_iconhd_parser_t *) dc_parser_allocate (context, &mares_iconhd_parser_vtable);
parser = (mares_iconhd_parser_t *) dc_parser_allocate (context, &mares_iconhd_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -705,41 +703,6 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
return DC_STATUS_SUCCESS;
}
static dc_status_t
mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->logformat = 0;
parser->mode = (parser->model == GENIUS || parser->model == HORIZON) ? GENIUS_AIR : ICONHD_AIR;
parser->nsamples = 0;
parser->samplesize = 0;
parser->headersize = 0;
parser->settings = 0;
parser->surftime = 0;
parser->interval = 0;
parser->samplerate = 0;
parser->ntanks = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
}
for (unsigned int i = 0; i < NTANKS; ++i) {
parser->tank[i].volume = 0;
parser->tank[i].workpressure = 0;
parser->tank[i].beginpressure = 0;
parser->tank[i].endpressure = 0;
}
parser->layout = NULL;
return DC_STATUS_SUCCESS;
}
static dc_status_t
mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -827,7 +790,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
if (parser->layout->divetime != UNSUPPORTED) {
*((unsigned int *) value) = array_uint16_le (p + parser->layout->divetime);
} else {
*((unsigned int *) value) = parser->nsamples * parser->interval - parser->surftime;
*((unsigned int *) value) = parser->nsamples * parser->interval / 1000 - parser->surftime;
}
break;
case DC_FIELD_MAXDEPTH:
@ -837,6 +800,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -864,6 +828,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
} else {
tank->gasmix = DC_GASMIX_UNKNOWN;
}
tank->usage = DC_USAGE_NONE;
break;
case DC_FIELD_ATMOSPHERIC:
*((double *) value) = array_uint16_le (p + parser->layout->atmospheric) / (1000.0 * parser->layout->atmospheric_divisor);
@ -981,14 +946,6 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
const unsigned char *data = abstract->data;
if (parser->samplerate > 1) {
// The Smart Apnea supports multiple samples per second
// (e.g. 2, 4 or 8). Since our smallest unit of time is one
// second, we can't represent this, and the extra samples
// will get dropped.
WARNING(abstract->context, "Multiple samples per second are not supported!");
}
// Previous gas mix - initialize with impossible value
unsigned int gasmix_previous = 0xFFFFFFFF;
@ -1039,29 +996,30 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
unsigned int surftime = array_uint16_le (data + offset + 4);
// Surface Time (seconds).
time += surftime;
time += surftime * 1000;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Surface Depth (0 m).
sample.depth = 0.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += parser->samplesize;
nsamples++;
for (unsigned int i = 0; i < divetime; ++i) {
unsigned int count = divetime * parser->samplerate;
for (unsigned int i = 0; i < count; ++i) {
// Time (seconds).
time += parser->interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
unsigned int depth = array_uint16_le (data + offset);
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 2 * parser->samplerate;
offset += 2;
}
} else if (parser->model != GENIUS && parser->model != HORIZON && parser->mode == ICONHD_FREEDIVE) {
unsigned int maxdepth = array_uint16_le (data + offset + 0);
@ -1069,22 +1027,22 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
unsigned int surftime = array_uint16_le (data + offset + 4);
// Surface Time (seconds).
time += surftime;
time += surftime * 1000;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Surface Depth (0 m).
sample.depth = 0.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Dive Time (seconds).
time += divetime;
time += divetime * 1000;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Maximum Depth (1/10 m).
sample.depth = maxdepth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += parser->samplesize;
nsamples++;
@ -1142,15 +1100,15 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Time (seconds).
time += parser->interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (1/10 °C).
sample.temperature = temperature / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Current gas mix
if (parser->ngasmixes > 0) {
@ -1160,7 +1118,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
}
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
}
@ -1171,7 +1129,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = bookmark;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
if (parser->model == GENIUS || parser->model == HORIZON) {
@ -1184,7 +1142,8 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.deco.depth = 0.0;
}
sample.deco.time = decotime * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = tts;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
// Alarms
for (unsigned int v = alarms, i = 0; v; v >>= 1, ++i) {
@ -1210,7 +1169,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
}
}
@ -1231,7 +1190,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
if (gasmix < parser->ntanks) {
sample.pressure.tank = gasmix;
sample.pressure.value = pressure / 100.0;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
} else if (pressure != 0) {
WARNING (abstract->context, "Invalid tank with non-zero pressure.");
}

View File

@ -35,7 +35,7 @@ dc_status_t
mares_nemo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
mares_nemo_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
mares_nemo_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -59,7 +59,6 @@ struct mares_nemo_parser_t {
unsigned int extra;
};
static dc_status_t mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t mares_nemo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -67,7 +66,6 @@ static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_
static const dc_parser_vtable_t mares_nemo_parser_vtable = {
sizeof(mares_nemo_parser_t),
DC_FAMILY_MARES_NEMO,
mares_nemo_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -79,15 +77,16 @@ static const dc_parser_vtable_t mares_nemo_parser_vtable = {
dc_status_t
mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
dc_status_t status = DC_STATUS_SUCCESS;
mares_nemo_parser_t *parser = NULL;
if (out == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (mares_nemo_parser_t *) dc_parser_allocate (context, &mares_nemo_parser_vtable);
parser = (mares_nemo_parser_t *) dc_parser_allocate (context, &mares_nemo_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -98,70 +97,42 @@ mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
if (model == NEMOWIDE || model == NEMOAIR || model == PUCK || model == PUCKAIR)
freedive = GAUGE;
// Set the default values.
parser->model = model;
parser->freedive = freedive;
parser->mode = AIR;
parser->length = 0;
parser->sample_count = 0;
parser->sample_size = 0;
parser->header = 0;
parser->extra = 0;
*out = (dc_parser_t*) parser;
return DC_STATUS_SUCCESS;
}
static dc_status_t
mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
mares_nemo_parser_t *parser = (mares_nemo_parser_t *) abstract;
// Clear the previous state.
parser->base.data = NULL;
parser->base.size = 0;
parser->mode = AIR;
parser->length = 0;
parser->sample_count = 0;
parser->sample_size = 0;
parser->header = 0;
parser->extra = 0;
if (size == 0)
return DC_STATUS_SUCCESS;
if (size < 2 + 3)
return DC_STATUS_DATAFORMAT;
if (size < 2 + 3) {
status = DC_STATUS_DATAFORMAT;
goto error_free;
}
unsigned int length = array_uint16_le (data);
if (length > size)
return DC_STATUS_DATAFORMAT;
if (length > size) {
status = DC_STATUS_DATAFORMAT;
goto error_free;
}
unsigned int extra = 0;
const unsigned char marker[3] = {0xAA, 0xBB, 0xCC};
if (memcmp (data + length - 3, marker, sizeof (marker)) == 0) {
if (parser->model == PUCKAIR)
if (model == PUCKAIR)
extra = 7;
else
extra = 12;
}
if (length < 2 + extra + 3)
return DC_STATUS_DATAFORMAT;
if (length < 2 + extra + 3) {
status = DC_STATUS_DATAFORMAT;
goto error_free;
}
unsigned int mode = data[length - extra - 1];
unsigned int header_size = 53;
unsigned int sample_size = 2;
if (extra) {
if (parser->model == PUCKAIR)
if (model == PUCKAIR)
sample_size = 3;
else
sample_size = 5;
}
if (mode == parser->freedive) {
if (mode == freedive) {
header_size = 28;
sample_size = 6;
}
@ -169,12 +140,14 @@ mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un
unsigned int nsamples = array_uint16_le (data + length - extra - 3);
unsigned int nbytes = 2 + nsamples * sample_size + header_size + extra;
if (length != nbytes)
return DC_STATUS_DATAFORMAT;
if (length != nbytes) {
status = DC_STATUS_DATAFORMAT;
goto error_free;
}
// Store the new state.
parser->base.data = data;
parser->base.size = size;
// Set the default values.
parser->model = model;
parser->freedive = freedive;
parser->mode = mode;
parser->length = length;
parser->sample_count = nsamples;
@ -182,7 +155,13 @@ mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un
parser->header = header_size;
parser->extra = extra;
*out = (dc_parser_t*) parser;
return DC_STATUS_SUCCESS;
error_free:
dc_parser_deallocate ((dc_parser_t *) parser);
return status;
}
@ -251,6 +230,7 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
}
gasmix->helium = 0.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
gasmix->usage = DC_USAGE_NONE;
break;
case DC_FIELD_TANK_COUNT:
if (parser->extra)
@ -290,6 +270,7 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
} else {
tank->gasmix = DC_GASMIX_UNKNOWN;
}
tank->usage = DC_USAGE_NONE;
break;
case DC_FIELD_TEMPERATURE_MINIMUM:
*((double *) value) = (signed char) p[53 - 11];
@ -382,17 +363,17 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
// Time (seconds).
time += 20;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Gas change.
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
@ -402,7 +383,7 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = ascent;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
// Deco violation
@ -411,7 +392,7 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
// Deco stop
@ -422,20 +403,21 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
}
sample.deco.time = 0;
sample.deco.depth = 0.0;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
// Pressure (1 bar).
if (parser->sample_size == 3) {
sample.pressure.tank = 0;
sample.pressure.value = data[idx + 2];
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
} else if (parser->sample_size == 5) {
unsigned int type = (time / 20) % 3;
if (type == 0) {
pressure -= data[idx + 2] * 100;
sample.pressure.tank = 0;
sample.pressure.value = pressure / 100.0;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
}
}
@ -459,12 +441,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
// Surface Time (seconds).
time += surftime;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Surface Depth (0 m).
sample.depth = 0.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
if (profiles) {
// Get the freedive sample interval for this model.
@ -500,12 +482,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
time += interval;
if (time > maxtime)
time = maxtime; // Adjust the last sample.
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
}
// Verify that the number of samples in the profile data
@ -519,12 +501,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
} else {
// Dive Time (seconds).
time += divetime;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Maximum Depth (1/10 m).
sample.depth = maxdepth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
}
}
}

View File

@ -35,7 +35,7 @@ dc_status_t
mclean_extreme_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
mclean_extreme_parser_create (dc_parser_t **parser, dc_context_t *context);
mclean_extreme_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -58,7 +58,6 @@ struct mclean_extreme_parser_t {
unsigned int gasmix[NGASMIXES];
};
static dc_status_t mclean_extreme_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -66,7 +65,6 @@ static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract,
static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
sizeof(mclean_extreme_parser_t),
DC_FAMILY_MCLEAN_EXTREME,
mclean_extreme_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -77,7 +75,7 @@ static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
};
dc_status_t
mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
mclean_extreme_parser_t *parser = NULL;
@ -86,7 +84,7 @@ mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
}
// Allocate memory.
parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable);
parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable, data, size);
if (parser == NULL) {
ERROR(context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -104,21 +102,6 @@ mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
}
static dc_status_t
mclean_extreme_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
mclean_extreme_parser_t *parser = (mclean_extreme_parser_t *)abstract;
// Reset the cache.
parser->cached = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i] = INVALID;
}
return DC_STATUS_SUCCESS;
}
static dc_status_t
mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -221,6 +204,7 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns
*((unsigned int *)value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.01 * abstract->data[0x0001 + 1 + 2 * parser->gasmix[flags]];
gasmix->oxygen = 0.01 * abstract->data[0x0001 + 0 + 2 * parser->gasmix[flags]];
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -269,14 +253,14 @@ mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_
const unsigned int setpoint = abstract->data[0x0013 + sp_index];
time += interval;
sample.time = time;
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
sample.depth = 0.1 * depth;
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
sample.temperature = temperature;
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
if (gasmix_id != gasmix_previous) {
// Find the gasmix in the list.
@ -298,13 +282,13 @@ mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_
}
sample.gasmix = idx;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix_id;
}
if (ccr) {
sample.setpoint = 0.01 * setpoint;
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
}
offset += SZ_SAMPLE;

View File

@ -339,7 +339,7 @@ static const oceanic_common_layout_t oceanic_reactpro_layout = {
0x0600, /* rb_logbook_end */
8, /* rb_logbook_entry_size */
0x0600, /* rb_profile_begin */
0xFFF0, /* rb_profile_end */
0xFE00, /* rb_profile_end */
1, /* pt_mode_global */
1, /* pt_mode_logbook */
0, /* pt_mode_serial */

View File

@ -37,7 +37,7 @@ dc_status_t
oceanic_atom2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
dc_status_t
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -62,7 +62,6 @@ struct oceanic_atom2_parser_t {
double maxdepth;
};
static dc_status_t oceanic_atom2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -70,7 +69,6 @@ static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract,
static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
sizeof(oceanic_atom2_parser_t),
DC_FAMILY_OCEANIC_ATOM2,
oceanic_atom2_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -82,7 +80,7 @@ static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
dc_status_t
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
{
oceanic_atom2_parser_t *parser = NULL;
@ -90,7 +88,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (oceanic_atom2_parser_t *) dc_parser_allocate (context, &oceanic_atom2_parser_vtable);
parser = (oceanic_atom2_parser_t *) dc_parser_allocate (context, &oceanic_atom2_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -157,28 +155,6 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
}
static dc_status_t
oceanic_atom2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->header = 0;
parser->footer = 0;
parser->mode = NORMAL;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->oxygen[i] = 0;
parser->helium[i] = 0;
}
parser->divetime = 0;
parser->maxdepth = 0.0;
return DC_STATUS_SUCCESS;
}
static dc_status_t
oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -524,6 +500,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->oxygen = parser->oxygen[flags] / 100.0;
gasmix->helium = parser->helium[flags] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -605,7 +582,7 @@ oceanic_atom2_parser_vendor (oceanic_atom2_parser_t *parser, const unsigned char
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_ATOM2;
sample.vendor.size = length;
sample.vendor.data = data + offset;
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
offset += length;
}
@ -627,8 +604,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
unsigned int extratime = 0;
unsigned int time = 0;
unsigned int interval = 1;
unsigned int samplerate = 1;
unsigned int interval = 1000;
if (parser->mode != FREEDIVE) {
unsigned int offset = 0x17;
if (parser->model == A300CS || parser->model == VTX ||
@ -636,21 +612,13 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
parser->model == PROPLUSX || parser->model == I770R ||
parser->model == SAGE || parser->model == BEACON)
offset = 0x1f;
const unsigned int intervals[] = {2, 15, 30, 60};
const unsigned int intervals[] = {2000, 15000, 30000, 60000};
unsigned int idx = data[offset] & 0x03;
interval = intervals[idx];
} else if (parser->model == F11A || parser->model == F11B) {
const unsigned int intervals[] = {1, 1, 1, 2};
const unsigned int samplerates[] = {4, 2, 1, 1};
const unsigned int intervals[] = {250, 500, 1000, 2000};
unsigned int idx = data[0x29] & 0x03;
interval = intervals[idx];
samplerate = samplerates[idx];
if (samplerate > 1) {
// Some models supports multiple samples per second.
// Since our smallest unit of time is one second, we can't
// represent this, and the extra samples will get dropped.
WARNING(abstract->context, "Multiple samples per second are not supported!");
}
}
unsigned int samplesize = PAGESIZE / 2;
@ -771,14 +739,14 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
// The surface time is not always a nice multiple of the samplerate.
// The number of inserted surface samples is therefore rounded down
// to keep the timestamps aligned at multiples of the samplerate.
unsigned int surftime = 60 * bcd2dec (data[offset + 1]) + bcd2dec (data[offset + 2]);
unsigned int surftime = (60 * bcd2dec (data[offset + 1]) + bcd2dec (data[offset + 2])) * 1000;
unsigned int nsamples = surftime / interval;
for (unsigned int i = 0; i < nsamples; ++i) {
// Time
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Vendor specific data
if (i == 0) {
@ -790,25 +758,18 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
// Depth
sample.depth = 0.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
complete = 1;
}
extratime += surftime;
} else {
// Skip the extra samples.
if ((count % samplerate) != 0) {
offset += samplesize;
count++;
continue;
}
// Time.
if (parser->model == I450T || parser->model == I470TC) {
unsigned int minute = bcd2dec(data[offset + 0]);
unsigned int hour = bcd2dec(data[offset + 1] & 0x0F);
unsigned int second = bcd2dec(data[offset + 2]);
unsigned int timestamp = (hour * 3600) + (minute * 60 ) + second + extratime;
unsigned int timestamp = ((hour * 3600) + (minute * 60 ) + second) * 1000 + extratime;
if (timestamp < time) {
ERROR (abstract->context, "Timestamp moved backwards.");
return DC_STATUS_DATAFORMAT;
@ -822,7 +783,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
time += interval;
}
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Vendor specific data
oceanic_atom2_parser_vendor (parser,
@ -884,7 +845,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
temperature += (data[offset + 7] & 0x0C) >> 2;
}
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
// Tank Pressure (psi)
@ -912,7 +873,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
pressure -= data[offset + 1];
sample.pressure.tank = tank;
sample.pressure.value = pressure * PSI / BAR;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
// Depth (1/16 ft)
@ -935,7 +896,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
else
depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF;
sample.depth = depth / 16.0 * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Gas mix
unsigned int have_gasmix = 0;
@ -950,7 +911,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = gasmix - 1;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
gasmix_previous = gasmix;
}
@ -999,7 +960,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
sample.deco.depth = 0.0;
}
sample.deco.time = decotime * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
}
unsigned int have_rbt = 0;
@ -1022,7 +984,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
}
if (have_rbt) {
sample.rbt = rbt;
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
if (callback) callback (DC_SAMPLE_RBT, &sample, userdata);
}
// Bookmarks
@ -1037,7 +999,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
count++;

View File

@ -37,7 +37,7 @@ dc_status_t
oceanic_veo250_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
oceanic_veo250_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
oceanic_veo250_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -42,7 +42,6 @@ struct oceanic_veo250_parser_t {
double maxdepth;
};
static dc_status_t oceanic_veo250_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -50,7 +49,6 @@ static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract,
static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
sizeof(oceanic_veo250_parser_t),
DC_FAMILY_OCEANIC_VEO250,
oceanic_veo250_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -62,7 +60,7 @@ static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
dc_status_t
oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
oceanic_veo250_parser_t *parser = NULL;
@ -70,7 +68,7 @@ oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (oceanic_veo250_parser_t *) dc_parser_allocate (context, &oceanic_veo250_parser_vtable);
parser = (oceanic_veo250_parser_t *) dc_parser_allocate (context, &oceanic_veo250_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -88,20 +86,6 @@ oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
}
static dc_status_t
oceanic_veo250_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
oceanic_veo250_parser_t *parser = (oceanic_veo250_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0.0;
return DC_STATUS_SUCCESS;
}
static dc_status_t
oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -170,6 +154,7 @@ oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
*((unsigned int *) value) = 1;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
if (data[footer + 6])
gasmix->oxygen = data[footer + 6] / 100.0;
@ -230,19 +215,19 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
// Time.
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Vendor specific data
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VEO250;
sample.vendor.size = PAGESIZE / 2;
sample.vendor.data = data + offset;
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
// Depth (ft)
unsigned int depth = data[offset + 2];
sample.depth = depth * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (°F)
unsigned int temperature;
@ -253,7 +238,7 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
temperature = data[offset + 7];
}
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// NDL / Deco
unsigned int have_deco = 0;
@ -277,7 +262,8 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
sample.deco.depth = 0.0;
}
sample.deco.time = decotime * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
}
offset += PAGESIZE / 2;

View File

@ -37,7 +37,7 @@ dc_status_t
oceanic_vtpro_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
dc_status_t
oceanic_vtpro_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
oceanic_vtpro_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
#ifdef __cplusplus
}

View File

@ -42,7 +42,6 @@ struct oceanic_vtpro_parser_t {
double maxdepth;
};
static dc_status_t oceanic_vtpro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -50,7 +49,6 @@ static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract,
static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
sizeof(oceanic_vtpro_parser_t),
DC_FAMILY_OCEANIC_VTPRO,
oceanic_vtpro_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -62,7 +60,7 @@ static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
dc_status_t
oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
{
oceanic_vtpro_parser_t *parser = NULL;
@ -70,7 +68,7 @@ oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (oceanic_vtpro_parser_t *) dc_parser_allocate (context, &oceanic_vtpro_parser_vtable);
parser = (oceanic_vtpro_parser_t *) dc_parser_allocate (context, &oceanic_vtpro_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -88,20 +86,6 @@ oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
}
static dc_status_t
oceanic_vtpro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
oceanic_vtpro_parser_t *parser = (oceanic_vtpro_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0.0;
return DC_STATUS_SUCCESS;
}
static dc_status_t
oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -200,6 +184,7 @@ oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
*((unsigned int *) value) = 1;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
if (oxygen)
gasmix->oxygen = oxygen / 100.0;
@ -220,6 +205,7 @@ oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
tank->gasmix = flags;
tank->beginpressure = beginpressure * 2 * PSI / BAR;
tank->endpressure = endpressure * 2 * PSI / BAR;
tank->usage = DC_USAGE_NONE;
break;
default:
return DC_STATUS_UNSUPPORTED;
@ -331,14 +317,14 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
time = timestamp * 60 + (i + 1) * interval;
else
time = timestamp * 60 + (i + 1) * 60.0 / count + 0.5;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Vendor specific data
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VTPRO;
sample.vendor.size = PAGESIZE / 2;
sample.vendor.data = data + offset;
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
// Depth (ft)
unsigned int depth = 0;
@ -348,7 +334,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
depth = data[offset + 3];
}
sample.depth = depth * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (°F)
unsigned int temperature = 0;
@ -358,7 +344,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
temperature = data[offset + 6];
}
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// NDL / Deco
if (parser->model != AERIS500AI) {
@ -372,7 +358,8 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
sample.deco.depth = 0.0;
}
sample.deco.time = decotime * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
}
offset += PAGESIZE / 2;

View File

@ -36,7 +36,7 @@ dc_status_t
oceans_s1_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
oceans_s1_parser_create (dc_parser_t **parser, dc_context_t *context);
oceans_s1_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -58,7 +58,6 @@ struct oceans_s1_parser_t {
unsigned int divetime;
};
static dc_status_t oceans_s1_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t oceans_s1_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t oceans_s1_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -66,7 +65,6 @@ static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sa
static const dc_parser_vtable_t oceans_s1_parser_vtable = {
sizeof(oceans_s1_parser_t),
DC_FAMILY_OCEANS_S1,
oceans_s1_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -77,7 +75,7 @@ static const dc_parser_vtable_t oceans_s1_parser_vtable = {
};
dc_status_t
oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
oceans_s1_parser_t *parser = NULL;
@ -85,7 +83,7 @@ oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (oceans_s1_parser_t *) dc_parser_allocate (context, &oceans_s1_parser_vtable);
parser = (oceans_s1_parser_t *) dc_parser_allocate (context, &oceans_s1_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -105,23 +103,6 @@ oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
}
static dc_status_t
oceans_s1_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
oceans_s1_parser_t *parser = (oceans_s1_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->timestamp = 0;
parser->number = 0;
parser->divemode = 0;
parser->oxygen = 0;
parser->maxdepth = 0;
parser->divetime = 0;
return DC_STATUS_SUCCESS;
}
static dc_status_t
oceans_s1_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -166,6 +147,7 @@ oceans_s1_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
*((unsigned int *) value) = parser->divemode == SCUBA;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
gasmix->oxygen = parser->oxygen / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -249,19 +231,19 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
unsigned int nsamples = seconds / interval;
for (unsigned int i = 0; i < nsamples; ++i) {
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
sample.depth = 0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
}
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
sample.depth = depth / 100.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
} else if (strncmp(line, "enddive", 7) == 0) {
if (sscanf(line, "enddive %u,%u", &maxdepth, &divetime) != 2) {
ERROR (parser->base.context, "Failed to parse the line '%s'.", line);
@ -280,14 +262,14 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
}
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
sample.depth = depth / 100.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
sample.temperature = temperature;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
if (events & EVENT_DECO_STOP) {
sample.deco.type = DC_DECO_DECOSTOP;
@ -298,7 +280,8 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
}
sample.deco.depth = 0.0;
sample.deco.time = 0;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
}
}

View File

@ -41,7 +41,7 @@ typedef struct dc_parser_vtable_t dc_parser_vtable_t;
struct dc_parser_t {
const dc_parser_vtable_t *vtable;
dc_context_t *context;
const unsigned char *data;
unsigned char *data;
unsigned int size;
};
@ -50,8 +50,6 @@ struct dc_parser_vtable_t {
dc_family_t type;
dc_status_t (*set_data) (dc_parser_t *parser, const unsigned char *data, unsigned int size);
dc_status_t (*set_clock) (dc_parser_t *parser, unsigned int devtime, dc_ticks_t systime);
dc_status_t (*set_atmospheric) (dc_parser_t *parser, double atmospheric);
@ -68,7 +66,7 @@ struct dc_parser_vtable_t {
};
dc_parser_t *
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable);
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, const unsigned char data[], size_t size);
void
dc_parser_deallocate (dc_parser_t *parser);
@ -84,7 +82,7 @@ typedef struct sample_statistics_t {
#define SAMPLE_STATISTICS_INITIALIZER {0, 0.0}
void
sample_statistics_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata);
sample_statistics_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata);
#ifdef __cplusplus
}

View File

@ -20,6 +20,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "suunto_d9.h"
@ -75,7 +76,7 @@
#define REACTPROWHITE 0x4354
static dc_status_t
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t family, unsigned int model, unsigned int serial, unsigned int devtime, dc_ticks_t systime)
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, dc_family_t family, unsigned int model, unsigned int serial)
{
dc_status_t rc = DC_STATUS_SUCCESS;
dc_parser_t *parser = NULL;
@ -85,126 +86,126 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
switch (family) {
case DC_FAMILY_SUUNTO_SOLUTION:
rc = suunto_solution_parser_create (&parser, context);
rc = suunto_solution_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_SUUNTO_EON:
rc = suunto_eon_parser_create (&parser, context, 0);
rc = suunto_eon_parser_create (&parser, context, data, size, 0);
break;
case DC_FAMILY_SUUNTO_VYPER:
if (model == 0x01)
rc = suunto_eon_parser_create (&parser, context, 1);
rc = suunto_eon_parser_create (&parser, context, data, size, 1);
else
rc = suunto_vyper_parser_create (&parser, context, serial);
rc = suunto_vyper_parser_create (&parser, context, data, size, serial);
break;
case DC_FAMILY_SUUNTO_VYPER2:
case DC_FAMILY_SUUNTO_D9:
rc = suunto_d9_parser_create (&parser, context, model, serial);
rc = suunto_d9_parser_create (&parser, context, data, size, model, serial);
break;
case DC_FAMILY_SUUNTO_EONSTEEL:
rc = suunto_eonsteel_parser_create(&parser, context, model);
rc = suunto_eonsteel_parser_create(&parser, context, data, size, model);
break;
case DC_FAMILY_UWATEC_ALADIN:
case DC_FAMILY_UWATEC_MEMOMOUSE:
rc = uwatec_memomouse_parser_create (&parser, context, devtime, systime);
rc = uwatec_memomouse_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_UWATEC_SMART:
rc = uwatec_smart_parser_create (&parser, context, model);
rc = uwatec_smart_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_REEFNET_SENSUS:
rc = reefnet_sensus_parser_create (&parser, context, devtime, systime);
rc = reefnet_sensus_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_REEFNET_SENSUSPRO:
rc = reefnet_sensuspro_parser_create (&parser, context, devtime, systime);
rc = reefnet_sensuspro_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_REEFNET_SENSUSULTRA:
rc = reefnet_sensusultra_parser_create (&parser, context, devtime, systime);
rc = reefnet_sensusultra_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_OCEANIC_VTPRO:
rc = oceanic_vtpro_parser_create (&parser, context, model);
rc = oceanic_vtpro_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_OCEANIC_VEO250:
rc = oceanic_veo250_parser_create (&parser, context, model);
rc = oceanic_veo250_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_OCEANIC_ATOM2:
if (model == REACTPROWHITE)
rc = oceanic_veo250_parser_create (&parser, context, model);
rc = oceanic_veo250_parser_create (&parser, context, data, size, model);
else
rc = oceanic_atom2_parser_create (&parser, context, model, serial);
rc = oceanic_atom2_parser_create (&parser, context, data, size, model, serial);
break;
case DC_FAMILY_MARES_NEMO:
case DC_FAMILY_MARES_PUCK:
rc = mares_nemo_parser_create (&parser, context, model);
rc = mares_nemo_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_MARES_DARWIN:
rc = mares_darwin_parser_create (&parser, context, model);
rc = mares_darwin_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_MARES_ICONHD:
rc = mares_iconhd_parser_create (&parser, context, model, serial);
rc = mares_iconhd_parser_create (&parser, context, data, size, model, serial);
break;
case DC_FAMILY_HW_OSTC:
rc = hw_ostc_parser_create (&parser, context, serial);
rc = hw_ostc_parser_create (&parser, context, data, size, serial);
break;
case DC_FAMILY_HW_FROG:
case DC_FAMILY_HW_OSTC3:
rc = hw_ostc3_parser_create (&parser, context, serial, model);
rc = hw_ostc3_parser_create (&parser, context, data, size, model, serial);
break;
case DC_FAMILY_CRESSI_EDY:
case DC_FAMILY_ZEAGLE_N2ITION3:
rc = cressi_edy_parser_create (&parser, context, model);
rc = cressi_edy_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_CRESSI_LEONARDO:
rc = cressi_leonardo_parser_create (&parser, context, model);
rc = cressi_leonardo_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_CRESSI_GOA:
rc = cressi_goa_parser_create (&parser, context, model);
rc = cressi_goa_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_ATOMICS_COBALT:
rc = atomics_cobalt_parser_create (&parser, context);
rc = atomics_cobalt_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_SHEARWATER_PREDATOR:
rc = shearwater_predator_parser_create (&parser, context, model, serial);
rc = shearwater_predator_parser_create (&parser, context, data, size, model, serial);
break;
case DC_FAMILY_SHEARWATER_PETREL:
rc = shearwater_petrel_parser_create (&parser, context, model, serial);
rc = shearwater_petrel_parser_create (&parser, context, data, size, model, serial);
break;
case DC_FAMILY_DIVERITE_NITEKQ:
rc = diverite_nitekq_parser_create (&parser, context);
rc = diverite_nitekq_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_CITIZEN_AQUALAND:
rc = citizen_aqualand_parser_create (&parser, context);
rc = citizen_aqualand_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_DIVESYSTEM_IDIVE:
rc = divesystem_idive_parser_create (&parser, context, model);
rc = divesystem_idive_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_COCHRAN_COMMANDER:
rc = cochran_commander_parser_create (&parser, context, model);
rc = cochran_commander_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_TECDIVING_DIVECOMPUTEREU:
rc = tecdiving_divecomputereu_parser_create (&parser, context);
rc = tecdiving_divecomputereu_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_MCLEAN_EXTREME:
rc = mclean_extreme_parser_create (&parser, context);
rc = mclean_extreme_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_LIQUIVISION_LYNX:
rc = liquivision_lynx_parser_create (&parser, context, model);
rc = liquivision_lynx_parser_create (&parser, context, data, size, model);
break;
case DC_FAMILY_SPORASUB_SP2:
rc = sporasub_sp2_parser_create (&parser, context);
rc = sporasub_sp2_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_DEEPSIX_EXCURSION:
rc = deepsix_excursion_parser_create (&parser, context);
rc = deepsix_excursion_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_SEAC_SCREEN:
rc = seac_screen_parser_create (&parser, context);
rc = seac_screen_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_DEEPBLU_COSMIQ:
rc = deepblu_cosmiq_parser_create (&parser, context);
rc = deepblu_cosmiq_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_OCEANS_S1:
rc = oceans_s1_parser_create (&parser, context);
rc = oceans_s1_parser_create (&parser, context, data, size);
break;
case DC_FAMILY_DIVESOFT_FREEDOM:
rc = divesoft_freedom_parser_create (&parser, context);
rc = divesoft_freedom_parser_create (&parser, context, data, size);
break;
default:
return DC_STATUS_INVALIDARGS;
@ -221,30 +222,42 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
}
dc_status_t
dc_parser_new (dc_parser_t **out, dc_device_t *device)
dc_parser_new (dc_parser_t **out, dc_device_t *device, const unsigned char data[], size_t size)
{
dc_status_t status = DC_STATUS_SUCCESS;
dc_parser_t *parser = NULL;
if (device == NULL)
return DC_STATUS_INVALIDARGS;
return dc_parser_new_internal (out, device->context,
dc_device_get_type (device),
device->devinfo.model,
device->devinfo.serial,
device->clock.devtime, device->clock.systime);
status = dc_parser_new_internal (&parser, device->context, data, size,
dc_device_get_type (device), device->devinfo.model, 0);
if (status != DC_STATUS_SUCCESS)
goto error_exit;
status = dc_parser_set_clock (parser, device->clock.devtime, device->clock.systime);
if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED)
goto error_free;
*out = parser;
return DC_STATUS_SUCCESS;
error_free:
dc_parser_deallocate (parser);
error_exit:
return status;
}
dc_status_t
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime)
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, const unsigned char data[], size_t size)
{
return dc_parser_new_internal (out, context,
dc_descriptor_get_type (descriptor),
dc_descriptor_get_model (descriptor),
0,
devtime, systime);
return dc_parser_new_internal (out, context, data, size,
dc_descriptor_get_type (descriptor), dc_descriptor_get_model (descriptor), 0);
}
dc_parser_t *
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable)
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, const unsigned char data[], size_t size)
{
dc_parser_t *parser = NULL;
@ -261,15 +274,34 @@ dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable)
// Initialize the base class.
parser->vtable = vtable;
parser->context = context;
if (size) {
// Allocate memory for the data.
parser->data = malloc (size);
if (parser->data == NULL) {
ERROR (context, "Failed to allocate memory.");
free (parser);
return NULL;
}
// Copy the data.
memcpy (parser->data, data, size);
parser->size = size;
} else {
parser->data = NULL;
parser->size = 0;
}
return parser;
}
void
dc_parser_deallocate (dc_parser_t *parser)
{
if (parser == NULL)
return;
free (parser->data);
free (parser);
}
@ -332,22 +364,6 @@ dc_parser_set_density (dc_parser_t *parser, double density)
}
dc_status_t
dc_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size)
{
if (parser == NULL)
return DC_STATUS_UNSUPPORTED;
if (parser->vtable->set_data == NULL)
return DC_STATUS_UNSUPPORTED;
parser->data = data;
parser->size = size;
return parser->vtable->set_data (parser, data, size);
}
dc_status_t
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime)
{
@ -405,17 +421,17 @@ dc_parser_destroy (dc_parser_t *parser)
void
sample_statistics_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
sample_statistics_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata)
{
sample_statistics_t *statistics = (sample_statistics_t *) userdata;
switch (type) {
case DC_SAMPLE_TIME:
statistics->divetime = value.time;
statistics->divetime = value->time / 1000;
break;
case DC_SAMPLE_DEPTH:
if (statistics->maxdepth < value.depth)
statistics->maxdepth = value.depth;
if (statistics->maxdepth < value->depth)
statistics->maxdepth = value->depth;
break;
default:
break;

View File

@ -36,7 +36,7 @@ dc_status_t
reefnet_sensus_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
reefnet_sensus_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
reefnet_sensus_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -48,7 +48,6 @@ struct reefnet_sensus_parser_t {
unsigned int maxdepth;
};
static dc_status_t reefnet_sensus_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
static dc_status_t reefnet_sensus_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
static dc_status_t reefnet_sensus_parser_set_density (dc_parser_t *abstract, double density);
@ -59,7 +58,6 @@ static dc_status_t reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract,
static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
sizeof(reefnet_sensus_parser_t),
DC_FAMILY_REEFNET_SENSUS,
reefnet_sensus_parser_set_data, /* set_data */
reefnet_sensus_parser_set_clock, /* set_clock */
reefnet_sensus_parser_set_atmospheric, /* set_atmospheric */
reefnet_sensus_parser_set_density, /* set_density */
@ -71,7 +69,7 @@ static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
dc_status_t
reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
reefnet_sensus_parser_t *parser = NULL;
@ -79,7 +77,7 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (reefnet_sensus_parser_t *) dc_parser_allocate (context, &reefnet_sensus_parser_vtable);
parser = (reefnet_sensus_parser_t *) dc_parser_allocate (context, &reefnet_sensus_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -88,8 +86,8 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
// Set the default values.
parser->atmospheric = DEF_ATMOSPHERIC;
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
parser->devtime = devtime;
parser->systime = systime;
parser->devtime = 0;
parser->systime = 0;
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0;
@ -100,35 +98,6 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
}
static dc_status_t
reefnet_sensus_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;
// Reset the cache.
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0;
return DC_STATUS_SUCCESS;
}
dc_status_t
reefnet_sensus_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
{
reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;
if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
parser->atmospheric = atmospheric;
parser->hydrostatic = hydrostatic;
return DC_STATUS_SUCCESS;
}
static dc_status_t
reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
{
@ -279,13 +248,13 @@ reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
// Time (seconds)
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (adjusted feet of seawater).
unsigned int depth = data[offset++];
sample.depth = ((depth + 33.0 - (double) SAMPLE_DEPTH_ADJUST) * FSW - parser->atmospheric) / parser->hydrostatic;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (degrees Fahrenheit)
if ((nsamples % 6) == 0) {
@ -293,7 +262,7 @@ reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
return DC_STATUS_DATAFORMAT;
unsigned int temperature = data[offset++];
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
// Current sample is complete.

View File

@ -36,7 +36,7 @@ dc_status_t
reefnet_sensuspro_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
reefnet_sensuspro_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
reefnet_sensuspro_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -47,7 +47,6 @@ struct reefnet_sensuspro_parser_t {
unsigned int maxdepth;
};
static dc_status_t reefnet_sensuspro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t reefnet_sensuspro_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
static dc_status_t reefnet_sensuspro_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
static dc_status_t reefnet_sensuspro_parser_set_density (dc_parser_t *abstract, double density);
@ -58,7 +57,6 @@ static dc_status_t reefnet_sensuspro_parser_samples_foreach (dc_parser_t *abstra
static const dc_parser_vtable_t reefnet_sensuspro_parser_vtable = {
sizeof(reefnet_sensuspro_parser_t),
DC_FAMILY_REEFNET_SENSUSPRO,
reefnet_sensuspro_parser_set_data, /* set_data */
reefnet_sensuspro_parser_set_clock, /* set_clock */
reefnet_sensuspro_parser_set_atmospheric, /* set_atmospheric */
reefnet_sensuspro_parser_set_density, /* set_density */
@ -70,7 +68,7 @@ static const dc_parser_vtable_t reefnet_sensuspro_parser_vtable = {
dc_status_t
reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
reefnet_sensuspro_parser_t *parser = NULL;
@ -78,7 +76,7 @@ reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsig
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (reefnet_sensuspro_parser_t *) dc_parser_allocate (context, &reefnet_sensuspro_parser_vtable);
parser = (reefnet_sensuspro_parser_t *) dc_parser_allocate (context, &reefnet_sensuspro_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -87,8 +85,8 @@ reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsig
// Set the default values.
parser->atmospheric = DEF_ATMOSPHERIC;
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
parser->devtime = devtime;
parser->systime = systime;
parser->devtime = 0;
parser->systime = 0;
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0;
@ -99,35 +97,6 @@ reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsig
}
static dc_status_t
reefnet_sensuspro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract;
// Reset the cache.
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0;
return DC_STATUS_SUCCESS;
}
dc_status_t
reefnet_sensuspro_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
{
reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract;
if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
parser->atmospheric = atmospheric;
parser->hydrostatic = hydrostatic;
return DC_STATUS_SUCCESS;
}
static dc_status_t
reefnet_sensuspro_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
{
@ -278,16 +247,16 @@ reefnet_sensuspro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callb
// Time (seconds)
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Temperature (°F)
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Depth (absolute pressure in fsw)
sample.depth = (depth * FSW - parser->atmospheric) / parser->hydrostatic;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 2;
}

View File

@ -36,7 +36,7 @@ dc_status_t
reefnet_sensusultra_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
reefnet_sensusultra_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
reefnet_sensusultra_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -47,7 +47,6 @@ struct reefnet_sensusultra_parser_t {
unsigned int maxdepth;
};
static dc_status_t reefnet_sensusultra_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t reefnet_sensusultra_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
static dc_status_t reefnet_sensusultra_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
static dc_status_t reefnet_sensusultra_parser_set_density (dc_parser_t *abstract, double density);
@ -58,7 +57,6 @@ static dc_status_t reefnet_sensusultra_parser_samples_foreach (dc_parser_t *abst
static const dc_parser_vtable_t reefnet_sensusultra_parser_vtable = {
sizeof(reefnet_sensusultra_parser_t),
DC_FAMILY_REEFNET_SENSUSULTRA,
reefnet_sensusultra_parser_set_data, /* set_data */
reefnet_sensusultra_parser_set_clock, /* set_clock */
reefnet_sensusultra_parser_set_atmospheric, /* set_atmospheric */
reefnet_sensusultra_parser_set_density, /* set_density */
@ -70,7 +68,7 @@ static const dc_parser_vtable_t reefnet_sensusultra_parser_vtable = {
dc_status_t
reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
reefnet_sensusultra_parser_t *parser = NULL;
@ -78,7 +76,7 @@ reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, uns
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (reefnet_sensusultra_parser_t *) dc_parser_allocate (context, &reefnet_sensusultra_parser_vtable);
parser = (reefnet_sensusultra_parser_t *) dc_parser_allocate (context, &reefnet_sensusultra_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -87,8 +85,8 @@ reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, uns
// Set the default values.
parser->atmospheric = DEF_ATMOSPHERIC;
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
parser->devtime = devtime;
parser->systime = systime;
parser->devtime = 0;
parser->systime = 0;
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0;
@ -99,35 +97,6 @@ reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, uns
}
static dc_status_t
reefnet_sensusultra_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract;
// Reset the cache.
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0;
return DC_STATUS_SUCCESS;
}
dc_status_t
reefnet_sensusultra_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
{
reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract;
if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
parser->atmospheric = atmospheric;
parser->hydrostatic = hydrostatic;
return DC_STATUS_SUCCESS;
}
static dc_status_t
reefnet_sensusultra_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
{
@ -275,18 +244,18 @@ reefnet_sensusultra_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// Time (seconds)
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Temperature (0.01 °K)
unsigned int temperature = array_uint16_le (data + offset);
sample.temperature = temperature / 100.0 - 273.15;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Depth (absolute pressure in millibar)
unsigned int depth = array_uint16_le (data + offset + 2);
sample.depth = (depth * BAR / 1000.0 - parser->atmospheric) / parser->hydrostatic;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
offset += 4;
}

View File

@ -35,7 +35,7 @@ dc_status_t
seac_screen_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
seac_screen_parser_create (dc_parser_t **parser, dc_context_t *context);
seac_screen_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -48,7 +48,6 @@ struct seac_screen_parser_t {
unsigned int gf_high;
};
static dc_status_t seac_screen_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t seac_screen_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t seac_screen_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -56,7 +55,6 @@ static dc_status_t seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc
static const dc_parser_vtable_t seac_screen_parser_vtable = {
sizeof(seac_screen_parser_t),
DC_FAMILY_SEAC_SCREEN,
seac_screen_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -67,7 +65,7 @@ static const dc_parser_vtable_t seac_screen_parser_vtable = {
};
dc_status_t
seac_screen_parser_create (dc_parser_t **out, dc_context_t *context)
seac_screen_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
seac_screen_parser_t *parser = NULL;
@ -75,7 +73,7 @@ seac_screen_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (seac_screen_parser_t *) dc_parser_allocate (context, &seac_screen_parser_vtable);
parser = (seac_screen_parser_t *) dc_parser_allocate (context, &seac_screen_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -95,23 +93,6 @@ seac_screen_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_SUCCESS;
}
static dc_status_t
seac_screen_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
seac_screen_parser_t *parser = (seac_screen_parser_t *)abstract;
// Reset the cache.
parser->cached = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->oxygen[i] = 0;
}
parser->gf_low = 0;
parser->gf_high = 0;
return DC_STATUS_SUCCESS;
}
static dc_status_t
seac_screen_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -239,6 +220,7 @@ seac_screen_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsig
*((unsigned int *)value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = DC_USAGE_NONE;
gasmix->helium = 0.0;
gasmix->oxygen = parser->oxygen[flags] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -331,16 +313,16 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
return DC_STATUS_DATAFORMAT;
}
time = timestamp;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/100 m).
sample.depth = depth / 100.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (1/100 °C).
sample.temperature = temperature / 100.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Gas mix
if (o2 != o2_previous) {
@ -363,7 +345,7 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
}
sample.gasmix = idx;
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
o2_previous = o2;
}
@ -377,11 +359,12 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.deco.time = ndl_tts;
sample.deco.depth = 0;
}
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = 0;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
// CNS
sample.cns = cns / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
// Deco model
if (gf_low == 0 && gf_high == 0) {

View File

@ -57,7 +57,6 @@
#include "context-private.h"
#include "iostream-private.h"
#include "iterator-private.h"
#include "descriptor-private.h"
#include "platform.h"
#include "timer.h"
@ -230,7 +229,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
return DC_STATUS_NOMEMORY;
}
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, filename, NULL)) {
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, filename)) {
continue;
}

View File

@ -31,7 +31,6 @@
#include "context-private.h"
#include "iostream-private.h"
#include "iterator-private.h"
#include "descriptor-private.h"
#include "platform.h"
static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item);
@ -228,7 +227,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
// Null terminate the string.
data[data_len] = 0;
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, data, NULL)) {
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, data)) {
continue;
}

View File

@ -36,10 +36,13 @@
#define ESC_END 0xDC
#define ESC_ESC 0xDD
// SIDs for CAN WDBI (Write Data By Identifier) as defined by ISO 14229-1
// (the RDBI command is implemented in shearwater_common_identifier)
#define CAN_WDBI_REQUEST_SID 0x2E
#define CAN_WDBI_RESPONSE_SID 0x6E
#define RDBI_REQUEST 0x22
#define RDBI_RESPONSE 0x62
#define WDBI_REQUEST 0x2E
#define WDBI_RESPONSE 0x6E
#define NAK 0x7F
dc_status_t
shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream)
@ -90,7 +93,7 @@ shearwater_common_decompress_lre (unsigned char *data, unsigned int size, dc_buf
// The 9th bit indicates whether the remaining 8 bits represent
// a run of zero bytes or not. If the bit is set, the value is
// not a run and doesnt need expansion. If the bit is not set,
// not a run and doesn't need expansion. If the bit is not set,
// the value contains the number of zero bytes in the run. A
// zero-length run indicates the end of the compressed stream.
if (value & 0x100) {
@ -517,195 +520,237 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf
dc_status_t
shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id)
shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size)
{
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
dc_status_t rc = DC_STATUS_SUCCESS;
// Erase the buffer.
if (!dc_buffer_clear (buffer)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
// Transfer the request.
unsigned int n = 0;
unsigned char request[] = {0x22,
unsigned char request[] = {
RDBI_REQUEST,
(id >> 8) & 0xFF,
(id ) & 0xFF};
unsigned char response[SZ_PACKET];
rc = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n);
if (rc != DC_STATUS_SUCCESS) {
return rc;
status = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n);
if (status != DC_STATUS_SUCCESS) {
return status;
}
// Verify the response.
if (n < 3 || response[0] != 0x62 || response[1] != request[1] || response[2] != request[2]) {
if (n < 3 || response[0] != RDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) {
if (n == 3 && response[0] == NAK && response[1] == RDBI_REQUEST) {
ERROR (abstract->context, "Received NAK packet with error code 0x%02x.", response[2]);
return DC_STATUS_UNSUPPORTED;
}
ERROR (abstract->context, "Unexpected response packet.");
return DC_STATUS_PROTOCOL;
}
// Append the packet to the output buffer.
if (!dc_buffer_append (buffer, response + 3, n - 3)) {
ERROR (abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
return rc;
}
dc_status_t shearwater_common_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id)
{
dc_device_t *abstract = (dc_device_t *)device;
unsigned n = 0;
char request_header[] = {
CAN_WDBI_REQUEST_SID,
(id >> 8) & 0xFF,
id & 0xFF
};
if (!dc_buffer_prepend(buffer, request_header, sizeof(request_header))) {
ERROR(abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}
char response[SZ_PACKET];
dc_status_t rc = shearwater_common_transfer(device, dc_buffer_get_data(buffer), dc_buffer_get_size(buffer), response, sizeof(response), &n);
if (rc != DC_STATUS_SUCCESS) {
return rc;
}
// Verify the response.
if (n < 3 || response[0] != CAN_WDBI_RESPONSE_SID || response[1] != request_header[1] || response[2] != request_header[2]) {
ERROR(abstract->context, "Unexpected response packet.");
unsigned int length = n - 3;
if (length != size) {
ERROR (abstract->context, "Unexpected packet size (%u bytes).", length);
return DC_STATUS_PROTOCOL;
}
return rc;
if (length) {
memcpy (data, response + 3, length);
}
return status;
}
dc_status_t shearwater_common_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime)
dc_status_t
shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size)
{
shearwater_common_device_t *device = (shearwater_common_device_t *)abstract;
dc_datetime_t local_time;
memcpy(&local_time, datetime, sizeof(local_time));
// We need to supply a unix timestamp in _local_ time
local_time.timezone = DC_TIMEZONE_NONE;
dc_ticks_t unix_timestamp = dc_datetime_mktime(&local_time);
if (unix_timestamp == -1) {
ERROR(abstract->context, "Invalid date/time value specified.");
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
if (size + 3 > SZ_PACKET) {
return DC_STATUS_INVALIDARGS;
}
dc_buffer_t *buffer = dc_buffer_new(WDBI_TIME_PACKET_SIZE);
if (buffer == NULL) {
ERROR(abstract->context, "Insufficient buffer space available.");
dc_buffer_free(buffer);
return DC_STATUS_NOMEMORY;
// Transfer the request.
unsigned int n = 0;
unsigned char request[SZ_PACKET] = {
WDBI_REQUEST,
(id >> 8) & 0xFF,
(id ) & 0xFF};
if (size) {
memcpy (request + 3, data, size);
}
unsigned char response[SZ_PACKET];
status = shearwater_common_transfer (device, request, size + 3, response, sizeof (response), &n);
if (status != DC_STATUS_SUCCESS) {
return status;
}
char shearwater_timestamp[] = {
(unix_timestamp >> 24) & 0xFF,
(unix_timestamp >> 16) & 0xFF,
(unix_timestamp >> 8) & 0xFF,
unix_timestamp & 0xFF,
};
dc_buffer_append(buffer, shearwater_timestamp, 4);
dc_status_t rc = shearwater_common_can_wdbi(device, buffer, ID_LOCAL_TIME);
if (rc != DC_STATUS_SUCCESS) {
ERROR(abstract->context, "Failed to write the dive computer time.");
// Verify the response.
if (n < 3 || response[0] != WDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) {
if (n == 3 && response[0] == NAK && response[1] == WDBI_REQUEST) {
ERROR (abstract->context, "Received NAK packet with error code 0x%02x.", response[2]);
return DC_STATUS_UNSUPPORTED;
}
ERROR (abstract->context, "Unexpected response packet.");
return DC_STATUS_PROTOCOL;
}
dc_buffer_free(buffer);
return rc;
return status;
}
dc_status_t shearwater_common_read_model(shearwater_common_device_t *device, unsigned int *model)
dc_status_t
shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime)
{
dc_buffer_t *buffer = dc_buffer_new(SZ_PACKET);
if (buffer == NULL) {
ERROR(device->base.context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
// Convert to local time.
dc_datetime_t local = *datetime;
local.timezone = DC_TIMEZONE_NONE;
dc_ticks_t ticks = dc_datetime_mktime (&local);
if (ticks == -1) {
ERROR (abstract->context, "Invalid date/time value specified.");
return DC_STATUS_INVALIDARGS;
}
// Read the hardware type.
dc_status_t rc = shearwater_common_identifier(device, buffer, ID_HARDWARE);
if (rc != DC_STATUS_SUCCESS) {
ERROR(device->base.context, "Failed to read the hardware type.");
dc_buffer_free(buffer);
const unsigned char timestamp[] = {
(ticks >> 24) & 0xFF,
(ticks >> 16) & 0xFF,
(ticks >> 8) & 0xFF,
(ticks ) & 0xFF,
};
return rc;
status = shearwater_common_wdbi (device, ID_TIME_LOCAL, timestamp, sizeof(timestamp));
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to write the dive computer local time.");
return status;
}
return status;
}
dc_status_t
shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime)
{
dc_status_t status = DC_STATUS_SUCCESS;
dc_device_t *abstract = (dc_device_t *) device;
// Convert to UTC time.
dc_ticks_t ticks = dc_datetime_mktime (datetime);
if (ticks == -1) {
ERROR (abstract->context, "Invalid date/time value specified.");
return DC_STATUS_INVALIDARGS;
}
const unsigned char timestamp[] = {
(ticks >> 24) & 0xFF,
(ticks >> 16) & 0xFF,
(ticks >> 8) & 0xFF,
(ticks ) & 0xFF,
};
status = shearwater_common_wdbi (device, ID_TIME_UTC, timestamp, sizeof(timestamp));
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to write the dive computer UTC time.");
return status;
}
int timezone = datetime->timezone / 60;
const unsigned char offset[] = {
(timezone >> 24) & 0xFF,
(timezone >> 16) & 0xFF,
(timezone >> 8) & 0xFF,
(timezone ) & 0xFF,
};
status = shearwater_common_wdbi (device, ID_TIME_OFFSET, offset, sizeof (offset));
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to write the dive computer timezone offset.");
return status;
}
// We don't have a way to determine the daylight savings time setting,
// but the required offset is already factored into the timezone offset.
const unsigned char dst[] = {0, 0, 0, 0};
status = shearwater_common_wdbi (device, ID_TIME_DST, dst, sizeof (dst));
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to write the dive computer DST setting.");
return status;
}
return status;
}
dc_status_t shearwater_common_get_model(shearwater_common_device_t *device, unsigned int *model)
{
// Read the hardware type.
unsigned char rsp_hardware[2] = {0};
status = shearwater_common_rdbi (device, ID_HARDWARE, rsp_hardware, sizeof(rsp_hardware));
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the hardware type.");
return status;
}
// Convert and map to the model number.
unsigned int hardware = array_uint_be(dc_buffer_get_data(buffer), dc_buffer_get_size(buffer));
unsigned int hardware = array_uint16_be (rsp_hardware);
switch (hardware) {
case 0x0101:
case 0x0202:
*model = PREDATOR;
break;
case 0x0606:
case 0x0A0A: // Nerd 1
*model = NERD;
break;
case 0x7E2D:
case 0x0E0D: // Nerd 2
*model = NERD2;
model = PREDATOR;
break;
case 0x0404:
case 0x0909: // Petrel 1
*model = PETREL;
case 0x0909:
model = PETREL;
break;
case 0x0505:
case 0x0808:
case 0x0838:
case 0x08A5:
case 0x0B0B:
case 0x7828:
case 0x7B2C:
case 0x8838: // Petrel 2
case 0x0B0B: // current docs (June 2023) imply this is a Petrel 2
*model = PETREL;
case 0x8838:
model = PETREL2;
break;
case 0xB407: // Petrel 3
*model = PETREL3;
case 0xB407:
model = PETREL3;
break;
case 0x0707: // Perdix
*model = PERDIX;
case 0x0606:
case 0x0A0A:
model = NERD;
break;
case 0x0C0C: // current docs (June 2023) imply this is not a valid hardware ID
case 0x0C0D: // current docs (June 2023) show this as Perdix AI
case 0x0D0D: // current docs (June 2023) imply this is not a valid hardware ID
case 0x7C2D: // Perdix AI
case 0x0E0D:
case 0x7E2D:
model = NERD2;
break;
case 0x0707:
model = PERDIX;
break;
case 0x0C0D:
case 0x7C2D:
case 0x8D6C:
*model = PERDIXAI;
model = PERDIXAI;
break;
case 0xC407: // Perdix 2
*model = PERDIX2;
case 0xC407:
model = PERDIX2;
break;
case 0x0F0F:
case 0x1F0A:
case 0x1F0F:
*model = TERIC;
model = TERIC;
break;
case 0x1512:
*model = PEREGRINE;
case 0x1512:
model = PEREGRINE;
break;
case 0xC0E0:
model = TERN;
break;
default:
// return a model of 0 which is unknown
WARNING(device->base.context, "Unknown hardware type %04x. Assuming Petrel.", hardware);
WARNING (device->base.context, "Unknown hardware type 0x%04x.", hardware);
}
dc_buffer_free(buffer);
return rc;
return model;
}

View File

@ -41,6 +41,11 @@ extern "C" {
#define WDBI_TIME_PACKET_SIZE 7
#define ID_TIME_LOCAL 0x9030
#define ID_TIME_UTC 0x9031
#define ID_TIME_OFFSET 0x9032
#define ID_TIME_DST 0x9033
#define PREDATOR 2
#define PETREL 3
#define PETREL2 PETREL
@ -52,6 +57,7 @@ extern "C" {
#define PEREGRINE 9
#define PETREL3 10
#define PERDIX2 11
#define TERN 12
#define NSTEPS 10000
#define STEP(i,n) ((NSTEPS * (i) + (n) / 2) / (n))
@ -71,7 +77,19 @@ dc_status_t
shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression, dc_event_progress_t *progress);
dc_status_t
shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id);
shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size);
dc_status_t
shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size);
dc_status_t
shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime);
dc_status_t
shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime);
unsigned int
shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware);
dc_status_t shearwater_common_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id);

View File

@ -45,80 +45,9 @@ typedef struct shearwater_petrel_device_t {
} shearwater_petrel_device_t;
static dc_status_t shearwater_petrel_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime)
{
shearwater_common_device_t *device = (shearwater_common_device_t *)abstract;
unsigned int model = 0;
shearwater_common_read_model(device, &model);
if (model == TERIC) {
dc_ticks_t unix_timestamp = dc_datetime_mktime(datetime);
if (unix_timestamp == -1) {
ERROR(abstract->context, "Invalid date/time value specified.");
return DC_STATUS_INVALIDARGS;
}
dc_buffer_t *buffer = dc_buffer_new(WDBI_TIME_PACKET_SIZE);
if (buffer == NULL) {
ERROR(abstract->context, "Insufficient buffer space available.");
dc_buffer_free(buffer);
return DC_STATUS_NOMEMORY;
}
char shearwater_timestamp[] = {
(unix_timestamp >> 24) & 0xFF,
(unix_timestamp >> 16) & 0xFF,
(unix_timestamp >> 8) & 0xFF,
unix_timestamp & 0xFF,
};
dc_buffer_append(buffer, shearwater_timestamp, 4);
dc_status_t rc = shearwater_common_can_wdbi(device, buffer, ID_UTC_TIME);
if (rc != DC_STATUS_SUCCESS) {
ERROR(abstract->context, "Failed to write the dive computer UTC time.");
}
dc_buffer_clear(buffer);
int local_time_offset_minutes = datetime->timezone / 60;
char shearwater_local_time_offset[] = {
(local_time_offset_minutes >> 24) & 0xFF,
(local_time_offset_minutes >> 16) & 0xFF,
(local_time_offset_minutes >> 8) & 0xFF,
local_time_offset_minutes & 0xFF,
};
dc_buffer_append(buffer, shearwater_local_time_offset, 4);
rc = shearwater_common_can_wdbi(device, buffer, ID_LOCAL_TIME_OFFSET);
if (rc != DC_STATUS_SUCCESS) {
ERROR(abstract->context, "Failed to write the dive computer local time offset.");
}
dc_buffer_clear(buffer);
// We don't have a way to determine the daylight savings time setting,
// but the required offset is already factored into ID_LOCAL_TIME_OFFSET
char shearwater_local_time_dst[] = { 0, 0, 0, 0 };
dc_buffer_append(buffer, shearwater_local_time_dst, 4);
rc = shearwater_common_can_wdbi(device, buffer, ID_LOCAL_TIME_DST);
if (rc != DC_STATUS_SUCCESS) {
ERROR(abstract->context, "Failed to write the dive computer DST setting.");
}
dc_buffer_free(buffer);
return rc;
}
return shearwater_common_device_timesync(abstract, datetime);
}
static dc_status_t shearwater_petrel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
static dc_status_t shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
static dc_status_t shearwater_petrel_device_close (dc_device_t *abstract);
static const dc_device_vtable_t shearwater_petrel_device_vtable = {
@ -225,55 +154,43 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
shearwater_petrel_device_t *device = (shearwater_petrel_device_t *) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
// Allocate memory buffers for the manifests.
dc_buffer_t *buffer = dc_buffer_new (MANIFEST_SIZE);
dc_buffer_t *manifests = dc_buffer_new (MANIFEST_SIZE);
if (buffer == NULL || manifests == NULL) {
ERROR (abstract->context, "Insufficient buffer space available.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return DC_STATUS_NOMEMORY;
}
// Enable progress notifications.
unsigned int current = 0, maximum = 0;
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
// Read the serial number.
rc = shearwater_common_identifier (&device->base, buffer, ID_SERIAL);
unsigned char rsp_serial[8] = {0};
rc = shearwater_common_rdbi (&device->base, ID_SERIAL, rsp_serial, sizeof(rsp_serial));
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the serial number.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc;
}
// Convert to a number.
unsigned char serial[4] = {0};
if (array_convert_hex2bin (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer),
serial, sizeof (serial)) != 0 ) {
if (array_convert_hex2bin (rsp_serial, sizeof(rsp_serial), serial, sizeof (serial)) != 0 ) {
ERROR (abstract->context, "Failed to convert the serial number.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return DC_STATUS_DATAFORMAT;
}
// Read the firmware version.
rc = shearwater_common_identifier (&device->base, buffer, ID_FIRMWARE);
unsigned char rsp_firmware[11] = {0};
rc = shearwater_common_rdbi (&device->base, ID_FIRMWARE, rsp_firmware, sizeof(rsp_firmware));
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the firmware version.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc;
}
// Convert to a number.
unsigned int firmware = str2num (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), 1);
unsigned int firmware = str2num (rsp_firmware, sizeof(rsp_firmware), 1);
unsigned int model = 0;
shearwater_common_read_model((shearwater_common_device_t *)device, &model);
rc = shearwater_common_get_model (&device->base, &model);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the hardware type.");
return rc;
}
// Emit a device info event.
dc_event_devinfo_t devinfo;
@ -283,22 +200,14 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
// Read the logbook type
rc = shearwater_common_identifier (&device->base, buffer, ID_LOGUPLOAD);
unsigned char rsp_logupload[9] = {0};
rc = shearwater_common_rdbi (&device->base, ID_LOGUPLOAD, rsp_logupload, sizeof(rsp_logupload));
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the logbook type.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return rc;
}
if (dc_buffer_get_size (buffer) != 9) {
ERROR (abstract->context, "Unexpected packet size (" DC_PRINTF_SIZE " bytes).", dc_buffer_get_size(buffer));
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return DC_STATUS_DATAFORMAT;
}
unsigned int base_addr = array_uint32_be (dc_buffer_get_data (buffer) + 1);
unsigned int base_addr = array_uint32_be (rsp_logupload + 1);
switch (base_addr) {
case 0xDD000000: // Predator - we shouldn't get here, we could give up or we can try 0xC0000000
case 0xC0000000: // Predator-Like Format (what we used to call the Petrel format)
@ -311,9 +220,17 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
break;
default: // unknown format
ERROR (abstract->context, "Unknown logbook format %08x", base_addr);
return DC_STATUS_DATAFORMAT;
}
// Allocate memory buffers for the manifests.
dc_buffer_t *buffer = dc_buffer_new (MANIFEST_SIZE);
dc_buffer_t *manifests = dc_buffer_new (MANIFEST_SIZE);
if (buffer == NULL || manifests == NULL) {
ERROR (abstract->context, "Insufficient buffer space available.");
dc_buffer_free (buffer);
dc_buffer_free (manifests);
return DC_STATUS_DATAFORMAT;
return DC_STATUS_NOMEMORY;
}
// Read the manifest pages
@ -430,3 +347,23 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
return rc;
}
static dc_status_t
shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime)
{
dc_status_t status = DC_STATUS_SUCCESS;
shearwater_common_device_t *device = (shearwater_common_device_t *) abstract;
unsigned int model = 0;
status = shearwater_common_get_model (&device->base, &model);
if (status != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to read the hardware type.");
return status;
}
if (model == TERIC) {
return shearwater_common_timesync_utc (device, datetime);
} else {
return shearwater_common_timesync_local (device, datetime);
}
}

View File

@ -35,7 +35,7 @@ dc_status_t
shearwater_petrel_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -44,6 +44,7 @@ typedef struct shearwater_predator_device_t {
static dc_status_t shearwater_predator_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
static dc_status_t shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
static dc_status_t shearwater_predator_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
static dc_status_t shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
static const dc_device_vtable_t shearwater_predator_device_vtable = {
sizeof(shearwater_predator_device_t),
@ -53,7 +54,7 @@ static const dc_device_vtable_t shearwater_predator_device_vtable = {
NULL, /* write */
shearwater_predator_device_dump, /* dump */
shearwater_predator_device_foreach, /* foreach */
shearwater_common_device_timesync,
shearwater_predator_device_timesync,
NULL /* close */
};
@ -357,3 +358,9 @@ shearwater_predator_extract_dives (dc_device_t *abstract, const unsigned char da
return shearwater_predator_extract_predator (abstract, data, size, callback, userdata);
}
}
static dc_status_t
shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime)
{
return shearwater_common_timesync_local ((shearwater_common_device_t *) abstract, datetime);
}

View File

@ -35,7 +35,7 @@ dc_status_t
shearwater_predator_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -109,6 +109,8 @@ typedef struct shearwater_predator_gasmix_t {
unsigned int oxygen;
unsigned int helium;
unsigned int diluent;
unsigned int enabled;
unsigned int active;
} shearwater_predator_gasmix_t;
typedef struct shearwater_predator_tank_t {
@ -121,6 +123,7 @@ typedef struct shearwater_predator_tank_t {
unsigned int serial;
char name[2];
unsigned int battery;
dc_usage_t usage;
} shearwater_predator_tank_t;
struct shearwater_predator_parser_t {
@ -143,8 +146,10 @@ struct shearwater_predator_parser_t {
shearwater_predator_tank_t tank[NTANKS];
unsigned int tankidx[NTANKS];
unsigned int aimode;
unsigned int hpccr;
unsigned int calibrated;
double calibration[3];
unsigned int divemode;
unsigned int serial;
unsigned int units;
unsigned int atmospheric;
@ -154,7 +159,6 @@ struct shearwater_predator_parser_t {
struct dc_field_cache cache;
};
static dc_status_t shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -164,7 +168,6 @@ static dc_status_t shearwater_predator_parser_cache (shearwater_predator_parser_
static const dc_parser_vtable_t shearwater_predator_parser_vtable = {
sizeof(shearwater_predator_parser_t),
DC_FAMILY_SHEARWATER_PREDATOR,
shearwater_predator_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -177,7 +180,6 @@ static const dc_parser_vtable_t shearwater_predator_parser_vtable = {
static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
sizeof(shearwater_predator_parser_t),
DC_FAMILY_SHEARWATER_PETREL,
shearwater_predator_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -188,6 +190,12 @@ static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
};
static unsigned int
shearwater_predator_is_ccr (unsigned int divemode)
{
return divemode == M_CC || divemode == M_CC2 || divemode == M_SC;
}
static unsigned int
shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil)
{
@ -203,7 +211,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 model, unsigned int serial, unsigned int petrel)
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int petrel, unsigned int serial)
{
shearwater_predator_parser_t *parser = NULL;
const dc_parser_vtable_t *vtable = NULL;
@ -221,7 +229,7 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
}
// Allocate memory.
parser = (shearwater_predator_parser_t *) dc_parser_allocate (context, vtable);
parser = (shearwater_predator_parser_t *) dc_parser_allocate (context, vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -249,6 +257,8 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
parser->gasmix[i].diluent = 0;
parser->gasmix[i].enabled = 0;
parser->gasmix[i].active = 0;
}
parser->ntanks = 0;
for (unsigned int i = 0; i < NTANKS; ++i) {
@ -261,9 +271,11 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
parser->tank[i].serial = 0;
memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name));
parser->tank[i].battery = 0;
parser->tank[i].usage = DC_USAGE_NONE;
parser->tankidx[i] = i;
}
parser->aimode = AI_OFF;
parser->hpccr = 0;
parser->calibrated = 0;
for (unsigned int i = 0; i < 3; ++i) {
parser->calibration[i] = 0.0;
@ -281,65 +293,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 model, unsigned int serial)
shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
{
return shearwater_common_parser_create (out, context, model, serial, 0);
return shearwater_common_parser_create (out, context, data, size, model, 0, serial);
}
dc_status_t
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
{
return shearwater_common_parser_create (out, context, model, serial, 1);
}
static dc_status_t
shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
shearwater_predator_parser_t *parser = (shearwater_predator_parser_t *) abstract;
// Reset the cache.
parser->cached = 0;
parser->pnf = 0;
parser->logversion = 0;
parser->headersize = 0;
parser->footersize = 0;
for (unsigned int i = 0; i < NRECORDS; ++i) {
parser->opening[i] = UNDEFINED;
parser->closing[i] = UNDEFINED;
}
parser->final = UNDEFINED;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
parser->gasmix[i].diluent = 0;
}
parser->ntanks = 0;
for (unsigned int i = 0; i < NTANKS; ++i) {
parser->tank[i].enabled = 0;
parser->tank[i].active = 0;
parser->tank[i].beginpressure = 0;
parser->tank[i].endpressure = 0;
parser->tank[i].pressure_max = 0;
parser->tank[i].pressure_reserve = 0;
parser->tank[i].serial = 0;
memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name));
parser->tankidx[i] = i;
}
parser->aimode = AI_OFF;
parser->calibrated = 0;
for (unsigned int i = 0; i < 3; ++i) {
parser->calibration[i] = 0.0;
}
parser->units = METRIC;
parser->density = DEF_DENSITY_SALT;
parser->atmospheric = DEF_ATMOSPHERIC / (BAR / 1000);
DC_ASSIGN_FIELD(parser->cache, DIVEMODE, DC_DIVEMODE_OC);
return DC_STATUS_SUCCESS;
return shearwater_common_parser_create (out, context, data, size, model, 1, serial);
}
@ -522,11 +485,13 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
shearwater_predator_tank_t tank[NTANKS] = {0};
unsigned int o2_previous = UNDEFINED, he_previous = UNDEFINED, dil_previous = UNDEFINED;
unsigned int aimode = AI_OFF;
unsigned int hpccr = 0;
if (!pnf) {
for (unsigned int i = 0; i < NFIXED; ++i) {
gasmix[i].oxygen = data[20 + i];
gasmix[i].helium = data[30 + i];
gasmix[i].diluent = i >= 5;
gasmix[i].enabled = 1;
}
}
@ -575,6 +540,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
ngasmixes = idx + 1;
}
gasmix[idx].active = 1;
o2_previous = o2;
he_previous = he;
dil_previous = ccr;
@ -636,8 +603,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
tank[id].enabled = 1;
tank[id].beginpressure = pressure;
tank[id].endpressure = pressure;
tank[id].name[0] = i == 0 ? 'D': 'O';
tank[id].name[1] = 0;
tank[id].usage = i == 0 ? DC_USAGE_DILUENT : DC_USAGE_OXYGEN;
hpccr = 1;
}
tank[id].endpressure = pressure;
}
@ -681,9 +648,24 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
if (aimode == AI_HPCCR) {
for (unsigned int i = 0; i < 2; ++i) {
tank[4 + i].enabled = 1;
tank[4 + i].name[0] = i == 0 ? 'D': 'O';
tank[4 + i].name[1] = 0;
tank[4 + i].usage = i == 0 ? DC_USAGE_DILUENT : DC_USAGE_OXYGEN;
}
hpccr = 1;
}
}
}
// Gas mix on/off state.
unsigned int state = array_uint16_be (data + offset + 17);
for (unsigned int i = 0; i < NFIXED; ++i) {
gasmix[i].enabled = (state & (1 << i)) != 0;
}
unsigned int gtrmode = data[offset + 29];
if (popcount(gtrmode) >= 2) {
for (unsigned int i = 0; i < 4; ++i) {
if (gtrmode & (1 << i)) {
tank[i].usage = DC_USAGE_SIDEMOUNT;
}
}
}
@ -809,6 +791,10 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
for (unsigned int i = 0; i < ngasmixes; ++i) {
if (gasmix[i].oxygen == 0 && gasmix[i].helium == 0)
continue;
if (!gasmix[i].enabled && !gasmix[i].active)
continue;
if (gasmix[i].diluent && !shearwater_predator_is_ccr (divemode))
continue;
parser->gasmix[parser->ngasmixes] = gasmix[i];
parser->ngasmixes++;
}
@ -824,6 +810,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
}
}
parser->aimode = aimode;
parser->hpccr = hpccr;
parser->divemode = divemode;
parser->units = data[parser->opening[0] + 8];
parser->atmospheric = array_uint16_be (data + parser->opening[1] + (parser->pnf ? 16 : 47));
parser->density = array_uint16_be (data + parser->opening[3] + (parser->pnf ? 3 : 83));
@ -907,6 +895,7 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
*((unsigned int *) value) = parser->ngasmixes;
break;
case DC_FIELD_GASMIX:
gasmix->usage = parser->gasmix[flags].diluent ? DC_USAGE_DILUENT : DC_USAGE_NONE;
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
gasmix->helium = parser->gasmix[flags].helium / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
@ -921,6 +910,21 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
tank->beginpressure = parser->tank[flags].beginpressure * 2 * PSI / BAR;
tank->endpressure = parser->tank[flags].endpressure * 2 * PSI / BAR;
tank->gasmix = DC_GASMIX_UNKNOWN;
if (shearwater_predator_is_ccr (parser->divemode) && !parser->hpccr) {
switch (parser->tank[flags].name[0]) {
case 'O':
tank->usage = DC_USAGE_OXYGEN;
break;
case 'D':
tank->usage = DC_USAGE_DILUENT;
break;
default:
tank->usage = DC_USAGE_NONE;
break;
}
} else {
tank->usage = parser->tank[flags].usage;
}
break;
case DC_FIELD_SALINITY:
if (parser->density == 1000)
@ -984,14 +988,9 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// Sample interval.
unsigned int time = 0;
unsigned int interval = 10;
unsigned int interval = 10000;
if (parser->pnf && parser->logversion >= 9 && parser->opening[5] != UNDEFINED) {
interval = array_uint16_be (data + parser->opening[5] + 23);
if (interval % 1000 != 0) {
ERROR (abstract->context, "Unsupported sample interval (%u ms).", interval);
return DC_STATUS_DATAFORMAT;
}
interval /= 1000;
}
unsigned int pnf = parser->pnf;
@ -1017,7 +1016,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/10 m or ft).
unsigned int depth = array_uint16_be (data + pnf + offset);
@ -1025,7 +1024,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.depth = depth * FEET / 10.0;
else
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (°C or °F).
int temperature = (signed char) data[offset + pnf + 13];
@ -1040,7 +1039,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
else
sample.temperature = temperature;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Status flags.
unsigned int status = data[offset + pnf + 11];
@ -1049,19 +1048,21 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
if (ccr) {
// PPO2
if ((status & PPO2_EXTERNAL) == 0) {
if (!parser->calibrated) {
sample.ppo2 = data[offset + pnf + 6] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
} else {
sample.ppo2 = data[offset + pnf + 12] * parser->calibration[0];
if (callback && (parser->calibrated & 0x01)) callback (DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = DC_SENSOR_NONE;
sample.ppo2.value = data[offset + pnf + 6] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
sample.ppo2 = data[offset + pnf + 14] * parser->calibration[1];
if (callback && (parser->calibrated & 0x02)) callback (DC_SAMPLE_PPO2, sample, userdata);
sample.ppo2.sensor = 0;
sample.ppo2.value = data[offset + pnf + 12] * parser->calibration[0];
if (callback && (parser->calibrated & 0x01)) callback (DC_SAMPLE_PPO2, &sample, userdata);
sample.ppo2 = data[offset + pnf + 15] * parser->calibration[2];
if (callback && (parser->calibrated & 0x04)) callback (DC_SAMPLE_PPO2, sample, userdata);
}
sample.ppo2.sensor = 1;
sample.ppo2.value = data[offset + pnf + 14] * parser->calibration[1];
if (callback && (parser->calibrated & 0x02)) callback (DC_SAMPLE_PPO2, &sample, userdata);
sample.ppo2.sensor = 2;
sample.ppo2.value = data[offset + pnf + 15] * parser->calibration[2];
if (callback && (parser->calibrated & 0x04)) callback (DC_SAMPLE_PPO2, &sample, userdata);
}
// Setpoint
@ -1075,13 +1076,13 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.setpoint = data[17] / 100.0;
}
}
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
}
// CNS
if (parser->petrel) {
sample.cns = data[offset + pnf + 22] / 100.0;
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
}
// Gaschange.
@ -1096,7 +1097,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
o2_previous = o2;
he_previous = he;
dil_previous = ccr;
@ -1115,7 +1116,8 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.deco.depth = 0.0;
}
sample.deco.time = data[offset + pnf + 9] * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
sample.deco.tts = array_uint16_be (data + offset + pnf + 4) * 60;
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
// for logversion 7 and newer (introduced for Perdix AI)
// detect tank pressure
@ -1137,7 +1139,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
pressure &= 0x0FFF;
sample.pressure.tank = parser->tankidx[id];
sample.pressure.value = pressure * 2 * PSI / BAR;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
}
@ -1150,7 +1152,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// 0xFB Tank size or max pressure havent been set up
if (data[offset + pnf + 21] < 0xF0) {
sample.rbt = data[offset + pnf + 21];
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
if (callback) callback (DC_SAMPLE_RBT, &sample, userdata);
}
}
} else if (type == LOG_RECORD_DIVE_SAMPLE_EXT) {
@ -1163,7 +1165,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
pressure &= 0x0FFF;
sample.pressure.tank = parser->tankidx[id];
sample.pressure.value = pressure * 2 * PSI / BAR;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
}
}
@ -1175,7 +1177,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
if (pressure) {
sample.pressure.tank = parser->tankidx[id];
sample.pressure.value = pressure * 2 * PSI / BAR;
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
}
}
}
@ -1194,17 +1196,17 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (absolute pressure in millibar)
unsigned int depth = array_uint16_be (data + idx + 1);
sample.depth = (signed int)(depth - parser->atmospheric) * (BAR / 1000.0) / (parser->density * GRAVITY);
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (1/10 °C).
int temperature = (signed short) array_uint16_be (data + idx + 3);
sample.temperature = temperature / 10.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
}
} else if (type == LOG_RECORD_INFO_EVENT) {
unsigned int event = data[offset + 1];
@ -1216,7 +1218,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// Compass heading
if (w1 != 0xFFFFFFFF) {
sample.bearing = w1;
if (callback) callback (DC_SAMPLE_BEARING, sample, userdata);
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
}
// Tag
@ -1224,7 +1226,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = w2;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
}
}

View File

@ -35,7 +35,7 @@ dc_status_t
sporasub_sp2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
dc_status_t
sporasub_sp2_parser_create (dc_parser_t **parser, dc_context_t *context);
sporasub_sp2_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
#ifdef __cplusplus
}

View File

@ -37,7 +37,6 @@ struct sporasub_sp2_parser_t {
dc_parser_t base;
};
static dc_status_t sporasub_sp2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
static dc_status_t sporasub_sp2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
static dc_status_t sporasub_sp2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
@ -45,7 +44,6 @@ static dc_status_t sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, d
static const dc_parser_vtable_t sporasub_sp2_parser_vtable = {
sizeof(sporasub_sp2_parser_t),
DC_FAMILY_SPORASUB_SP2,
sporasub_sp2_parser_set_data, /* set_data */
NULL, /* set_clock */
NULL, /* set_atmospheric */
NULL, /* set_density */
@ -57,7 +55,7 @@ static const dc_parser_vtable_t sporasub_sp2_parser_vtable = {
dc_status_t
sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context)
sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
{
sporasub_sp2_parser_t *parser = NULL;
@ -65,7 +63,7 @@ sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
parser = (sporasub_sp2_parser_t *) dc_parser_allocate (context, &sporasub_sp2_parser_vtable);
parser = (sporasub_sp2_parser_t *) dc_parser_allocate (context, &sporasub_sp2_parser_vtable, data, size);
if (parser == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
@ -77,13 +75,6 @@ sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context)
}
static dc_status_t
sporasub_sp2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{
return DC_STATUS_SUCCESS;
}
static dc_status_t
sporasub_sp2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
{
@ -184,21 +175,21 @@ sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Time (seconds)
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
sample.time = time * 1000;
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
// Depth (1/100 m)
sample.depth = depth / 100.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
// Temperature (1/10 °C)
sample.temperature = temperature / 10.0 - 20.0;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
// Heartrate
if (heartrate) {
sample.heartbeat = heartrate;
if (callback) callback (DC_SAMPLE_HEARTBEAT, sample, userdata);
if (callback) callback (DC_SAMPLE_HEARTBEAT, &sample, userdata);
}
offset += SZ_SAMPLE;

Some files were not shown because too many files have changed in this diff Show More