diff --git a/configure.ac b/configure.ac index f580dbc1..fbb20734 100644 --- a/configure.ac +++ b/configure.ac @@ -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])) diff --git a/contrib/msvc/libdivecomputer.vcxproj b/contrib/msvc/libdivecomputer.vcxproj index 7f1335c7..704ef8b7 100644 --- a/contrib/msvc/libdivecomputer.vcxproj +++ b/contrib/msvc/libdivecomputer.vcxproj @@ -331,7 +331,6 @@ - diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 63f9e855..4ea44de2 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -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 \ diff --git a/doc/man/dc_device_foreach.3 b/doc/man/dc_device_foreach.3 index a349a728..86782f84 100644 --- a/doc/man/dc_device_foreach.3 +++ b/doc/man/dc_device_foreach.3 @@ -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 diff --git a/doc/man/dc_parser_get_datetime.3 b/doc/man/dc_parser_get_datetime.3 index ba1f365d..0b7b707c 100644 --- a/doc/man/dc_parser_get_datetime.3 +++ b/doc/man/dc_parser_get_datetime.3 @@ -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 diff --git a/doc/man/dc_parser_get_field.3 b/doc/man/dc_parser_get_field.3 index a4c33f2e..0f6455dc 100644 --- a/doc/man/dc_parser_get_field.3 +++ b/doc/man/dc_parser_get_field.3 @@ -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 diff --git a/doc/man/dc_parser_new.3 b/doc/man/dc_parser_new.3 index 9f879cdf..e5340f0c 100644 --- a/doc/man/dc_parser_new.3 +++ b/doc/man/dc_parser_new.3 @@ -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 diff --git a/doc/man/dc_parser_samples_foreach.3 b/doc/man/dc_parser_samples_foreach.3 index 5ac55549..69a637f2 100644 --- a/doc/man/dc_parser_samples_foreach.3 +++ b/doc/man/dc_parser_samples_foreach.3 @@ -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 diff --git a/doc/man/dc_parser_set_data.3 b/doc/man/dc_parser_set_data.3 deleted file mode 100644 index 39af43b7..00000000 --- a/doc/man/dc_parser_set_data.3 +++ /dev/null @@ -1,65 +0,0 @@ -.\" -.\" libdivecomputer -.\" -.\" Copyright (C) 2017 Kristaps Dzonsons -.\" -.\" 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 . diff --git a/doc/man/libdivecomputer.3 b/doc/man/libdivecomputer.3 index 4e1f6013..cbe22eb9 100644 --- a/doc/man/libdivecomputer.3 +++ b/doc/man/libdivecomputer.3 @@ -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 . diff --git a/examples/dctool_download.c b/examples/dctool_download.c index 04aedcf8..29742e0c 100644 --- a/examples/dctool_download.c +++ b/examples/dctool_download.c @@ -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); diff --git a/examples/dctool_parse.c b/examples/dctool_parse.c index b898b5c8..4ecf30e3 100644 --- a/examples/dctool_parse.c +++ b/examples/dctool_parse.c @@ -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; } diff --git a/examples/output_xml.c b/examples/output_xml.c index 8e9380a2..1bb673bf 100644 --- a/examples/output_xml.c +++ b/examples/output_xml.c @@ -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, "\n"); fprintf (sampledata->ostream, "\n"); - fprintf (sampledata->ostream, " \n", value.time / 60, value.time % 60); + if (milliseconds) { + fprintf (sampledata->ostream, " \n", seconds / 60, seconds % 60, milliseconds); + } else { + fprintf (sampledata->ostream, " \n", seconds / 60, seconds % 60); + } break; case DC_SAMPLE_DEPTH: fprintf (sampledata->ostream, " %.2f\n", - convert_depth(value.depth, sampledata->units)); + convert_depth(value->depth, sampledata->units)); break; case DC_SAMPLE_PRESSURE: fprintf (sampledata->ostream, " %.2f\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, " %.2f\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, " %s\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, " %u\n", value.rbt); + fprintf (sampledata->ostream, " %u\n", value->rbt); break; case DC_SAMPLE_HEARTBEAT: - fprintf (sampledata->ostream, " %u\n", value.heartbeat); + fprintf (sampledata->ostream, " %u\n", value->heartbeat); break; case DC_SAMPLE_BEARING: - fprintf (sampledata->ostream, " %u\n", value.bearing); + fprintf (sampledata->ostream, " %u\n", value->bearing); break; case DC_SAMPLE_VENDOR: - fprintf (sampledata->ostream, " ", 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, " ", 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, "\n"); break; case DC_SAMPLE_SETPOINT: - fprintf (sampledata->ostream, " %.2f\n", value.setpoint); + fprintf (sampledata->ostream, " %.2f\n", value->setpoint); break; case DC_SAMPLE_PPO2: - fprintf (sampledata->ostream, " %.2f\n", value.ppo2); + if (value->ppo2.sensor != DC_SENSOR_NONE) { + fprintf (sampledata->ostream, " %.2f\n", value->ppo2.sensor, value->ppo2.value); + } else { + fprintf (sampledata->ostream, " %.2f\n", value->ppo2.value); + } break; case DC_SAMPLE_CNS: - fprintf (sampledata->ostream, " %.1f\n", value.cns * 100.0); + fprintf (sampledata->ostream, " %.1f\n", value->cns * 100.0); break; case DC_SAMPLE_DECO: fprintf (sampledata->ostream, " %s\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, " %u\n", + value->deco.tts); + } break; case DC_SAMPLE_GASMIX: - fprintf (sampledata->ostream, " %u\n", value.gasmix); + fprintf (sampledata->ostream, " %u\n", value->gasmix); break; default: break; @@ -322,11 +338,19 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u "\n" " %.1f\n" " %.1f\n" - " %.1f\n" - "\n", + " %.1f\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, + " %s\n", + usage[gasmix.usage]); + } + fprintf (output->ostream, + "\n"); + } // Parse the tanks. @@ -354,6 +378,12 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u " %u\n", tank.gasmix); } + if (tank.usage) { + const char *usage[] = {"none", "oxygen", "diluent", "sidemount"}; + fprintf (output->ostream, + " %s\n", + usage[tank.usage]); + } if (tank.type != DC_TANKVOLUME_NONE) { fprintf (output->ostream, " %s\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, "%.1f\n", - salinity.type, salinity.density); + const char *names[] = {"fresh", "salt"}; + if (salinity.density) { + fprintf (output->ostream, "%s\n", + salinity.density, names[salinity.type]); + } else { + fprintf (output->ostream, "%s\n", + names[salinity.type]); + } } // Parse the atmospheric pressure. diff --git a/include/libdivecomputer/atomics_cobalt.h b/include/libdivecomputer/atomics_cobalt.h index 5afb1c14..c2dfd66f 100644 --- a/include/libdivecomputer/atomics_cobalt.h +++ b/include/libdivecomputer/atomics_cobalt.h @@ -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 */ diff --git a/include/libdivecomputer/descriptor.h b/include/libdivecomputer/descriptor.h index a2b4495e..bdd8c73c 100644 --- a/include/libdivecomputer/descriptor.h +++ b/include/libdivecomputer/descriptor.h @@ -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 */ diff --git a/include/libdivecomputer/parser.h b/include/libdivecomputer/parser.h index 37c9f813..71797ba2 100644 --- a/include/libdivecomputer/parser.h +++ b/include/libdivecomputer/parser.h @@ -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); diff --git a/include/libdivecomputer/reefnet_sensus.h b/include/libdivecomputer/reefnet_sensus.h index 583d9af6..b0fe2716 100644 --- a/include/libdivecomputer/reefnet_sensus.h +++ b/include/libdivecomputer/reefnet_sensus.h @@ -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 */ diff --git a/include/libdivecomputer/reefnet_sensuspro.h b/include/libdivecomputer/reefnet_sensuspro.h index a92966f0..b879a502 100644 --- a/include/libdivecomputer/reefnet_sensuspro.h +++ b/include/libdivecomputer/reefnet_sensuspro.h @@ -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 */ diff --git a/include/libdivecomputer/reefnet_sensusultra.h b/include/libdivecomputer/reefnet_sensusultra.h index c5a89444..fc1b4f7c 100644 --- a/include/libdivecomputer/reefnet_sensusultra.h +++ b/include/libdivecomputer/reefnet_sensusultra.h @@ -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 */ diff --git a/include/libdivecomputer/usb.h b/include/libdivecomputer/usb.h index 6d138137..82e58818 100644 --- a/include/libdivecomputer/usb.h +++ b/include/libdivecomputer/usb.h @@ -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. */ diff --git a/include/libdivecomputer/usbhid.h b/include/libdivecomputer/usbhid.h index f1c542a0..245adf0e 100644 --- a/include/libdivecomputer/usbhid.h +++ b/include/libdivecomputer/usbhid.h @@ -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. */ diff --git a/src/Makefile.am b/src/Makefile.am index fec3d319..21399599 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/array.c b/src/array.c index 29f5faf3..f47c3eb0 100644 --- a/src/array.c +++ b/src/array.c @@ -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; +} diff --git a/src/array.h b/src/array.h index a6ef21e9..fab1475e 100644 --- a/src/array.h +++ b/src/array.h @@ -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 */ diff --git a/src/atomics_cobalt.c b/src/atomics_cobalt.c index 1c2e3a57..8c386965 100644 --- a/src/atomics_cobalt.c +++ b/src/atomics_cobalt.c @@ -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; diff --git a/src/atomics_cobalt.h b/src/atomics_cobalt.h index 09f02267..8c706415 100644 --- a/src/atomics_cobalt.h +++ b/src/atomics_cobalt.h @@ -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 } diff --git a/src/atomics_cobalt_parser.c b/src/atomics_cobalt_parser.c index 7a95e6fa..1121234a 100644 --- a/src/atomics_cobalt_parser.c +++ b/src/atomics_cobalt_parser.c @@ -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; } diff --git a/src/bluetooth.c b/src/bluetooth.c index aa5f05a8..309953cc 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -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; } diff --git a/src/citizen_aqualand.c b/src/citizen_aqualand.c index 63760ac7..66455f4b 100644 --- a/src/citizen_aqualand.c +++ b/src/citizen_aqualand.c @@ -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); } diff --git a/src/citizen_aqualand.h b/src/citizen_aqualand.h index ac47cb6a..bc233119 100644 --- a/src/citizen_aqualand.h +++ b/src/citizen_aqualand.h @@ -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 } diff --git a/src/citizen_aqualand_parser.c b/src/citizen_aqualand_parser.c index 5b955559..ff1ea9ed 100644 --- a/src/citizen_aqualand_parser.c +++ b/src/citizen_aqualand_parser.c @@ -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); } } } diff --git a/src/cochran_commander.h b/src/cochran_commander.h index 84a521e3..1a36676f 100644 --- a/src/cochran_commander.h +++ b/src/cochran_commander.h @@ -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 } diff --git a/src/cochran_commander_parser.c b/src/cochran_commander_parser.c index a4515ea8..aeaf25c8 100644 --- a/src/cochran_commander_parser.c +++ b/src/cochran_commander_parser.c @@ -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 @@ cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, unsig } -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; } diff --git a/src/cressi_edy.c b/src/cressi_edy.c index 86ed76e3..d61b84e1 100644 --- a/src/cressi_edy.c +++ b/src/cressi_edy.c @@ -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) diff --git a/src/cressi_edy.h b/src/cressi_edy.h index 7aa5a34f..238e5df2 100644 --- a/src/cressi_edy.h +++ b/src/cressi_edy.h @@ -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 } diff --git a/src/cressi_edy_parser.c b/src/cressi_edy_parser.c index 3817fc75..951c032b 100644 --- a/src/cressi_edy_parser.c +++ b/src/cressi_edy_parser.c @@ -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; } } diff --git a/src/cressi_goa.h b/src/cressi_goa.h index 0a925129..63283a07 100644 --- a/src/cressi_goa.h +++ b/src/cressi_goa.h @@ -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 } diff --git a/src/cressi_goa_parser.c b/src/cressi_goa_parser.c index f5d4a4c8..28986622 100644 --- a/src/cressi_goa_parser.c +++ b/src/cressi_goa_parser.c @@ -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; } } diff --git a/src/cressi_leonardo.h b/src/cressi_leonardo.h index 982bb012..2efc4d82 100644 --- a/src/cressi_leonardo.h +++ b/src/cressi_leonardo.h @@ -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 } diff --git a/src/cressi_leonardo_parser.c b/src/cressi_leonardo_parser.c index 7ef6f98e..2f83ab99 100644 --- a/src/cressi_leonardo_parser.c +++ b/src/cressi_leonardo_parser.c @@ -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; diff --git a/src/deepblu_cosmiq.h b/src/deepblu_cosmiq.h index 35878122..0d0c29a7 100644 --- a/src/deepblu_cosmiq.h +++ b/src/deepblu_cosmiq.h @@ -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 } diff --git a/src/deepblu_cosmiq_parser.c b/src/deepblu_cosmiq_parser.c index 508bc5d8..95b5ae78 100644 --- a/src/deepblu_cosmiq_parser.c +++ b/src/deepblu_cosmiq_parser.c @@ -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; diff --git a/src/deepsix_excursion.h b/src/deepsix_excursion.h index 42ecffc8..839511f9 100644 --- a/src/deepsix_excursion.h +++ b/src/deepsix_excursion.h @@ -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 } diff --git a/src/deepsix_excursion_parser.c b/src/deepsix_excursion_parser.c index 2fc8c2c1..52d06af9 100644 --- a/src/deepsix_excursion_parser.c +++ b/src/deepsix_excursion_parser.c @@ -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; diff --git a/src/descriptor-private.h b/src/descriptor-private.h deleted file mode 100644 index 3346654b..00000000 --- a/src/descriptor-private.h +++ /dev/null @@ -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 - -// 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 */ diff --git a/src/descriptor.c b/src/descriptor.c index c4e719f5..7a824dcb 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -23,7 +23,10 @@ #include #include -#include "descriptor-private.h" +#include +#include +#include + #include "iterator-private.h" #include "platform.h" @@ -36,39 +39,29 @@ 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); - -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); +typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); + +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); +static int dc_filter_garmin (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata); static dc_status_t dc_descriptor_iterator_next (dc_iterator_t *iterator, void *item); @@ -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", @@ -828,7 +858,8 @@ static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, v } // Not merged upstream yet -static int dc_filter_garmin (dc_transport_t transport, const void *userdata, void *params) +static int +dc_filter_garmin (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata) { static const dc_usb_desc_t usbhid[] = { {0x091e, 0x2b2b}, // Garmin Descent Mk1 @@ -933,10 +964,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); } diff --git a/src/diverite_nitekq.h b/src/diverite_nitekq.h index e016cabb..9bbf7280 100644 --- a/src/diverite_nitekq.h +++ b/src/diverite_nitekq.h @@ -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 } diff --git a/src/diverite_nitekq_parser.c b/src/diverite_nitekq_parser.c index 56237696..d9f6dccd 100644 --- a/src/diverite_nitekq_parser.c +++ b/src/diverite_nitekq_parser.c @@ -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 { diff --git a/src/divesoft_freedom.h b/src/divesoft_freedom.h index db04edb6..bca87b7f 100644 --- a/src/divesoft_freedom.h +++ b/src/divesoft_freedom.h @@ -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 } diff --git a/src/divesoft_freedom_parser.c b/src/divesoft_freedom_parser.c index b595e63b..96475113 100644 --- a/src/divesoft_freedom_parser.c +++ b/src/divesoft_freedom_parser.c @@ -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) { diff --git a/src/divesystem_idive.h b/src/divesystem_idive.h index 1da80a00..91e1ea95 100644 --- a/src/divesystem_idive.h +++ b/src/divesystem_idive.h @@ -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 } diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index 3270c55c..c13a8047 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -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; diff --git a/src/field-cache.h b/src/field-cache.h index 1a869ad0..09c06e0c 100644 --- a/src/field-cache.h +++ b/src/field-cache.h @@ -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]; diff --git a/src/garmin.c b/src/garmin.c index c156097b..f51e19ae 100644 --- a/src/garmin.c +++ b/src/garmin.c @@ -448,7 +448,6 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void { dc_status_t status = DC_STATUS_SUCCESS; garmin_device_t *device = (garmin_device_t *) abstract; - dc_parser_t *parser; char pathname[PATH_MAX]; char pathname_input[PATH_MAX]; size_t pathlen; @@ -539,16 +538,12 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void free(files.array); return DC_STATUS_NOMEMORY; } - if ((rc = garmin_parser_create(&parser, abstract->context) != DC_STATUS_SUCCESS)) { - ERROR (abstract->context, "Failed to create parser for dive verification."); - free(files.array); - return rc; - } dc_event_devinfo_t devinfo; dc_event_devinfo_t *devinfo_p = &devinfo; for (int i = 0; i < files.nr; i++) { const char *name = files.array[i].name; + dc_parser_t *parser; const unsigned char *data; unsigned int size; short is_dive = 0; @@ -574,7 +569,14 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void data = dc_buffer_get_data(file); size = dc_buffer_get_size(file); - is_dive = !device->model || garmin_parser_is_dive(parser, data, size, devinfo_p); + status = garmin_parser_create(&parser, abstract->context, data, size); + if (status != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to create parser for dive verification."); + free(files.array); + return rc; + } + + is_dive = !device->model || garmin_parser_is_dive(parser, devinfo_p); if (devinfo_p) { // first time we came through here, let's emit the // devinfo and vendor events @@ -583,6 +585,7 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void } if (!is_dive) { DEBUG(abstract->context, "decided %s isn't a dive.", name); + dc_parser_destroy(parser); continue; } @@ -591,10 +594,10 @@ garmin_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void progress.current++; device_event_emit(abstract, DC_EVENT_PROGRESS, &progress); + dc_parser_destroy(parser); } free(files.array); - dc_parser_destroy(parser); dc_buffer_free(file); return status; } diff --git a/src/garmin.h b/src/garmin.h index ade3d6c0..88bb6523 100644 --- a/src/garmin.h +++ b/src/garmin.h @@ -35,12 +35,12 @@ dc_status_t garmin_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model); dc_status_t -garmin_parser_create (dc_parser_t **parser, dc_context_t *context); +garmin_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size); // we need to be able to call into the parser to check if the // files that we find are actual dives int -garmin_parser_is_dive (dc_parser_t *abstract, const unsigned char *data, unsigned int size, dc_event_devinfo_t *devinfo_p); +garmin_parser_is_dive (dc_parser_t *abstract, dc_event_devinfo_t *devinfo_p); // The dive names are of the form "2018-08-20-10-23-30.fit" // With the terminating zero, that's 24 bytes. diff --git a/src/garmin_parser.c b/src/garmin_parser.c index 466c6d21..c344ebd9 100644 --- a/src/garmin_parser.c +++ b/src/garmin_parser.c @@ -232,12 +232,12 @@ static void garmin_event(struct garmin_parser_t *garmin, if (!sample.event.name) return; - garmin->callback(DC_SAMPLE_EVENT, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_EVENT, &sample, garmin->userdata); return; case 57: sample.gasmix = data; - garmin->callback(DC_SAMPLE_GASMIX, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_GASMIX, &sample, garmin->userdata); dc_tankinfo_t *tankinfo = &garmin->cache.tankinfo[data]; if (!garmin->dive.current_tankinfo || (*tankinfo & DC_TANKINFO_CC_DILUENT) != (*garmin->dive.current_tankinfo & DC_TANKINFO_CC_DILUENT)) { @@ -250,7 +250,7 @@ static void garmin_event(struct garmin_parser_t *garmin, } sample2.event.flags = 2 << SAMPLE_FLAGS_SEVERITY_SHIFT; - garmin->callback(DC_SAMPLE_EVENT, sample2, garmin->userdata); + garmin->callback(DC_SAMPLE_EVENT, &sample2, garmin->userdata); garmin->dive.current_tankinfo = tankinfo; } @@ -324,7 +324,7 @@ static void flush_pending_record(struct garmin_parser_t *garmin) sample.deco.type = DC_DECO_DECOSTOP; sample.deco.time = record->stop_time; sample.deco.depth = record->ceiling; - garmin->callback(DC_SAMPLE_DECO, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_DECO, &sample, garmin->userdata); } if (pending & RECORD_EVENT) { @@ -337,19 +337,19 @@ static void flush_pending_record(struct garmin_parser_t *garmin) sample.pressure.tank = find_tank_index(garmin, record->sensor); sample.pressure.value = record->pressure / 100.0; - garmin->callback(DC_SAMPLE_PRESSURE, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_PRESSURE, &sample, garmin->userdata); } if (pending & RECORD_SETPOINT_CHANGE) { dc_sample_value_t sample = {0}; sample.setpoint = record->setpoint_actual_cbar / 100.0; - garmin->callback(DC_SAMPLE_SETPOINT, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_SETPOINT, &sample, garmin->userdata); } } -static dc_status_t garmin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); +static dc_status_t garmin_parser_set_data (garmin_parser_t *garmin, const unsigned char *data, unsigned int size); static dc_status_t garmin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t garmin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t garmin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -357,7 +357,6 @@ static dc_status_t garmin_parser_samples_foreach (dc_parser_t *abstract, dc_samp static const dc_parser_vtable_t garmin_parser_vtable = { sizeof(garmin_parser_t), DC_FAMILY_GARMIN, - garmin_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -368,7 +367,7 @@ static const dc_parser_vtable_t garmin_parser_vtable = { }; dc_status_t -garmin_parser_create (dc_parser_t **out, dc_context_t *context) +garmin_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size) { garmin_parser_t *parser = NULL; @@ -376,12 +375,14 @@ garmin_parser_create (dc_parser_t **out, dc_context_t *context) return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (garmin_parser_t *) dc_parser_allocate (context, &garmin_parser_vtable); + parser = (garmin_parser_t *) dc_parser_allocate (context, &garmin_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; } + garmin_parser_set_data(parser, data, size); + *out = (dc_parser_t *) parser; return DC_STATUS_SUCCESS; @@ -509,7 +510,7 @@ DECLARE_FIELD(ANY, timestamp, UINT32) // Now we're ready to actually update the sample times garmin->record_data.time = data+1; sample.time = data; - garmin->callback(DC_SAMPLE_TIME, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_TIME, &sample, garmin->userdata); } } DECLARE_FIELD(ANY, message_index, UINT16) { garmin->record_data.index = data; } @@ -556,7 +557,7 @@ DECLARE_FIELD(RECORD, heart_rate, UINT8) // bpm if (garmin->callback) { dc_sample_value_t sample = {0}; sample.heartbeat = data; - garmin->callback(DC_SAMPLE_HEARTBEAT, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_HEARTBEAT, &sample, garmin->userdata); } } DECLARE_FIELD(RECORD, cadence, UINT8) { } // cadence @@ -568,7 +569,7 @@ DECLARE_FIELD(RECORD, temperature, SINT8) // degrees C if (garmin->callback) { dc_sample_value_t sample = {0}; sample.temperature = data; - garmin->callback(DC_SAMPLE_TEMPERATURE, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_TEMPERATURE, &sample, garmin->userdata); } } DECLARE_FIELD(RECORD, abs_pressure, UINT32) {} // Pascal @@ -577,7 +578,7 @@ DECLARE_FIELD(RECORD, depth, UINT32) // mm if (garmin->callback) { dc_sample_value_t sample = {0}; sample.depth = data / 1000.0; - garmin->callback(DC_SAMPLE_DEPTH, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_DEPTH, &sample, garmin->userdata); } } DECLARE_FIELD(RECORD, next_stop_depth, UINT32) // mm @@ -595,7 +596,7 @@ DECLARE_FIELD(RECORD, tts, UINT32) if (garmin->callback) { dc_sample_value_t sample = {0}; sample.time = data; - garmin->callback(DC_SAMPLE_TTS, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_TTS, &sample, garmin->userdata); } } DECLARE_FIELD(RECORD, ndl, UINT32) // s @@ -604,7 +605,7 @@ DECLARE_FIELD(RECORD, ndl, UINT32) // s dc_sample_value_t sample = {0}; sample.deco.type = DC_DECO_NDL; sample.deco.time = data; - garmin->callback(DC_SAMPLE_DECO, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_DECO, &sample, garmin->userdata); } } DECLARE_FIELD(RECORD, cns_load, UINT8) @@ -612,7 +613,7 @@ DECLARE_FIELD(RECORD, cns_load, UINT8) if (garmin->callback) { dc_sample_value_t sample = {0}; sample.cns = data / 100.0; - garmin->callback(DC_SAMPLE_CNS, sample, garmin->userdata); + garmin->callback(DC_SAMPLE_CNS, &sample, garmin->userdata); } } DECLARE_FIELD(RECORD, n2_load, UINT16) { } // percent @@ -1586,10 +1587,8 @@ static void add_gps_string(garmin_parser_t *garmin, const char *desc, struct pos } int -garmin_parser_is_dive (dc_parser_t *abstract, const unsigned char *data, unsigned int size, dc_event_devinfo_t *devinfo_p) +garmin_parser_is_dive (dc_parser_t *abstract, dc_event_devinfo_t *devinfo_p) { - // set up the parser and extract data - dc_parser_set_data(abstract, data, size); garmin_parser_t *garmin = (garmin_parser_t *) abstract; if (devinfo_p) { @@ -1621,10 +1620,8 @@ static void add_sensor_string(garmin_parser_t *garmin, const char *desc, const s } static dc_status_t -garmin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) +garmin_parser_set_data (garmin_parser_t *garmin, const unsigned char *data, unsigned int size) { - garmin_parser_t *garmin = (garmin_parser_t *) abstract; - /* Walk the data once without a callback to set up the core fields */ garmin->callback = NULL; garmin->userdata = NULL; diff --git a/src/hw_ostc.h b/src/hw_ostc.h index 5635e6d3..922fa02c 100644 --- a/src/hw_ostc.h +++ b/src/hw_ostc.h @@ -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 } diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index 023c978c..f0cb7b19 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -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) diff --git a/src/hw_ostc3.h b/src/hw_ostc3.h index 1e7720a3..f2d7bbf1 100644 --- a/src/hw_ostc3.h +++ b/src/hw_ostc3.h @@ -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 } diff --git a/src/hw_ostc_parser.c b/src/hw_ostc_parser.c index 92017421..6f09107f 100644 --- a/src/hw_ostc_parser.c +++ b/src/hw_ostc_parser.c @@ -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) -{ - return hw_ostc_parser_create_internal (out, context, serial, 1, model); -} - -static dc_status_t -hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) +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) { - 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; + return hw_ostc_parser_create_internal (out, context, data, size, 1, model, serial); } - 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,25 +1067,25 @@ 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, ccr); 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); - offset += 2; length -= 2; } @@ -1105,22 +1096,21 @@ 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) { - // OSTC4 reports gas changes to another diluent with an offset - idx -= OSTC4_CC_DILUENT_GAS_OFFSET; + unsigned int id = data[offset]; + if (parser->model == OSTC4 && ccr && id > parser->nfixed) { + // Fix the OSTC4 diluent index. + id -= parser->nfixed; } - 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); - offset++; length--; } @@ -1133,7 +1123,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,25 +1137,25 @@ 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); - - hw_ostc_notify_bailout(parser, data, idx, callback, userdata); - + if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); + hw_ostc_notify_bailout(parser, data, idx, callback, userdata); offset += 2; length -= 2; } @@ -1197,7 +1187,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 +1202,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 +1217,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 +1228,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 +1241,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 +1261,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,25 +1275,25 @@ 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); - offset += 2; length -= 2; } @@ -1319,7 +1311,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); +} diff --git a/src/irda.c b/src/irda.c index a5bb8e45..dd5397b4 100644 --- a/src/irda.c +++ b/src/irda.c @@ -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; } diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 85d99ec8..b346ef01 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -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 diff --git a/src/liquivision_lynx.h b/src/liquivision_lynx.h index 52e72944..dd278b45 100644 --- a/src/liquivision_lynx.h +++ b/src/liquivision_lynx.h @@ -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 } diff --git a/src/liquivision_lynx_parser.c b/src/liquivision_lynx_parser.c index 764d20e3..c336b6a0 100644 --- a/src/liquivision_lynx_parser.c +++ b/src/liquivision_lynx_parser.c @@ -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; } diff --git a/src/mares_darwin.h b/src/mares_darwin.h index a902014f..35efbcb2 100644 --- a/src/mares_darwin.h +++ b/src/mares_darwin.h @@ -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 } diff --git a/src/mares_darwin_parser.c b/src/mares_darwin_parser.c index 88e831c8..bebd89cd 100644 --- a/src/mares_darwin_parser.c +++ b/src/mares_darwin_parser.c @@ -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); } } diff --git a/src/mares_iconhd.c b/src/mares_iconhd.c index eb4f337a..b86ff0d4 100644 --- a/src/mares_iconhd.c +++ b/src/mares_iconhd.c @@ -21,7 +21,6 @@ #include // memcpy, memcmp #include // malloc, free -#include // 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; diff --git a/src/mares_iconhd.h b/src/mares_iconhd.h index 1354f775..c055012d 100644 --- a/src/mares_iconhd.h +++ b/src/mares_iconhd.h @@ -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 } diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 50cf6f74..08dbea52 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -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."); } diff --git a/src/mares_nemo.h b/src/mares_nemo.h index c7a162bd..1847d0f3 100644 --- a/src/mares_nemo.h +++ b/src/mares_nemo.h @@ -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 } diff --git a/src/mares_nemo_parser.c b/src/mares_nemo_parser.c index 2f26605c..cb3e3bfe 100644 --- a/src/mares_nemo_parser.c +++ b/src/mares_nemo_parser.c @@ -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); } } } diff --git a/src/mclean_extreme.h b/src/mclean_extreme.h index c388bd47..fd7c6bcd 100644 --- a/src/mclean_extreme.h +++ b/src/mclean_extreme.h @@ -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 } diff --git a/src/mclean_extreme_parser.c b/src/mclean_extreme_parser.c index 694bf603..b9de4950 100644 --- a/src/mclean_extreme_parser.c +++ b/src/mclean_extreme_parser.c @@ -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; diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index a032f9cf..d9f3a6d6 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -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 */ diff --git a/src/oceanic_atom2.h b/src/oceanic_atom2.h index 657c7196..201ac320 100644 --- a/src/oceanic_atom2.h +++ b/src/oceanic_atom2.h @@ -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 } diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index edb652d0..fe50796d 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -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++; diff --git a/src/oceanic_veo250.h b/src/oceanic_veo250.h index fc79375a..5d24f74b 100644 --- a/src/oceanic_veo250.h +++ b/src/oceanic_veo250.h @@ -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 } diff --git a/src/oceanic_veo250_parser.c b/src/oceanic_veo250_parser.c index 90d33830..096e47c8 100644 --- a/src/oceanic_veo250_parser.c +++ b/src/oceanic_veo250_parser.c @@ -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; diff --git a/src/oceanic_vtpro.h b/src/oceanic_vtpro.h index 6a3c2cd6..3928adf5 100644 --- a/src/oceanic_vtpro.h +++ b/src/oceanic_vtpro.h @@ -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 } diff --git a/src/oceanic_vtpro_parser.c b/src/oceanic_vtpro_parser.c index 9650c496..ec380b32 100644 --- a/src/oceanic_vtpro_parser.c +++ b/src/oceanic_vtpro_parser.c @@ -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; diff --git a/src/oceans_s1.h b/src/oceans_s1.h index 825d3093..e5e43f8d 100644 --- a/src/oceans_s1.h +++ b/src/oceans_s1.h @@ -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 } diff --git a/src/oceans_s1_parser.c b/src/oceans_s1_parser.c index 8b4cfbd8..cce50312 100644 --- a/src/oceans_s1_parser.c +++ b/src/oceans_s1_parser.c @@ -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); } } diff --git a/src/parser-private.h b/src/parser-private.h index af1a76e8..73e2e592 100644 --- a/src/parser-private.h +++ b/src/parser-private.h @@ -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 } diff --git a/src/parser.c b/src/parser.c index b2530704..840c9198 100644 --- a/src/parser.c +++ b/src/parser.c @@ -20,6 +20,7 @@ */ #include +#include #include #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,133 +86,133 @@ 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; // Not merged upstream yet case DC_FAMILY_GARMIN: - rc = garmin_parser_create (&parser, context); + rc = garmin_parser_create (&parser, context, data, size); break; } @@ -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; - parser->data = NULL; - parser->size = 0; + 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; diff --git a/src/reefnet_sensus.h b/src/reefnet_sensus.h index a021b86e..38157dcc 100644 --- a/src/reefnet_sensus.h +++ b/src/reefnet_sensus.h @@ -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 } diff --git a/src/reefnet_sensus_parser.c b/src/reefnet_sensus_parser.c index 00c3b477..29e7f464 100644 --- a/src/reefnet_sensus_parser.c +++ b/src/reefnet_sensus_parser.c @@ -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. diff --git a/src/reefnet_sensuspro.h b/src/reefnet_sensuspro.h index 99325155..f187f935 100644 --- a/src/reefnet_sensuspro.h +++ b/src/reefnet_sensuspro.h @@ -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 } diff --git a/src/reefnet_sensuspro_parser.c b/src/reefnet_sensuspro_parser.c index ad371d79..5d6fd5eb 100644 --- a/src/reefnet_sensuspro_parser.c +++ b/src/reefnet_sensuspro_parser.c @@ -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; } diff --git a/src/reefnet_sensusultra.h b/src/reefnet_sensusultra.h index af73c8a6..1cefc9c9 100644 --- a/src/reefnet_sensusultra.h +++ b/src/reefnet_sensusultra.h @@ -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 } diff --git a/src/reefnet_sensusultra_parser.c b/src/reefnet_sensusultra_parser.c index bc52f1f6..670a0c3c 100644 --- a/src/reefnet_sensusultra_parser.c +++ b/src/reefnet_sensusultra_parser.c @@ -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; } diff --git a/src/seac_screen.h b/src/seac_screen.h index 64c15b65..4ff05eae 100644 --- a/src/seac_screen.h +++ b/src/seac_screen.h @@ -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 } diff --git a/src/seac_screen_parser.c b/src/seac_screen_parser.c index c4a855c3..07553d6c 100644 --- a/src/seac_screen_parser.c +++ b/src/seac_screen_parser.c @@ -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) { diff --git a/src/serial_posix.c b/src/serial_posix.c index a189e150..792a1c9f 100644 --- a/src/serial_posix.c +++ b/src/serial_posix.c @@ -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; } diff --git a/src/serial_win32.c b/src/serial_win32.c index aeeeb830..e506cbd4 100644 --- a/src/serial_win32.c +++ b/src/serial_win32.c @@ -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; } diff --git a/src/shearwater_common.c b/src/shearwater_common.c index bea08898..43da4551 100644 --- a/src/shearwater_common.c +++ b/src/shearwater_common.c @@ -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 doesn’t 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,230 @@ 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; + 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_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id) +dc_status_t +shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size) { - dc_device_t *abstract = (dc_device_t *)device; + dc_status_t status = DC_STATUS_SUCCESS; + 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; + if (size + 3 > SZ_PACKET) { + return DC_STATUS_INVALIDARGS; } - 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; + // 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; } // 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."); - + 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; } - return rc; + return status; } - -dc_status_t shearwater_common_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime) +dc_status_t +shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime) { - shearwater_common_device_t *device = (shearwater_common_device_t *)abstract; + dc_status_t status = DC_STATUS_SUCCESS; + dc_device_t *abstract = (dc_device_t *) device; - dc_datetime_t local_time; - memcpy(&local_time, datetime, sizeof(local_time)); + // Convert to local time. + dc_datetime_t local = *datetime; + local.timezone = DC_TIMEZONE_NONE; - // We need to supply a unix timestamp in _local_ time - local_time.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; + } - dc_ticks_t unix_timestamp = dc_datetime_mktime(&local_time); - if (unix_timestamp == -1) { - ERROR(abstract->context, "Invalid date/time value specified."); + const unsigned char timestamp[] = { + (ticks >> 24) & 0xFF, + (ticks >> 16) & 0xFF, + (ticks >> 8) & 0xFF, + (ticks ) & 0xFF, + }; - return DC_STATUS_INVALIDARGS; + 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; } - 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 status; +} - return DC_STATUS_NOMEMORY; +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; } - char shearwater_timestamp[] = { - (unix_timestamp >> 24) & 0xFF, - (unix_timestamp >> 16) & 0xFF, - (unix_timestamp >> 8) & 0xFF, - unix_timestamp & 0xFF, + const unsigned char timestamp[] = { + (ticks >> 24) & 0xFF, + (ticks >> 16) & 0xFF, + (ticks >> 8) & 0xFF, + (ticks ) & 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."); + 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; } - dc_buffer_free(buffer); - - return rc; -} + int timezone = datetime->timezone / 60; + const unsigned char offset[] = { + (timezone >> 24) & 0xFF, + (timezone >> 16) & 0xFF, + (timezone >> 8) & 0xFF, + (timezone ) & 0xFF, + }; -dc_status_t shearwater_common_read_model(shearwater_common_device_t *device, unsigned int *model) -{ - dc_buffer_t *buffer = dc_buffer_new(SZ_PACKET); - if (buffer == NULL) { - ERROR(device->base.context, "Insufficient buffer space available."); - return DC_STATUS_NOMEMORY; + 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; } - // 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); + // 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}; - return rc; + 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; } - // Convert and map to the model number. - unsigned int hardware = array_uint_be(dc_buffer_get_data(buffer), dc_buffer_get_size(buffer)); + return status; +} + +unsigned int +shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware) +{ + unsigned int model = 0; + 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; } diff --git a/src/shearwater_common.h b/src/shearwater_common.h index 397d9508..377c8df0 100644 --- a/src/shearwater_common.h +++ b/src/shearwater_common.h @@ -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); diff --git a/src/shearwater_petrel.c b/src/shearwater_petrel.c index 3b0a0b31..7ec18ff8 100644 --- a/src/shearwater_petrel.c +++ b/src/shearwater_petrel.c @@ -44,81 +44,9 @@ typedef struct shearwater_petrel_device_t { unsigned char fingerprint[4]; } 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 +153,48 @@ 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); + + // Read the hardware type. + unsigned char rsp_hardware[2] = {0}; + rc = shearwater_common_rdbi (&device->base, ID_HARDWARE, rsp_hardware, sizeof(rsp_hardware)); + if (rc != DC_STATUS_SUCCESS) { + ERROR (abstract->context, "Failed to read the hardware type."); + return rc; + } - unsigned int model = 0; - shearwater_common_read_model((shearwater_common_device_t *)device, &model); + // Convert and map to the model number. + unsigned int hardware = array_uint16_be (rsp_hardware); + unsigned int model = shearwater_common_get_model (&device->base, hardware); // Emit a device info event. dc_event_devinfo_t devinfo; @@ -283,22 +204,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 +224,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 +351,28 @@ 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; + + // 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_uint16_be (rsp_hardware); + unsigned int model = shearwater_common_get_model (device, hardware); + + if (model == TERIC) { + return shearwater_common_timesync_utc (device, datetime); + } else { + return shearwater_common_timesync_local (device, datetime); + } +} diff --git a/src/shearwater_petrel.h b/src/shearwater_petrel.h index 0d8593cb..ea52ee96 100644 --- a/src/shearwater_petrel.h +++ b/src/shearwater_petrel.h @@ -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 } diff --git a/src/shearwater_predator.c b/src/shearwater_predator.c index cb713a9e..fffd511f 100644 --- a/src/shearwater_predator.c +++ b/src/shearwater_predator.c @@ -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); +} diff --git a/src/shearwater_predator.h b/src/shearwater_predator.h index 2682e0a5..419c4b84 100644 --- a/src/shearwater_predator.h +++ b/src/shearwater_predator.h @@ -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 } diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index 419dd354..44c0c5b1 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -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 { @@ -120,6 +122,7 @@ typedef struct shearwater_predator_tank_t { unsigned int pressure_reserve; unsigned int serial; char name[2]; + dc_usage_t usage; unsigned int battery; } shearwater_predator_tank_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) { @@ -260,10 +270,12 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig parser->tank[i].pressure_reserve = 0; parser->tank[i].serial = 0; memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name)); + parser->tank[i].usage = DC_USAGE_NONE; parser->tank[i].battery = 0; 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 haven’t 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); } } diff --git a/src/sporasub_sp2.h b/src/sporasub_sp2.h index de2ca42a..6b21c458 100644 --- a/src/sporasub_sp2.h +++ b/src/sporasub_sp2.h @@ -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 } diff --git a/src/sporasub_sp2_parser.c b/src/sporasub_sp2_parser.c index 5ac44b8a..37f02115 100644 --- a/src/sporasub_sp2_parser.c +++ b/src/sporasub_sp2_parser.c @@ -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; diff --git a/src/suunto_d9.h b/src/suunto_d9.h index a522fb87..a7bf60d0 100644 --- a/src/suunto_d9.h +++ b/src/suunto_d9.h @@ -36,7 +36,7 @@ dc_status_t suunto_d9_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model); dc_status_t -suunto_d9_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial); +suunto_d9_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 } diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 9eafeb15..55d45ef9 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -94,7 +94,6 @@ typedef struct sample_info_t { unsigned int divisor; } sample_info_t; -static dc_status_t suunto_d9_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -102,7 +101,6 @@ static dc_status_t suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_s static const dc_parser_vtable_t suunto_d9_parser_vtable = { sizeof(suunto_d9_parser_t), DC_FAMILY_SUUNTO_D9, - suunto_d9_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -253,7 +251,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) } dc_status_t -suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial) +suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial) { suunto_d9_parser_t *parser = NULL; @@ -261,7 +259,7 @@ suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (suunto_d9_parser_t *) dc_parser_allocate (context, &suunto_d9_parser_vtable); + parser = (suunto_d9_parser_t *) dc_parser_allocate (context, &suunto_d9_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -288,28 +286,6 @@ suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int } -static dc_status_t -suunto_d9_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - suunto_d9_parser_t *parser = (suunto_d9_parser_t *) abstract; - - // Reset the cache. - parser->cached = 0; - parser->id = 0; - parser->mode = AIR; - parser->ngasmixes = 0; - parser->nccr = 0; - for (unsigned int i = 0; i < NGASMIXES; ++i) { - parser->oxygen[i] = 0; - parser->helium[i] = 0; - } - parser->gasmix = 0; - parser->config = 0; - - return DC_STATUS_SUCCESS; -} - - static dc_status_t suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { @@ -395,6 +371,7 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne *((unsigned int *) value) = parser->ngasmixes; break; case DC_FIELD_GASMIX: + gasmix->usage = DC_USAGE_NONE; gasmix->helium = parser->helium[flags] / 100.0; gasmix->oxygen = parser->oxygen[flags] / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; @@ -539,8 +516,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca dc_sample_value_t sample = {0}; // 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); // Sample data. for (unsigned int i = 0; i < nparams; ++i) { @@ -555,19 +532,19 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca case 0x64: // Depth value = array_uint16_le (data + offset); sample.depth = value / (double) info[i].divisor; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); break; case 0x68: // Pressure value = array_uint16_le (data + offset); if (value != 0xFFFF) { sample.pressure.tank = 0; sample.pressure.value = value / (double) info[i].divisor; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata); } break; case 0x74: // Temperature sample.temperature = (signed char) data[offset] / (double) info[i].divisor; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); + if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata); break; default: // Unknown sample type ERROR (abstract->context, "Unknown sample type 0x%02x.", info[i].type); @@ -585,7 +562,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca return DC_STATUS_DATAFORMAT; } sample.gasmix = parser->gasmix; - if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); } // Events @@ -625,7 +602,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca seconds = data[offset + 1]; sample.event.type = SAMPLE_EVENT_SURFACE; sample.event.time = seconds; - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); offset += 2; break; case 0x03: // Event @@ -731,7 +708,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca sample.event.flags = SAMPLE_FLAGS_BEGIN; sample.event.time = seconds; if (sample.event.type != SAMPLE_EVENT_NONE) { - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); } offset += 2; break; @@ -751,7 +728,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca sample.event.value = heading / 2; } sample.event.time = seconds; - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); offset += 4; break; case 0x05: // Gas Change @@ -767,7 +744,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca return DC_STATUS_DATAFORMAT; } sample.gasmix = idx; - if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); offset += 2; break; case 0x06: // Gas Change @@ -801,10 +778,10 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca return DC_STATUS_DATAFORMAT; } sample.gasmix = idx; - if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); if (type & 0x80) { sample.setpoint = ppo2 / 10.0; - if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata); + if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata); } offset += length; break; @@ -829,7 +806,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca } 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); time += interval_sample; nsamples++; diff --git a/src/suunto_eon.h b/src/suunto_eon.h index 5e99a695..9c605ebb 100644 --- a/src/suunto_eon.h +++ b/src/suunto_eon.h @@ -36,7 +36,7 @@ dc_status_t suunto_eon_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream); dc_status_t -suunto_eon_parser_create (dc_parser_t **parser, dc_context_t *context, int spyder); +suunto_eon_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, int spyder); #ifdef __cplusplus } diff --git a/src/suunto_eon_parser.c b/src/suunto_eon_parser.c index 8e80aca4..94370a33 100644 --- a/src/suunto_eon_parser.c +++ b/src/suunto_eon_parser.c @@ -43,7 +43,6 @@ struct suunto_eon_parser_t { unsigned int nitrox; }; -static dc_status_t suunto_eon_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t suunto_eon_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t suunto_eon_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -51,7 +50,6 @@ static dc_status_t suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_ static const dc_parser_vtable_t suunto_eon_parser_vtable = { sizeof(suunto_eon_parser_t), DC_FAMILY_SUUNTO_EON, - suunto_eon_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -112,7 +110,7 @@ suunto_eon_parser_cache (suunto_eon_parser_t *parser) } dc_status_t -suunto_eon_parser_create (dc_parser_t **out, dc_context_t *context, int spyder) +suunto_eon_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, int spyder) { suunto_eon_parser_t *parser = NULL; @@ -120,7 +118,7 @@ suunto_eon_parser_create (dc_parser_t **out, dc_context_t *context, int spyder) return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (suunto_eon_parser_t *) dc_parser_allocate (context, &suunto_eon_parser_vtable); + parser = (suunto_eon_parser_t *) dc_parser_allocate (context, &suunto_eon_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -140,22 +138,6 @@ suunto_eon_parser_create (dc_parser_t **out, dc_context_t *context, int spyder) } -static dc_status_t -suunto_eon_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - suunto_eon_parser_t *parser = (suunto_eon_parser_t *) abstract; - - // Reset the cache. - parser->cached = 0; - parser->divetime = 0; - parser->maxdepth = 0; - parser->marker = 0; - parser->nitrox = 0; - - return DC_STATUS_SUCCESS; -} - - static dc_status_t suunto_eon_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { @@ -225,6 +207,7 @@ suunto_eon_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign *((unsigned int *) value) = 1; break; case DC_FIELD_GASMIX: + gasmix->usage = DC_USAGE_NONE; gasmix->helium = 0.0; gasmix->oxygen = oxygen / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; @@ -242,6 +225,7 @@ suunto_eon_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign tank->gasmix = 0; tank->beginpressure = beginpressure; tank->endpressure = endpressure; + tank->usage = DC_USAGE_NONE; break; case DC_FIELD_TEMPERATURE_MINIMUM: if (parser->spyder) @@ -273,15 +257,15 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c // Time sample.time = 0; - if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + if (callback) callback (DC_SAMPLE_TIME, &sample, userdata); // Depth (0 ft) sample.depth = 0; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); // Initial gas mix. sample.gasmix = 0; - if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); unsigned int depth = 0; unsigned int time = 0; @@ -294,8 +278,8 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c if (complete) { // 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); complete = 0; } @@ -305,7 +289,7 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c // Depth (ft). sample.depth = depth * FEET; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); complete = 1; } else { @@ -333,7 +317,7 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c } if (sample.event.type != SAMPLE_EVENT_NONE) { - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); } } } @@ -341,13 +325,13 @@ suunto_eon_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c // Time if (complete) { 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 (0 ft) sample.depth = 0; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); return DC_STATUS_SUCCESS; } diff --git a/src/suunto_eonsteel.h b/src/suunto_eonsteel.h index 28001070..cb18296e 100644 --- a/src/suunto_eonsteel.h +++ b/src/suunto_eonsteel.h @@ -35,7 +35,7 @@ dc_status_t suunto_eonsteel_device_open(dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model); dc_status_t -suunto_eonsteel_parser_create(dc_parser_t **parser, dc_context_t *context, unsigned int model); +suunto_eonsteel_parser_create(dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model); #ifdef __cplusplus } diff --git a/src/suunto_eonsteel_parser.c b/src/suunto_eonsteel_parser.c index 29472219..0147f515 100644 --- a/src/suunto_eonsteel_parser.c +++ b/src/suunto_eonsteel_parser.c @@ -445,8 +445,8 @@ static void sample_time(struct sample_data *info, unsigned short time_delta) dc_sample_value_t sample = {0}; info->time += time_delta; - sample.time = info->time / 1000; - if (info->callback) info->callback(DC_SAMPLE_TIME, sample, info->userdata); + sample.time = info->time; + if (info->callback) info->callback(DC_SAMPLE_TIME, &sample, info->userdata); } static void sample_depth(struct sample_data *info, unsigned short depth) @@ -457,7 +457,7 @@ static void sample_depth(struct sample_data *info, unsigned short depth) return; sample.depth = depth / 100.0; - if (info->callback) info->callback(DC_SAMPLE_DEPTH, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_DEPTH, &sample, info->userdata); } static void sample_temp(struct sample_data *info, short temp) @@ -468,7 +468,7 @@ static void sample_temp(struct sample_data *info, short temp) return; sample.temperature = temp / 10.0; - if (info->callback) info->callback(DC_SAMPLE_TEMPERATURE, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_TEMPERATURE, &sample, info->userdata); } static void sample_ndl(struct sample_data *info, short ndl) @@ -480,7 +480,8 @@ static void sample_ndl(struct sample_data *info, short ndl) sample.deco.type = DC_DECO_NDL; sample.deco.time = ndl; - if (info->callback) info->callback(DC_SAMPLE_DECO, sample, info->userdata); + sample.deco.tts = 0; + if (info->callback) info->callback(DC_SAMPLE_DECO, &sample, info->userdata); } static void sample_tts(struct sample_data *info, unsigned short tts) @@ -488,7 +489,7 @@ static void sample_tts(struct sample_data *info, unsigned short tts) if (tts != 0xffff) { dc_sample_value_t sample = {0}; sample.time = tts; - if (info->callback) info->callback(DC_SAMPLE_TTS, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_TTS, &sample, info->userdata); } } @@ -504,7 +505,8 @@ static void sample_ceiling(struct sample_data *info, unsigned short ceiling) sample.deco.type = DC_DECO_DECOSTOP; sample.deco.time = ceiling ? 60 : 0; sample.deco.depth = ceiling / 100.0; - if (info->callback) info->callback(DC_SAMPLE_DECO, sample, info->userdata); + sample.deco.tts = 0; // Fixme? DC_SAMPLE_TTS? + if (info->callback) info->callback(DC_SAMPLE_DECO, &sample, info->userdata); } } @@ -517,7 +519,7 @@ static void sample_heading(struct sample_data *info, unsigned short heading) sample.event.type = SAMPLE_EVENT_HEADING; sample.event.value = heading; - if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } static void sample_abspressure(struct sample_data *info, unsigned short pressure) @@ -532,7 +534,7 @@ static void sample_gastime(struct sample_data *info, short gastime) return; sample.rbt = gastime / 60; - if (info->callback) info->callback (DC_SAMPLE_RBT, sample, info->userdata); + if (info->callback) info->callback (DC_SAMPLE_RBT, &sample, info->userdata); } /* @@ -560,7 +562,7 @@ static void sample_pressure(struct sample_data *info, unsigned short pressure) sample.pressure.tank = info->gasnr-1; sample.pressure.value = pressure / 100.0; - if (info->callback) info->callback(DC_SAMPLE_PRESSURE, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_PRESSURE, &sample, info->userdata); } static void sample_bookmark_event(struct sample_data *info, unsigned short idx) @@ -570,7 +572,7 @@ static void sample_bookmark_event(struct sample_data *info, unsigned short idx) sample.event.type = SAMPLE_EVENT_BOOKMARK; sample.event.value = idx; - if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } static void sample_gas_switch_event(struct sample_data *info, unsigned short idx) @@ -582,7 +584,7 @@ static void sample_gas_switch_event(struct sample_data *info, unsigned short idx return; sample.gasmix = idx - 1; - if (info->callback) info->callback(DC_SAMPLE_GASMIX, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_GASMIX, &sample, info->userdata); } static const char *mixname(suunto_eonsteel_parser_t *eon, int idx) @@ -622,7 +624,7 @@ static void sample_insert_gas_event(struct sample_data *info, unsigned short idx sample.event.name = strdup(event); sample.event.flags = SAMPLE_FLAGS_SEVERITY_INFO; - info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } static void sample_remove_gas_event(struct sample_data *info, unsigned short idx) @@ -639,7 +641,7 @@ static void sample_remove_gas_event(struct sample_data *info, unsigned short idx sample.event.name = strdup(event); sample.event.flags = SAMPLE_FLAGS_SEVERITY_INFO; - info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } /* @@ -730,7 +732,7 @@ static void sample_event_state_value(const struct type_desc *desc, struct sample sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END; sample.event.flags |= 1 << SAMPLE_FLAGS_SEVERITY_SHIFT; - if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } static void sample_event_notify_type(const struct type_desc *desc, struct sample_data *info, unsigned char type) @@ -753,7 +755,7 @@ static void sample_event_notify_value(const struct type_desc *desc, struct sampl sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END; sample.event.flags |= 2 << SAMPLE_FLAGS_SEVERITY_SHIFT; - if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } @@ -777,7 +779,7 @@ static void sample_event_warning_value(const struct type_desc *desc, struct samp sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END; sample.event.flags |= 3 << SAMPLE_FLAGS_SEVERITY_SHIFT; - if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } static void sample_event_alarm_type(const struct type_desc *desc, struct sample_data *info, unsigned char type) @@ -801,7 +803,7 @@ static void sample_event_alarm_value(const struct type_desc *desc, struct sample sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END; sample.event.flags |= 4 << SAMPLE_FLAGS_SEVERITY_SHIFT; - if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_EVENT, &sample, info->userdata); } // enum:0=Low,1=High,2=Custom @@ -827,7 +829,7 @@ static void sample_setpoint_type(const struct type_desc *desc, struct sample_dat return; } - if (info->callback) info->callback(DC_SAMPLE_SETPOINT, sample, info->userdata); + if (info->callback) info->callback(DC_SAMPLE_SETPOINT, &sample, info->userdata); free(type); } @@ -1048,6 +1050,7 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi if (fabs(tank->volume - rint(tank->volume)) > 0.001) tank->type += DC_TANKINFO_IMPERIAL - DC_TANKINFO_METRIC; } + tank->usage = eon->cache.tankusage[flags]; } return dc_field_get(&eon->cache, type, flags, value); @@ -1106,6 +1109,7 @@ static dc_status_t add_gas_type(suunto_eonsteel_parser_t *eon, const struct type { int idx = eon->cache.GASMIX_COUNT; dc_tankinfo_t tankinfo = DC_TANKINFO_METRIC; + dc_usage_t usage = DC_USAGE_NONE; char *name; if (idx >= MAXGASES) @@ -1116,15 +1120,17 @@ static dc_status_t add_gas_type(suunto_eonsteel_parser_t *eon, const struct type if (!name) DEBUG(eon->base.context, "Unable to look up gas type %u in %s", type, desc->format); else if (!strcasecmp(name, "Diluent")) - tankinfo |= DC_TANKINFO_CC_DILUENT; + usage = DC_USAGE_DILUENT; else if (!strcasecmp(name, "Oxygen")) - tankinfo |= DC_TANKINFO_CC_O2; + usage = DC_USAGE_OXYGEN; else if (!strcasecmp(name, "None")) tankinfo = DC_TANKVOLUME_NONE; else if (strcasecmp(name, "Primary")) DEBUG(eon->base.context, "Unknown gas type %u (%s)", type, name); eon->cache.tankinfo[idx] = tankinfo; + eon->cache.tankusage[idx] = usage; + eon->cache.GASMIX[idx].usage = usage; eon->cache.initialized |= 1 << DC_FIELD_GASMIX_COUNT; eon->cache.initialized |= 1 << DC_FIELD_TANK_COUNT; @@ -1488,18 +1494,6 @@ static void show_all_descriptors(suunto_eonsteel_parser_t *eon) show_descriptor(eon, i, eon->type_desc+i); } -static dc_status_t -suunto_eonsteel_parser_set_data(dc_parser_t *parser, const unsigned char *data, unsigned int size) -{ - suunto_eonsteel_parser_t *eon = (suunto_eonsteel_parser_t *) parser; - - desc_free(eon->type_desc, MAXTYPE); - memset(eon->type_desc, 0, sizeof(eon->type_desc)); - initialize_field_caches(eon); - show_all_descriptors(eon); - return DC_STATUS_SUCCESS; -} - static dc_status_t suunto_eonsteel_parser_destroy(dc_parser_t *parser) { @@ -1513,7 +1507,6 @@ suunto_eonsteel_parser_destroy(dc_parser_t *parser) static const dc_parser_vtable_t suunto_eonsteel_parser_vtable = { sizeof(suunto_eonsteel_parser_t), DC_FAMILY_SUUNTO_EONSTEEL, - suunto_eonsteel_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -1524,14 +1517,14 @@ static const dc_parser_vtable_t suunto_eonsteel_parser_vtable = { }; dc_status_t -suunto_eonsteel_parser_create(dc_parser_t **out, dc_context_t *context, unsigned int model) +suunto_eonsteel_parser_create(dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model) { suunto_eonsteel_parser_t *parser = NULL; if (out == NULL) return DC_STATUS_INVALIDARGS; - parser = (suunto_eonsteel_parser_t *) dc_parser_allocate (context, &suunto_eonsteel_parser_vtable); + parser = (suunto_eonsteel_parser_t *) dc_parser_allocate (context, &suunto_eonsteel_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -1540,6 +1533,9 @@ suunto_eonsteel_parser_create(dc_parser_t **out, dc_context_t *context, unsigned memset(&parser->type_desc, 0, sizeof(parser->type_desc)); memset(&parser->cache, 0, sizeof(parser->cache)); + initialize_field_caches(parser); + show_all_descriptors(parser); + *out = (dc_parser_t *) parser; return DC_STATUS_SUCCESS; diff --git a/src/suunto_solution.h b/src/suunto_solution.h index 9d9e632d..0556ad71 100644 --- a/src/suunto_solution.h +++ b/src/suunto_solution.h @@ -35,7 +35,7 @@ dc_status_t suunto_solution_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream); dc_status_t -suunto_solution_parser_create (dc_parser_t **parser, dc_context_t *context); +suunto_solution_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size); #ifdef __cplusplus } diff --git a/src/suunto_solution_parser.c b/src/suunto_solution_parser.c index 59648d53..69c6977b 100644 --- a/src/suunto_solution_parser.c +++ b/src/suunto_solution_parser.c @@ -39,14 +39,12 @@ struct suunto_solution_parser_t { unsigned int maxdepth; }; -static dc_status_t suunto_solution_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t suunto_solution_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t suunto_solution_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); static const dc_parser_vtable_t suunto_solution_parser_vtable = { sizeof(suunto_solution_parser_t), DC_FAMILY_SUUNTO_SOLUTION, - suunto_solution_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -58,7 +56,7 @@ static const dc_parser_vtable_t suunto_solution_parser_vtable = { dc_status_t -suunto_solution_parser_create (dc_parser_t **out, dc_context_t *context) +suunto_solution_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size) { suunto_solution_parser_t *parser = NULL; @@ -66,7 +64,7 @@ suunto_solution_parser_create (dc_parser_t **out, dc_context_t *context) return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (suunto_solution_parser_t *) dc_parser_allocate (context, &suunto_solution_parser_vtable); + parser = (suunto_solution_parser_t *) dc_parser_allocate (context, &suunto_solution_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -83,20 +81,6 @@ suunto_solution_parser_create (dc_parser_t **out, dc_context_t *context) } -static dc_status_t -suunto_solution_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - suunto_solution_parser_t *parser = (suunto_solution_parser_t *) abstract; - - // Reset the cache. - parser->cached = 0; - parser->divetime = 0; - parser->maxdepth = 0; - - return DC_STATUS_SUCCESS; -} - - static dc_status_t suunto_solution_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) { @@ -151,6 +135,7 @@ suunto_solution_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u *((unsigned int *) value) = 1; break; case DC_FIELD_GASMIX: + gasmix->usage = DC_USAGE_NONE; gasmix->helium = 0.0; gasmix->oxygen = 0.21; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; @@ -183,8 +168,8 @@ suunto_solution_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac if (value < 0x7e || value > 0x82) { // Time (minutes). time += 3 * 60; - sample.time = time; - if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + sample.time = time * 1000; + if (callback) callback (DC_SAMPLE_TIME, &sample, userdata); // Depth (ft). depth += (signed char) value; @@ -197,12 +182,12 @@ suunto_solution_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac depth += (signed char) data[offset++]; } sample.depth = depth * FEET; - 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; } } else { @@ -227,7 +212,7 @@ suunto_solution_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac } if (sample.event.type != SAMPLE_EVENT_NONE) { - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); } } } diff --git a/src/suunto_vyper.h b/src/suunto_vyper.h index e6f88124..3babccf9 100644 --- a/src/suunto_vyper.h +++ b/src/suunto_vyper.h @@ -35,7 +35,7 @@ dc_status_t suunto_vyper_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream); dc_status_t -suunto_vyper_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial); +suunto_vyper_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int serial); #ifdef __cplusplus } diff --git a/src/suunto_vyper_parser.c b/src/suunto_vyper_parser.c index 20a52df1..3d4317a9 100644 --- a/src/suunto_vyper_parser.c +++ b/src/suunto_vyper_parser.c @@ -47,7 +47,6 @@ struct suunto_vyper_parser_t { unsigned int oxygen[NGASMIXES]; }; -static dc_status_t suunto_vyper_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t suunto_vyper_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -55,7 +54,6 @@ static dc_status_t suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, d static const dc_parser_vtable_t suunto_vyper_parser_vtable = { sizeof(suunto_vyper_parser_t), DC_FAMILY_SUUNTO_VYPER, - suunto_vyper_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -165,7 +163,7 @@ suunto_vyper_parser_cache (suunto_vyper_parser_t *parser) dc_status_t -suunto_vyper_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial) +suunto_vyper_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int serial) { suunto_vyper_parser_t *parser = NULL; @@ -173,7 +171,7 @@ suunto_vyper_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (suunto_vyper_parser_t *) dc_parser_allocate (context, &suunto_vyper_parser_vtable); + parser = (suunto_vyper_parser_t *) dc_parser_allocate (context, &suunto_vyper_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -196,25 +194,6 @@ suunto_vyper_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i } -static dc_status_t -suunto_vyper_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - suunto_vyper_parser_t *parser = (suunto_vyper_parser_t *) abstract; - - // Reset the cache. - parser->cached = 0; - parser->divetime = 0; - parser->maxdepth = 0; - parser->marker = 0; - parser->ngasmixes = 0; - for (unsigned int i = 0; i < NGASMIXES; ++i) { - parser->oxygen[i] = 0; - } - - return DC_STATUS_SUCCESS; -} - - static dc_status_t suunto_vyper_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { @@ -274,6 +253,7 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((unsigned int *) value) = parser->ngasmixes; break; case DC_FIELD_GASMIX: + gas->usage = DC_USAGE_NONE; gas->helium = 0.0; gas->oxygen = parser->oxygen[flags] / 100.0; gas->nitrogen = 1.0 - gas->oxygen - gas->helium; @@ -294,6 +274,7 @@ suunto_vyper_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi tank->gasmix = 0; tank->beginpressure = beginpressure; tank->endpressure = endpressure; + tank->usage = DC_USAGE_NONE; break; case DC_FIELD_TEMPERATURE_SURFACE: *((double *) value) = (signed char) data[8]; @@ -348,16 +329,16 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Time sample.time = 0; - if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + if (callback) callback (DC_SAMPLE_TIME, &sample, userdata); // Depth (0 ft) sample.depth = 0; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); // Initial gas mix if (!gauge) { sample.gasmix = 0; - if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); + if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata); } unsigned int depth = 0; @@ -371,8 +352,8 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t if (complete) { // 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); complete = 0; } @@ -382,7 +363,7 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Depth (ft). sample.depth = depth * FEET; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); complete = 1; } else { @@ -426,7 +407,7 @@ suunto_vyper_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); sample.event.type = SAMPLE_EVENT_NONE; break; default: // Unknown @@ -435,7 +416,7 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t } if (sample.event.type != SAMPLE_EVENT_NONE) { - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); } } } @@ -443,13 +424,13 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Time if (complete) { 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 (0 ft) sample.depth = 0; - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); return DC_STATUS_SUCCESS; } diff --git a/src/tecdiving_divecomputereu.h b/src/tecdiving_divecomputereu.h index 714ae43c..8eafb4e8 100644 --- a/src/tecdiving_divecomputereu.h +++ b/src/tecdiving_divecomputereu.h @@ -35,7 +35,7 @@ dc_status_t tecdiving_divecomputereu_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream); dc_status_t -tecdiving_divecomputereu_parser_create (dc_parser_t **parser, dc_context_t *context); +tecdiving_divecomputereu_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size); #ifdef __cplusplus } diff --git a/src/tecdiving_divecomputereu_parser.c b/src/tecdiving_divecomputereu_parser.c index d060996d..4f3f5142 100644 --- a/src/tecdiving_divecomputereu_parser.c +++ b/src/tecdiving_divecomputereu_parser.c @@ -36,7 +36,6 @@ struct tecdiving_divecomputereu_parser_t { dc_parser_t base; }; -static dc_status_t tecdiving_divecomputereu_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t tecdiving_divecomputereu_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t tecdiving_divecomputereu_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t tecdiving_divecomputereu_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -44,7 +43,6 @@ static dc_status_t tecdiving_divecomputereu_parser_samples_foreach (dc_parser_t static const dc_parser_vtable_t tecdiving_divecomputereu_parser_vtable = { sizeof(tecdiving_divecomputereu_parser_t), DC_FAMILY_TECDIVING_DIVECOMPUTEREU, - tecdiving_divecomputereu_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -56,7 +54,7 @@ static const dc_parser_vtable_t tecdiving_divecomputereu_parser_vtable = { dc_status_t -tecdiving_divecomputereu_parser_create (dc_parser_t **out, dc_context_t *context) +tecdiving_divecomputereu_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size) { tecdiving_divecomputereu_parser_t *parser = NULL; @@ -64,7 +62,7 @@ tecdiving_divecomputereu_parser_create (dc_parser_t **out, dc_context_t *context return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (tecdiving_divecomputereu_parser_t *) dc_parser_allocate (context, &tecdiving_divecomputereu_parser_vtable); + parser = (tecdiving_divecomputereu_parser_t *) dc_parser_allocate (context, &tecdiving_divecomputereu_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -76,13 +74,6 @@ tecdiving_divecomputereu_parser_create (dc_parser_t **out, dc_context_t *context } -static dc_status_t -tecdiving_divecomputereu_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - return DC_STATUS_SUCCESS; -} - - static dc_status_t tecdiving_divecomputereu_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { @@ -159,28 +150,29 @@ tecdiving_divecomputereu_parser_samples_foreach (dc_parser_t *abstract, dc_sampl // 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 = array_uint16_be (data + offset + 2); 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 char) data[offset]; sample.temperature = temperature; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); + if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata); // ppO2 unsigned int ppo2 = data[offset + 1]; - sample.ppo2 = ppo2 / 10.0; - if (callback) callback (DC_SAMPLE_PPO2, sample, userdata); + sample.ppo2.sensor = DC_SENSOR_NONE; + sample.ppo2.value = ppo2 / 10.0; + if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata); // Setpoint unsigned int setpoint = data[offset + 4]; sample.setpoint = setpoint / 10.0; - if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata); + if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata); offset += 8; } diff --git a/src/usb.c b/src/usb.c index 758c604b..d7074cb9 100644 --- a/src/usb.c +++ b/src/usb.c @@ -39,12 +39,23 @@ #include "common-private.h" #include "context-private.h" #include "iostream-private.h" -#include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" +#include "array.h" #define ISINSTANCE(device) dc_iostream_isinstance((device), &dc_usb_vtable) +typedef struct dc_usb_params_t { + unsigned int interface; + unsigned char endpoint_in; + unsigned char endpoint_out; +} dc_usb_params_t; + +typedef struct dc_usb_config_t { + dc_usb_desc_t desc; + dc_usb_params_t params; +} dc_usb_config_t; + typedef struct dc_usb_session_t { size_t refcount; #ifdef HAVE_LIBUSB @@ -120,6 +131,26 @@ static const dc_iostream_vtable_t dc_usb_vtable = { dc_usb_close, /* close */ }; +static const dc_usb_config_t g_usb_config[] = { + // Atomic Aquatics Cobalt + {{0x0471, 0x0888}, {0, 0x82, 0x02}}, +}; + +static const dc_usb_params_t * +dc_usb_params_find (const dc_usb_desc_t *desc) +{ + if (desc == NULL) + return NULL; + + for (size_t i = 0; i < C_ARRAY_SIZE(g_usb_config); ++i) { + if (g_usb_config[i].desc.vid == desc->vid && + g_usb_config[i].desc.pid == desc->pid) + return &g_usb_config[i].params; + } + + return NULL; +} + static dc_status_t syserror(int errcode) { @@ -305,11 +336,13 @@ dc_usb_iterator_next (dc_iterator_t *abstract, void *out) } dc_usb_desc_t usb = {dev.idVendor, dev.idProduct}; - dc_usb_params_t params = {0, 0, 0}; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USB, &usb, ¶ms)) { + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USB, &usb)) { continue; } + // Check for known USB parameters. + const dc_usb_params_t *params = dc_usb_params_find (&usb); + // Get the active configuration descriptor. struct libusb_config_descriptor *config = NULL; rc = libusb_get_active_config_descriptor (current, &config); @@ -325,7 +358,8 @@ dc_usb_iterator_next (dc_iterator_t *abstract, void *out) const struct libusb_interface *iface = &config->interface[i]; for (int j = 0; j < iface->num_altsetting; j++) { const struct libusb_interface_descriptor *desc = &iface->altsetting[j]; - if (interface == NULL && desc->bInterfaceNumber == params.interface) { + if (interface == NULL && + (params == NULL || params->interface == desc->bInterfaceNumber)) { interface = desc; } } @@ -349,12 +383,12 @@ dc_usb_iterator_next (dc_iterator_t *abstract, void *out) } if (ep_in == NULL && direction == LIBUSB_ENDPOINT_IN && - (params.endpoint_in == 0 || params.endpoint_in == desc->bEndpointAddress)) { + (params == NULL || params->endpoint_in == desc->bEndpointAddress)) { ep_in = desc; } if (ep_out == NULL && direction == LIBUSB_ENDPOINT_OUT && - (params.endpoint_out == 0 || params.endpoint_out == desc->bEndpointAddress)) { + (params == NULL || params->endpoint_out == desc->bEndpointAddress)) { ep_out = desc; } } diff --git a/src/usb_storage.c b/src/usb_storage.c index 8bad4922..ab33a03b 100644 --- a/src/usb_storage.c +++ b/src/usb_storage.c @@ -35,7 +35,6 @@ #include "context-private.h" #include "iostream-private.h" #include "iterator-private.h" -#include "descriptor-private.h" #include "timer.h" // Fake "device" that just contains the directory name that diff --git a/src/usbhid.c b/src/usbhid.c index acd20ef7..b7818e04 100644 --- a/src/usbhid.c +++ b/src/usbhid.c @@ -57,7 +57,6 @@ #include "common-private.h" #include "context-private.h" #include "iostream-private.h" -#include "descriptor-private.h" #include "iterator-private.h" #include "platform.h" @@ -438,8 +437,8 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) return syserror (rc); } - dc_usb_desc_t usb = {dev.idVendor, dev.idProduct}; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb, NULL)) { + dc_usbhid_desc_t usb = {dev.idVendor, dev.idProduct}; + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb)) { continue; } @@ -522,8 +521,8 @@ dc_usbhid_iterator_next (dc_iterator_t *abstract, void *out) struct hid_device_info *current = iterator->current; iterator->current = current->next; - dc_usb_desc_t usb = {current->vendor_id, current->product_id}; - if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb, NULL)) { + dc_usbhid_desc_t usb = {current->vendor_id, current->product_id}; + if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_USBHID, &usb)) { continue; } diff --git a/src/uwatec_memomouse.h b/src/uwatec_memomouse.h index 49ecf9e7..e038cf98 100644 --- a/src/uwatec_memomouse.h +++ b/src/uwatec_memomouse.h @@ -35,7 +35,7 @@ dc_status_t uwatec_memomouse_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream); dc_status_t -uwatec_memomouse_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime); +uwatec_memomouse_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size); #ifdef __cplusplus } diff --git a/src/uwatec_memomouse_parser.c b/src/uwatec_memomouse_parser.c index 3c818fa6..0849a3c6 100644 --- a/src/uwatec_memomouse_parser.c +++ b/src/uwatec_memomouse_parser.c @@ -38,7 +38,6 @@ struct uwatec_memomouse_parser_t { dc_ticks_t systime; }; -static dc_status_t uwatec_memomouse_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t uwatec_memomouse_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime); static dc_status_t uwatec_memomouse_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t uwatec_memomouse_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); @@ -47,7 +46,6 @@ static dc_status_t uwatec_memomouse_parser_samples_foreach (dc_parser_t *abstrac static const dc_parser_vtable_t uwatec_memomouse_parser_vtable = { sizeof(uwatec_memomouse_parser_t), DC_FAMILY_UWATEC_MEMOMOUSE, - uwatec_memomouse_parser_set_data, /* set_data */ uwatec_memomouse_parser_set_clock, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -59,7 +57,7 @@ static const dc_parser_vtable_t uwatec_memomouse_parser_vtable = { dc_status_t -uwatec_memomouse_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime) +uwatec_memomouse_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size) { uwatec_memomouse_parser_t *parser = NULL; @@ -67,15 +65,15 @@ uwatec_memomouse_parser_create (dc_parser_t **out, dc_context_t *context, unsign return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (uwatec_memomouse_parser_t *) dc_parser_allocate (context, &uwatec_memomouse_parser_vtable); + parser = (uwatec_memomouse_parser_t *) dc_parser_allocate (context, &uwatec_memomouse_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; } // Set the default values. - parser->devtime = devtime; - parser->systime = systime; + parser->devtime = 0; + parser->systime = 0; *out = (dc_parser_t*) parser; @@ -83,13 +81,6 @@ uwatec_memomouse_parser_create (dc_parser_t **out, dc_context_t *context, unsign } -static dc_status_t -uwatec_memomouse_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - return DC_STATUS_SUCCESS; -} - - static dc_status_t uwatec_memomouse_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime) { @@ -166,6 +157,7 @@ uwatec_memomouse_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, *((unsigned int *) value) = 1; break; case DC_FIELD_GASMIX: + gasmix->usage = DC_USAGE_NONE; gasmix->helium = 0.0; if (size >= header + 18) { if (is_oxygen) @@ -197,6 +189,7 @@ uwatec_memomouse_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, } tank->endpressure = 0.0; tank->gasmix = 0; + tank->usage = DC_USAGE_NONE; break; case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed char) data[15] / 4.0; @@ -250,17 +243,17 @@ uwatec_memomouse_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba offset += 2; // 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); // Depth (meters) sample.depth = depth * 10.0 / 64.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; } @@ -272,7 +265,8 @@ uwatec_memomouse_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba } 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); // Warnings for (unsigned int i = 0; i < 6; ++i) { @@ -301,7 +295,7 @@ uwatec_memomouse_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba break; } if (sample.event.type != SAMPLE_EVENT_NONE) { - if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata); } } } @@ -325,7 +319,7 @@ uwatec_memomouse_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba offset++; } - if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata); + if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata); } time += 20; diff --git a/src/uwatec_smart.c b/src/uwatec_smart.c index 63915c88..e0d34c1b 100644 --- a/src/uwatec_smart.c +++ b/src/uwatec_smart.c @@ -287,8 +287,6 @@ uwatec_smart_usbhid_send (uwatec_smart_device_t *device, unsigned char cmd, cons return DC_STATUS_INVALIDARGS; } - HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "cmd", data, size); - buf[0] = 0; buf[1] = size + 1; buf[2] = cmd; @@ -297,6 +295,8 @@ uwatec_smart_usbhid_send (uwatec_smart_device_t *device, unsigned char cmd, cons } memset(buf + 3 + size, 0, sizeof(buf) - (size + 3)); + HEXDUMP (abstract->context, DC_LOGLEVEL_DEBUG, "cmd", buf + 2, size + 1); + if (dc_iostream_get_transport(device->iostream) == DC_TRANSPORT_BLE) { rc = dc_iostream_write(device->iostream, buf + 1, size + 2, NULL); } else { diff --git a/src/uwatec_smart.h b/src/uwatec_smart.h index 49013c51..646cc977 100644 --- a/src/uwatec_smart.h +++ b/src/uwatec_smart.h @@ -35,7 +35,7 @@ dc_status_t uwatec_smart_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream); dc_status_t -uwatec_smart_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model); +uwatec_smart_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model); #ifdef __cplusplus } diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index bd849a80..8e455a7f 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -51,7 +51,10 @@ #define ALADINA2 0x28 #define G2TEK 0x31 #define G2 0x32 +#define G3 0x34 #define G2HUD 0x42 +#define LUNA2AI 0x50 +#define LUNA2 0x51 #define UNSUPPORTED 0xFFFFFFFF @@ -157,7 +160,6 @@ struct uwatec_smart_parser_t { dc_divemode_t divemode; }; -static dc_status_t uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t uwatec_smart_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime); static dc_status_t uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value); static dc_status_t uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata); @@ -167,7 +169,6 @@ static dc_status_t uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_ static const dc_parser_vtable_t uwatec_smart_parser_vtable = { sizeof(uwatec_smart_parser_t), DC_FAMILY_UWATEC_SMART, - uwatec_smart_parser_set_data, /* set_data */ NULL, /* set_clock */ NULL, /* set_atmospheric */ NULL, /* set_density */ @@ -534,7 +535,8 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser) parser->model == G2 || parser->model == ALADINSPORTMATRIX || parser->model == ALADINSQUARE || parser->model == G2HUD || parser->model == ALADINA1 || parser->model == ALADINA2 || - parser->model == G2TEK) { + parser->model == G2TEK || parser->model == G3 || + parser->model == LUNA2AI || parser->model == LUNA2) { unsigned int offset = header->tankpressure + 2 * i; endpressure = array_uint16_le(data + offset); beginpressure = array_uint16_le(data + offset + 2 * header->ngases); @@ -573,7 +575,7 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser) dc_status_t -uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model) +uwatec_smart_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; uwatec_smart_parser_t *parser = NULL; @@ -582,7 +584,7 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i return DC_STATUS_INVALIDARGS; // Allocate memory. - parser = (uwatec_smart_parser_t *) dc_parser_allocate (context, &uwatec_smart_parser_vtable); + parser = (uwatec_smart_parser_t *) dc_parser_allocate (context, &uwatec_smart_parser_vtable, data, size); if (parser == NULL) { ERROR (context, "Failed to allocate memory."); return DC_STATUS_NOMEMORY; @@ -625,9 +627,12 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i case G2: case G2HUD: case G2TEK: + case G3: case ALADINSPORTMATRIX: case ALADINA1: case ALADINA2: + case LUNA2AI: + case LUNA2: parser->headersize = 84; parser->header = &uwatec_smart_trimix_header; parser->samples = uwatec_smart_galileo_samples; @@ -707,31 +712,6 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i } -static dc_status_t -uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) -{ - uwatec_smart_parser_t *parser = (uwatec_smart_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].id = 0; - parser->gasmix[i].oxygen = 0; - parser->gasmix[i].helium = 0; - parser->tank[i].id = 0; - parser->tank[i].beginpressure = 0; - parser->tank[i].endpressure = 0; - parser->tank[i].gasmix = 0; - } - parser->watertype = DC_WATER_FRESH; - parser->divemode = DC_DIVEMODE_OC; - - return DC_STATUS_SUCCESS; -} - - static dc_status_t uwatec_smart_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) { @@ -807,6 +787,7 @@ uwatec_smart_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->helium = parser->gasmix[flags].helium / 100.0; gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; @@ -821,6 +802,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi tank->beginpressure = parser->tank[flags].beginpressure / 128.0; tank->endpressure = parser->tank[flags].endpressure / 128.0; tank->gasmix = parser->tank[flags].gasmix; + tank->usage = DC_USAGE_NONE; break; case DC_FIELD_TEMPERATURE_MINIMUM: *((double *) value) = (signed short) array_uint16_le (data + table->temp_minimum) / 10.0; @@ -953,7 +935,8 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback parser->model == G2 || parser->model == ALADINSPORTMATRIX || parser->model == ALADINSQUARE || parser->model == G2HUD || parser->model == ALADINA1 || parser->model == ALADINA2 || - parser->model == G2TEK) { + parser->model == G2TEK || parser->model == G3 || + parser->model == LUNA2AI || parser->model == LUNA2) { // Uwatec Galileo id = uwatec_galileo_identify (data[offset]); } else { @@ -1162,8 +1145,8 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback } while (complete) { - sample.time = time; - if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + sample.time = time * 1000; + if (callback) callback (DC_SAMPLE_TIME, &sample, userdata); if (parser->ngasmixes && gasmix != gasmix_previous) { idx = uwatec_smart_find_gasmix (parser, gasmix); @@ -1172,13 +1155,13 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t 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; } if (have_temperature) { sample.temperature = temperature / 2.5; - if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); + if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata); } if (bookmark) { @@ -1186,12 +1169,12 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t 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); } if (have_rbt || have_pressure) { sample.rbt = rbt; - if (callback) callback (DC_SAMPLE_RBT, sample, userdata); + if (callback) callback (DC_SAMPLE_RBT, &sample, userdata); } if (have_pressure) { @@ -1199,24 +1182,24 @@ uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback if (idx < parser->ntanks) { sample.pressure.tank = idx; sample.pressure.value = pressure / 4.0; - if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata); + if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata); } } if (have_heartrate) { sample.heartbeat = heartrate; - if (callback) callback (DC_SAMPLE_HEARTBEAT, sample, userdata); + if (callback) callback (DC_SAMPLE_HEARTBEAT, &sample, userdata); } if (have_bearing) { sample.bearing = bearing; - if (callback) callback (DC_SAMPLE_BEARING, sample, userdata); + if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata); have_bearing = 0; } if (have_depth) { sample.depth = (signed int)(depth - depth_calibration) * (2.0 * BAR / 1000.0) / (density * 10.0); - if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); + if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata); } time += interval;