From c5249861758305cff525a02e0a243f65b0750862 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 4 Oct 2013 16:37:24 +0200 Subject: [PATCH] Add support for the Scubapro/Uwatec Meridian. The Uwatec Meridian protocol is identical to the Uwatec Smart/Galileo protocol, except for some additional framing around each data packet, and the switch from IrDA to usb-serial communication. For parsing, the data format appears to be identical to the Galileo data format. --- examples/universal.c | 1 + include/libdivecomputer/Makefile.am | 1 + include/libdivecomputer/common.h | 1 + include/libdivecomputer/uwatec.h | 1 + include/libdivecomputer/uwatec_meridian.h | 42 ++ src/Makefile.am | 1 + src/descriptor.c | 2 + src/device.c | 3 + src/libdivecomputer.symbols | 2 + src/parser.c | 1 + src/uwatec_meridian.c | 498 ++++++++++++++++++++++ src/uwatec_smart_parser.c | 5 +- 12 files changed, 557 insertions(+), 1 deletion(-) create mode 100644 include/libdivecomputer/uwatec_meridian.h create mode 100644 src/uwatec_meridian.c diff --git a/examples/universal.c b/examples/universal.c index 4eef0c5..f7af41b 100644 --- a/examples/universal.c +++ b/examples/universal.c @@ -81,6 +81,7 @@ static const backend_table_t g_backends[] = { {"aladin", DC_FAMILY_UWATEC_ALADIN}, {"memomouse", DC_FAMILY_UWATEC_MEMOMOUSE}, {"smart", DC_FAMILY_UWATEC_SMART}, + {"meridian", DC_FAMILY_UWATEC_MERIDIAN}, {"sensus", DC_FAMILY_REEFNET_SENSUS}, {"sensuspro", DC_FAMILY_REEFNET_SENSUSPRO}, {"sensusultra", DC_FAMILY_REEFNET_SENSUSULTRA}, diff --git a/include/libdivecomputer/Makefile.am b/include/libdivecomputer/Makefile.am index 9a68ffe..576c2fd 100644 --- a/include/libdivecomputer/Makefile.am +++ b/include/libdivecomputer/Makefile.am @@ -24,6 +24,7 @@ libdivecomputer_HEADERS = \ uwatec_aladin.h \ uwatec_memomouse.h \ uwatec_smart.h \ + uwatec_meridian.h \ oceanic.h \ oceanic_atom2.h \ oceanic_veo250.h \ diff --git a/include/libdivecomputer/common.h b/include/libdivecomputer/common.h index e8a58e3..2c27744 100644 --- a/include/libdivecomputer/common.h +++ b/include/libdivecomputer/common.h @@ -57,6 +57,7 @@ typedef enum dc_family_t { DC_FAMILY_UWATEC_ALADIN = (3 << 16), DC_FAMILY_UWATEC_MEMOMOUSE, DC_FAMILY_UWATEC_SMART, + DC_FAMILY_UWATEC_MERIDIAN, /* Oceanic */ DC_FAMILY_OCEANIC_VTPRO = (4 << 16), DC_FAMILY_OCEANIC_VEO250, diff --git a/include/libdivecomputer/uwatec.h b/include/libdivecomputer/uwatec.h index 32afd80..572d1dd 100644 --- a/include/libdivecomputer/uwatec.h +++ b/include/libdivecomputer/uwatec.h @@ -25,5 +25,6 @@ #include "uwatec_aladin.h" #include "uwatec_memomouse.h" #include "uwatec_smart.h" +#include "uwatec_meridian.h" #endif /* UWATEC_H */ diff --git a/include/libdivecomputer/uwatec_meridian.h b/include/libdivecomputer/uwatec_meridian.h new file mode 100644 index 0000000..723a9de --- /dev/null +++ b/include/libdivecomputer/uwatec_meridian.h @@ -0,0 +1,42 @@ +/* + * libdivecomputer + * + * Copyright (C) 2013 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 UWATEC_MERIDIAN_H +#define UWATEC_MERIDIAN_H + +#include "context.h" +#include "device.h" +#include "parser.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +dc_status_t +uwatec_meridian_device_open (dc_device_t **device, dc_context_t *context, const char *name); + +dc_status_t +uwatec_meridian_extract_dives (dc_device_t *device, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* UWATEC_MERIDIAN_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 2cce288..fcab17f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,7 @@ libdivecomputer_la_SOURCES = \ uwatec_aladin.c \ uwatec_memomouse.c uwatec_memomouse_parser.c \ uwatec_smart.c uwatec_smart_parser.c \ + uwatec_meridian.c \ oceanic_common.h oceanic_common.c \ oceanic_atom2.c oceanic_atom2_parser.c \ oceanic_veo250.c oceanic_veo250_parser.c \ diff --git a/src/descriptor.c b/src/descriptor.c index f7df199..08de001 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -104,6 +104,8 @@ static const dc_descriptor_t g_descriptors[] = { {"Uwatec", "Smart Z", DC_FAMILY_UWATEC_SMART, 0x1C}, {"Subgear","XP Air", DC_FAMILY_UWATEC_SMART, 0x1C}, #endif + /* Scubapro/Uwatec Meridian */ + {"Scubapro", "Meridian", DC_FAMILY_UWATEC_MERIDIAN, 0x20}, /* Reefnet */ {"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1}, {"Reefnet", "Sensus Pro", DC_FAMILY_REEFNET_SENSUSPRO, 2}, diff --git a/src/device.c b/src/device.c index 0fa4e7e..eb206c1 100644 --- a/src/device.c +++ b/src/device.c @@ -90,6 +90,9 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr case DC_FAMILY_UWATEC_SMART: rc = uwatec_smart_device_open (&device, context); break; + case DC_FAMILY_UWATEC_MERIDIAN: + rc = uwatec_meridian_device_open (&device, context, name); + break; case DC_FAMILY_REEFNET_SENSUS: rc = reefnet_sensus_device_open (&device, context, name); break; diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 525f193..a73440f 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -132,6 +132,8 @@ uwatec_memomouse_device_open uwatec_memomouse_extract_dives uwatec_smart_device_open uwatec_smart_extract_dives +uwatec_meridian_device_open +uwatec_meridian_extract_dives hw_ostc_device_open hw_ostc_device_md2hash hw_ostc_device_clock diff --git a/src/parser.c b/src/parser.c index 73ab0e7..2789a4e 100644 --- a/src/parser.c +++ b/src/parser.c @@ -70,6 +70,7 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device) rc = uwatec_memomouse_parser_create (&parser, context, device->clock.devtime, device->clock.systime); break; case DC_FAMILY_UWATEC_SMART: + case DC_FAMILY_UWATEC_MERIDIAN: rc = uwatec_smart_parser_create (&parser, context, device->devinfo.model, device->clock.devtime, device->clock.systime); break; case DC_FAMILY_REEFNET_SENSUS: diff --git a/src/uwatec_meridian.c b/src/uwatec_meridian.c new file mode 100644 index 0000000..fbf26c7 --- /dev/null +++ b/src/uwatec_meridian.c @@ -0,0 +1,498 @@ +/* + * libdivecomputer + * + * Copyright (C) 2013 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 + */ + +#include +#include +#include + +#include + +#include "context-private.h" +#include "device-private.h" +#include "checksum.h" +#include "serial.h" +#include "array.h" + +#define ISINSTANCE(device) dc_device_isinstance((device), &uwatec_meridian_device_vtable) + +#define EXITCODE(rc) \ +( \ + rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \ +) + +#define ACK 0x11 +#define NAK 0x66 + +typedef struct uwatec_meridian_device_t { + dc_device_t base; + serial_t *port; + unsigned int timestamp; + unsigned int devtime; + dc_ticks_t systime; +} uwatec_meridian_device_t; + +static dc_status_t uwatec_meridian_device_set_fingerprint (dc_device_t *device, const unsigned char data[], unsigned int size); +static dc_status_t uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer); +static dc_status_t uwatec_meridian_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata); +static dc_status_t uwatec_meridian_device_close (dc_device_t *abstract); + +static const dc_device_vtable_t uwatec_meridian_device_vtable = { + DC_FAMILY_UWATEC_MERIDIAN, + uwatec_meridian_device_set_fingerprint, /* set_fingerprint */ + NULL, /* read */ + NULL, /* write */ + uwatec_meridian_device_dump, /* dump */ + uwatec_meridian_device_foreach, /* foreach */ + uwatec_meridian_device_close /* close */ +}; + + +static dc_status_t +uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize) +{ + dc_device_t *abstract = (dc_device_t *) device; + + assert (csize > 0 && csize <= 255); + + // Build the packet. + unsigned char packet[255 + 12] = { + 0xFF, 0xFF, 0xFF, + 0xA6, 0x59, 0xBD, 0xC2, + 0x00, /* length */ + 0x00, 0x00, 0x00, + 0x00}; /* data and checksum */ + memcpy (packet + 11, command, csize); + packet[7] = csize; + packet[11 + csize] = checksum_xor_uint8 (packet + 7, csize + 4, 0x00); + + // Send the packet. + int n = serial_write (device->port, packet, csize + 12); + if (n != csize + 12) { + ERROR (abstract->context, "Failed to send the command."); + return EXITCODE (n); + } + + // Read the echo. + unsigned char echo[sizeof(packet)]; + n = serial_read (device->port, echo, csize + 12); + if (n != csize + 12) { + ERROR (abstract->context, "Failed to receive the echo."); + return EXITCODE (n); + } + + // Verify the echo. + if (memcmp (echo, packet, csize + 12) != 0) { + WARNING (abstract->context, "Unexpected echo."); + return DC_STATUS_PROTOCOL; + } + + // Read the header. + unsigned char header[6]; + n = serial_read (device->port, header, sizeof (header)); + if (n != sizeof (header)) { + ERROR (abstract->context, "Failed to receive the header."); + return EXITCODE (n); + } + + // Verify the header. + if (header[0] != ACK || array_uint32_le (header + 1) != asize + 1 || header[5] != packet[11]) { + WARNING (abstract->context, "Unexpected header."); + return DC_STATUS_PROTOCOL; + } + + // Read the packet. + n = serial_read (device->port, answer, asize); + if (n != asize) { + ERROR (abstract->context, "Failed to receive the packet."); + return EXITCODE (n); + } + + // Read the checksum. + unsigned char csum = 0x00; + n = serial_read (device->port, &csum, sizeof (csum)); + if (n != sizeof (csum)) { + ERROR (abstract->context, "Failed to receive the checksum."); + return EXITCODE (n); + } + + // Verify the checksum. + unsigned char ccsum = 0x00; + ccsum = checksum_xor_uint8 (header + 1, sizeof (header) - 1, ccsum); + ccsum = checksum_xor_uint8 (answer, asize, ccsum); + if (csum != ccsum) { + ERROR (abstract->context, "Unexpected answer checksum."); + return DC_STATUS_PROTOCOL; + } + + return DC_STATUS_SUCCESS; +} + + +static dc_status_t +uwatec_meridian_handshake (uwatec_meridian_device_t *device) +{ + dc_device_t *abstract = (dc_device_t *) device; + + // Command template. + unsigned char answer[1] = {0}; + unsigned char command[5] = {0x00, 0x10, 0x27, 0, 0}; + + // Handshake (stage 1). + command[0] = 0x1B; + dc_status_t rc = uwatec_meridian_transfer (device, command, 1, answer, 1); + if (rc != DC_STATUS_SUCCESS) + return rc; + + // Verify the answer. + if (answer[0] != 0x01) { + ERROR (abstract->context, "Unexpected answer byte(s)."); + return DC_STATUS_PROTOCOL; + } + + // Handshake (stage 2). + command[0] = 0x1C; + rc = uwatec_meridian_transfer (device, command, 5, answer, 1); + if (rc != DC_STATUS_SUCCESS) + return rc; + + // Verify the answer. + if (answer[0] != 0x01) { + ERROR (abstract->context, "Unexpected answer byte(s)."); + return DC_STATUS_PROTOCOL; + } + + return DC_STATUS_SUCCESS; +} + + +dc_status_t +uwatec_meridian_device_open (dc_device_t **out, dc_context_t *context, const char *name) +{ + if (out == NULL) + return DC_STATUS_INVALIDARGS; + + // Allocate memory. + uwatec_meridian_device_t *device = (uwatec_meridian_device_t *) malloc (sizeof (uwatec_meridian_device_t)); + if (device == NULL) { + ERROR (context, "Failed to allocate memory."); + return DC_STATUS_NOMEMORY; + } + + // Initialize the base class. + device_init (&device->base, context, &uwatec_meridian_device_vtable); + + // Set the default values. + device->port = NULL; + device->timestamp = 0; + device->systime = (dc_ticks_t) -1; + device->devtime = 0; + + // Open the device. + int rc = serial_open (&device->port, context, name); + if (rc == -1) { + ERROR (context, "Failed to open the serial port."); + free (device); + return DC_STATUS_IO; + } + + // Set the serial communication protocol (57600 8N1). + rc = serial_configure (device->port, 57600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE); + if (rc == -1) { + ERROR (context, "Failed to set the terminal attributes."); + serial_close (device->port); + free (device); + return DC_STATUS_IO; + } + + // Set the timeout for receiving data (3000ms). + if (serial_set_timeout (device->port, 3000) == -1) { + ERROR (context, "Failed to set the timeout."); + serial_close (device->port); + free (device); + return DC_STATUS_IO; + } + + // Make sure everything is in a sane state. + serial_flush (device->port, SERIAL_QUEUE_BOTH); + + // Perform the handshaking. + uwatec_meridian_handshake (device); + + *out = (dc_device_t*) device; + + return DC_STATUS_SUCCESS; +} + + +static dc_status_t +uwatec_meridian_device_close (dc_device_t *abstract) +{ + uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract; + + // Close the device. + if (serial_close (device->port) == -1) { + free (device); + return DC_STATUS_IO; + } + + // Free memory. + free (device); + + return DC_STATUS_SUCCESS; +} + + +static dc_status_t +uwatec_meridian_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size) +{ + uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract; + + if (size && size != 4) + return DC_STATUS_INVALIDARGS; + + if (size) + device->timestamp = array_uint32_le (data); + else + device->timestamp = 0; + + return DC_STATUS_SUCCESS; +} + + +static dc_status_t +uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer) +{ + uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract; + dc_status_t rc = DC_STATUS_SUCCESS; + + // Erase the current contents of the buffer. + if (!dc_buffer_clear (buffer)) { + ERROR (abstract->context, "Insufficient buffer space available."); + return DC_STATUS_NOMEMORY; + } + + // Enable progress notifications. + dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER; + device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress); + + // Command template. + unsigned char command[9] = {0x00, + (device->timestamp ) & 0xFF, + (device->timestamp >> 8 ) & 0xFF, + (device->timestamp >> 16) & 0xFF, + (device->timestamp >> 24) & 0xFF, + 0x10, + 0x27, + 0, + 0}; + + // Read the model number. + command[0] = 0x10; + unsigned char model[1] = {0}; + rc = uwatec_meridian_transfer (device, command, 1, model, sizeof (model)); + if (rc != DC_STATUS_SUCCESS) + return rc; + + // Read the serial number. + command[0] = 0x14; + unsigned char serial[4] = {0}; + rc = uwatec_meridian_transfer (device, command, 1, serial, sizeof (serial)); + if (rc != DC_STATUS_SUCCESS) + return rc; + + // Read the device clock. + command[0] = 0x1A; + unsigned char devtime[4] = {0}; + rc = uwatec_meridian_transfer (device, command, 1, devtime, sizeof (devtime)); + if (rc != DC_STATUS_SUCCESS) + return rc; + + // Store the clock calibration values. + device->systime = dc_datetime_now (); + device->devtime = array_uint32_le (devtime); + + // Update and emit a progress event. + progress.current += 9; + device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress); + + // Emit a clock event. + dc_event_clock_t clock; + clock.systime = device->systime; + clock.devtime = device->devtime; + device_event_emit (&device->base, DC_EVENT_CLOCK, &clock); + + // Emit a device info event. + dc_event_devinfo_t devinfo; + devinfo.model = model[0]; + devinfo.firmware = 0; + devinfo.serial = array_uint32_le (serial); + device_event_emit (&device->base, DC_EVENT_DEVINFO, &devinfo); + + // Data Length. + command[0] = 0xC6; + unsigned char answer[4] = {0}; + rc = uwatec_meridian_transfer (device, command, sizeof (command), answer, sizeof (answer)); + if (rc != DC_STATUS_SUCCESS) + return rc; + + unsigned int length = array_uint32_le (answer); + + // Update and emit a progress event. + progress.maximum = 4 + 9 + (length ? length + 4 : 0); + progress.current += 4; + device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress); + + if (length == 0) + return DC_STATUS_SUCCESS; + + // Allocate the required amount of memory. + if (!dc_buffer_resize (buffer, length)) { + ERROR (abstract->context, "Insufficient buffer space available."); + return DC_STATUS_NOMEMORY; + } + + unsigned char *data = dc_buffer_get_data (buffer); + + // Data. + command[0] = 0xC4; + rc = uwatec_meridian_transfer (device, command, sizeof (command), answer, sizeof (answer)); + if (rc != DC_STATUS_SUCCESS) + return rc; + + unsigned int total = array_uint32_le (answer); + + // Update and emit a progress event. + progress.current += 4; + device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress); + + if (total != length + 4) { + ERROR (abstract->context, "Received an unexpected size."); + return DC_STATUS_PROTOCOL; + } + + unsigned int nbytes = 0; + while (nbytes < length) { + + // Read the header. + unsigned char header[5]; + int n = serial_read (device->port, header, sizeof (header)); + if (n != sizeof (header)) { + ERROR (abstract->context, "Failed to receive the header."); + return EXITCODE (n); + } + + // Get the packet size. + unsigned int packetsize = array_uint32_le (header); + if (packetsize < 1 || nbytes + packetsize - 1 > length) { + WARNING (abstract->context, "Unexpected header."); + return DC_STATUS_PROTOCOL; + } + + // Read the packet data. + n = serial_read (device->port, data + nbytes, packetsize - 1); + if (n != packetsize - 1) { + ERROR (abstract->context, "Failed to receive the packet."); + return EXITCODE (n); + } + + // Read the checksum. + unsigned char csum = 0x00; + n = serial_read (device->port, &csum, sizeof (csum)); + if (n != sizeof (csum)) { + ERROR (abstract->context, "Failed to receive the checksum."); + return EXITCODE (n); + } + + // Verify the checksum. + unsigned char ccsum = 0x00; + ccsum = checksum_xor_uint8 (header, sizeof (header), ccsum); + ccsum = checksum_xor_uint8 (data + nbytes, packetsize - 1, ccsum); + if (csum != ccsum) { + ERROR (abstract->context, "Unexpected answer checksum."); + return DC_STATUS_PROTOCOL; + } + + + // Update and emit a progress event. + progress.current += packetsize - 1; + device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress); + + nbytes += packetsize - 1; + } + + return DC_STATUS_SUCCESS; +} + + +static dc_status_t +uwatec_meridian_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata) +{ + dc_buffer_t *buffer = dc_buffer_new (0); + if (buffer == NULL) + return DC_STATUS_NOMEMORY; + + dc_status_t rc = uwatec_meridian_device_dump (abstract, buffer); + if (rc != DC_STATUS_SUCCESS) { + dc_buffer_free (buffer); + return rc; + } + + rc = uwatec_meridian_extract_dives (abstract, + dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), callback, userdata); + + dc_buffer_free (buffer); + + return rc; +} + + +dc_status_t +uwatec_meridian_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata) +{ + if (abstract && !ISINSTANCE (abstract)) + return DC_STATUS_INVALIDARGS; + + const unsigned char header[4] = {0xa5, 0xa5, 0x5a, 0x5a}; + + // Search the data stream for start markers. + unsigned int previous = size; + unsigned int current = (size >= 4 ? size - 4 : 0); + while (current > 0) { + current--; + if (memcmp (data + current, header, sizeof (header)) == 0) { + // Get the length of the profile data. + unsigned int len = array_uint32_le (data + current + 4); + + // Check for a buffer overflow. + if (current + len > previous) + return DC_STATUS_DATAFORMAT; + + if (callback && !callback (data + current, len, data + current + 8, 4, userdata)) + return DC_STATUS_SUCCESS; + + // Prepare for the next dive. + previous = current; + current = (current >= 4 ? current - 4 : 0); + } + } + + return DC_STATUS_SUCCESS; +} diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 60cbfa4..97f6ae1 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -42,6 +42,7 @@ #define SMARTTEC 0x18 #define GALILEOTRIMIX 0x19 #define SMARTZ 0x1C +#define MERIDIAN 0x20 typedef struct uwatec_smart_parser_t uwatec_smart_parser_t; @@ -206,6 +207,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi break; case GALILEO: case GALILEOTRIMIX: + case MERIDIAN: header = 152; if (data[43] & 0x80) { header = 0xB1; @@ -454,6 +456,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t break; case GALILEO: case GALILEOTRIMIX: + case MERIDIAN: header = 152; if (data[43] & 0x80) { header = 0xB1; @@ -519,7 +522,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t // Process the type bits in the bitstream. unsigned int id = 0; - if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) { + if (parser->model == GALILEO || parser->model == GALILEOTRIMIX || parser->model == MERIDIAN) { // Uwatec Galileo id = uwatec_galileo_identify (data[offset]); } else {