Compare commits

...

34 Commits

Author SHA1 Message Date
Dirk Hohndel
b85153605f Merge branch 'Subsurface-testing' into Subsurface-branch
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-08-18 09:57:23 -07:00
Claudiu Olteanu
9b3d34dbf9 Use custom set_timeout callback for Shearwater family
Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-08-15 05:08:54 -07:00
Claudiu Olteanu
41ba0daec5 Use the custom set_timeout callback for HW_OSTC 3 family
Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-08-15 05:08:49 -07:00
Claudiu Olteanu
0541770a8c Add set_timeout callback for serial custom implementation
The new callback will be usefull when we will implement the support
for Windows. The implementation of native serial set_timeout method
uses a HANDLER on Windows and we will use the WinSock2 API which has
a socket descriptor.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-08-15 05:08:08 -07:00
Gaetan Bisson
dfe59b0188 Add new functions to list of exported symbols
This is required in order to build those new public functions into the
shared library.

Signed-off-by: Gaetan Bisson <bisson@archlinux.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-10 21:54:04 -07:00
Dirk Hohndel
328a599337 Revert "Avoid a run-time dependency on the libgcc dlls."
This breaks builds with clang

This reverts commit bd2b132d7f3c92aa434c4d799e8cc5358bc1baef.
2015-07-09 11:06:08 -07:00
Linus Torvalds
0cd8e0d695 EON Steel: expose the gas switch cylinder in the "flags" field
This seems to be the simplest extension to the SAMPLE_EVENT_GASCHANGE2
format: the "value" remains the oddly encoded gas mix, but the "flags"
value (if non-zero) now contains the actual cylinder number we switch
to.

This will need a trivial patch to subsurface to take advantage of the
new data too.  But then we can actually distinguish between cylinders
that have the same gas mix.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 13:06:59 -07:00
Linus Torvalds
f54ea6f4f5 Add EON Steel personal adjustment parsing
Suunto calls it "Conservatism" in the dump, but "Personal adjustment" in
at least some of the documentation. That's what we expose it as.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 13:06:55 -07:00
Linus Torvalds
bc983be484 Add EON Steel dive mode and transmitter ID information
This adds the divemode name (Nitrox, Trimix, Gauge, or whatever custon
name) and the transmitter ID as extra string information when
downloading from the EON Steel.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 13:06:52 -07:00
Linus Torvalds
68851cea17 Suunto EON Steel: populate various string data
The EON Steel saves the dive computer firmware versions etc per dive,
which is really nice for upgrades: old dives done with older firmware
still show the firmware at the time of the dive.  That, in turn, is nice
because we can use it for a reliable dive ID - dive time with serial
number etc.

This uses the new DC_FIELD_STRING model to feed the hw/sw information to
the application, since we need the parser to access it.  It also returns
battery state and deco model information.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 13:06:46 -07:00
Dirk Hohndel
d6335c4cf1 Make it easier to detect our branch of libdivecomputer
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:37 -07:00
Claudiu Olteanu
2f9227a3e2 Implement custom open device method for SHEARWATER family
Create a custom open method for SHEARWATER family.
This method can be used to pass a reference to a dc_serial_t
structure. In this way the applications can implement their
own implementation for a serial communication and set their
callbacks for the basic serial functions.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:37 -07:00
Claudiu Olteanu
0f6d480a1d Use the dc_serial_t structure in SHEARWATER family
Use the new structure in the SHEARWATER family implementation.
This patch opens a native serial device and use it
for the serial communication.

Also the patch uses the set of callback functions saved in the
dc_serial_t structure.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Claudiu Olteanu
d38ea815cf Implement custom device open method
This method can be used by external applications to open a
device and to pass their custom implementation for the
serial communication.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Claudiu Olteanu
70d4fcb46d Implement custom open method for HW OSTC 3 family
Create a custom open method for HW OSTC3 family.
This method can be used to pass a reference to a dc_serial_t
structure. In this way the applications can implement their
own implementation for a serial communication and set their
callbacks for the basic serial functions.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Claudiu Olteanu
42bc3f1303 Use the dc_serial_t structure in HW OSTC family 3
Open a native serial device and use it in the HW OSTC3
implementation.

This patch replaces the old serial structure with the
new one, which can be used for custom serial implementations.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Claudiu Olteanu
619b9de06e Create a generic way to represent any type of serial communication
Add a structure which holds references to basic operations
on a serial communication. This can be used to pass a set
of function pointer callbacks in order to create a custom
implementation for serial communication.

Add a generic structure to represent the needed information
for a serial communication.

Implement the initialization method where the user can
pass a set of function pointer callbacks and set some
custom data for the serial device.

Create open method for the native serial implementation.

Signed-off-by: Claudiu Olteanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Claudiu Olteanu
b9e731e641 Extend the transport enum descriptor for serial communication
Add a new transport type which can be used to identify
Bluetooth serial communication.

Signed-off-by Claudiu Oleanu <olteanu.claudiu@ymail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Anton Lundin
ac56b20192 Correct firmware version string from OSTC's
The format string was incorrect, producing firmware numbers as 3.2
instead of 3.02 as is the current OSTC firmware version.

This was reported via hw's forum:
http://forum.heinrichsweikamp.com/read.php?2,14550,14552

Signed-off-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
427466c349 Predator: don't report PPO2 unless in CC mode
Sending this in OC mode is redundant and might confuse applications that
assume they only get PPO2 data in CC mode.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
f1f2fa2c12 Don't report errors if we can't set serial mode
That's just silly and breaks using the simulator.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Anton Lundin
8d6417f16a Add deco model info strings to hw parser
Signed-off-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
c13f4da702 Mark a library built from our branch as such
This way it will be obvious when people report their libdivecomputer
version that they are not using upstream master.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Linus Torvalds
c0b79f46bf Fix suunto serial numbers
libdivecomputer has already done the "byte to decimal" conversion.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
c28aa775e6 Support serial number for Suuntu Vyper2 family of devices
We have the correct firmware in the devinfo, but that's the firmware the
dive computer is on NOW, not necessarily the firmware it was using when
recording the dive.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
fbe702ea7b Support firmware and serial number for Shearwater Petrel
This should work with the Predator as well.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
bb283bc5e1 Support serial number as DC_FIELD_STRING on atom2 backend
This has been verified with a few of the models, it needs much more
testing to make sure this is generally correct.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
d9b40eaa52 Add support to return serial number to OSTC devices
This data isn't per dive, but it makes sense to return it here as a
string (we already return it as unsigned int in the devinfo event after
opening the device).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
3ae06d85e9 Pass the serial number from the devinfo to the OSTC parsers
This way we can analyze the data in the parser and return it to the
application.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
5f4d8e09b4 Support FW Version on OSTC devices
And add battery voltage and desat for the Frog.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
54957047a1 Add DC_FIELD_STRING support to OSTC parser
Just support a few of the most useful values. There are several more we
could and should add.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
feb1d9d391 Add DC_FIELD_STRING support to Shearwater Petrel parser
Just support a few of the most useful values. There are several more we
could and should add.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Dirk Hohndel
4377bf7f2d Add DC_FIELD_STRING support to Atomics Aquatics Cobalt parser
Just support a few of the most useful values. There are several more we
could and should add.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:36 -07:00
Linus Torvalds
bdf8b4b3bd parser: add DC_FIELD_STRING field type for parse-time information
This can be used to return almost arbitrary information to the dive log
application at dive parse time, by returning a number of strings (with a
descriptor) for dive state.

NOTE! The strings are supposed to be human-readable, so that the dive
log application can just show them unedited - and without understanding
them - to the user, together with the description.  So if your dive
computer supports returning a battery voltage, for example, you can
return it as a

  { "Voltage", "4.449V" }

descriptor/value string pair, and the application could then put these
string pairs together and show (somewhere) an informational line like
"Voltage: 4.449V" along with the other information you return.

Some dive log applications migth recognize particular descriptor strings
and use them specially to fill in other information (ie serial numbers,
weight and suit information etc), but in general the interface is very
much meant to be informational free-form for a human user.

So do *not* use this interface to encode things that are not human-
readable.  Serial numbers or version information that is meaningful to
humans are fine. But random encoded data structures are not.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-07-07 11:25:35 -07:00
30 changed files with 703 additions and 65 deletions

View File

@ -2,7 +2,7 @@
m4_define([dc_version_major],[0])
m4_define([dc_version_minor],[5])
m4_define([dc_version_micro],[0])
m4_define([dc_version_suffix],[devel])
m4_define([dc_version_suffix],[devel-Subsurface-testing])
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
# Libtool versioning.

View File

@ -53,4 +53,5 @@ libdivecomputer_HEADERS = \
citizen.h \
citizen_aqualand.h \
divesystem.h \
divesystem_idive.h
divesystem_idive.h \
custom_serial.h

View File

@ -0,0 +1,64 @@
/*
* libdivecomputer
*
* Copyright (C) 2015 Claudiu Olteanu
* base on code that is Copyright (C) 2008 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 CUSTOM_SERIAL_H
#define CUSTOM_SERIAL_H
#include <string.h>
#include <stdlib.h>
#include "context.h"
#include "descriptor.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct serial_t serial_t;
typedef struct dc_serial_operations_t
{
int (*open) (serial_t **device, dc_context_t *context, const char *name);
int (*close) (serial_t *device);
int (*read) (serial_t *device, void* data, unsigned int size);
int (*write) (serial_t *device, const void* data, unsigned int size);
int (*flush) (serial_t *device, int queue);
int (*get_received) (serial_t *device);
int (*get_transmitted) (serial_t *device);
int (*set_timeout) (serial_t *device, long timeout);
} dc_serial_operations_t;
typedef struct dc_serial_t {
serial_t *port; //serial device port
dc_transport_t type; //the type of the transport (USB, SERIAL, IRDA, BLUETOOTH)
void *data; //specific data for serial device
const dc_serial_operations_t *ops; //reference to a custom set of operations
} dc_serial_t;
void dc_serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops);
dc_status_t dc_serial_native_open(dc_serial_t **serial, dc_context_t *context, const char *devname);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CUSTOM_SERIAL_H */

View File

@ -33,7 +33,8 @@ typedef enum dc_transport_t {
DC_TRANSPORT_NONE,
DC_TRANSPORT_SERIAL,
DC_TRANSPORT_USB,
DC_TRANSPORT_IRDA
DC_TRANSPORT_IRDA,
DC_TRANSPORT_BLUETOOTH
} dc_transport_t;
typedef struct dc_descriptor_t dc_descriptor_t;

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2008 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -27,6 +28,7 @@
#include "descriptor.h"
#include "buffer.h"
#include "datetime.h"
#include "custom_serial.h"
#ifdef __cplusplus
extern "C" {
@ -72,6 +74,9 @@ typedef int (*dc_dive_callback_t) (const unsigned char *data, unsigned int size,
dc_status_t
dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descriptor, const char *name);
dc_status_t
dc_device_custom_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descriptor, dc_serial_t *serial);
dc_family_t
dc_device_get_type (dc_device_t *device);

View File

@ -65,7 +65,7 @@ dc_status_t
hw_ostc_extract_dives (dc_device_t *device, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata);
dc_status_t
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int frog);
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial, unsigned int frog);
dc_status_t
hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename);

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2013 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -26,6 +27,7 @@
#include "device.h"
#include "parser.h"
#include "buffer.h"
#include "custom_serial.h"
#ifdef __cplusplus
extern "C" {
@ -37,6 +39,9 @@ extern "C" {
dc_status_t
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, const char *name);
dc_status_t
hw_ostc3_device_custom_open (dc_device_t **device, dc_context_t *context, dc_serial_t *serial);
dc_status_t
hw_ostc3_device_version (dc_device_t *device, unsigned char data[], unsigned int size);

View File

@ -43,7 +43,7 @@ dc_status_t
oceanic_atom2_device_keepalive (dc_device_t *device);
dc_status_t
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -59,9 +59,13 @@ typedef enum dc_field_type_t {
DC_FIELD_TEMPERATURE_MAXIMUM,
DC_FIELD_TANK_COUNT,
DC_FIELD_TANK,
DC_FIELD_DIVEMODE
DC_FIELD_DIVEMODE,
DC_FIELD_STRING,
} dc_field_type_t;
// Make it easy to test support compile-time with "#ifdef DC_FIELD_STRING"
#define DC_FIELD_STRING DC_FIELD_STRING
typedef enum parser_sample_event_t {
SAMPLE_EVENT_NONE,
SAMPLE_EVENT_DECOSTOP,
@ -181,6 +185,11 @@ typedef struct dc_tank_t {
double endpressure; /* End pressure (bar) */
} dc_tank_t;
typedef struct dc_field_string_t {
const char *desc;
const char *value;
} dc_field_string_t;
typedef union dc_sample_value_t {
unsigned int time;
double depth;

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2013 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -34,7 +35,10 @@ dc_status_t
shearwater_petrel_device_open (dc_device_t **device, dc_context_t *context, const char *name);
dc_status_t
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context);
shearwater_petrel_device_custom_open (dc_device_t **out, dc_context_t *context, dc_serial_t *serial);
dc_status_t
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2012 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -33,11 +34,14 @@ extern "C" {
dc_status_t
shearwater_predator_device_open (dc_device_t **device, dc_context_t *context, const char *name);
dc_status_t
shearwater_predator_device_custom_open (dc_device_t **device, dc_context_t *context, dc_serial_t *serial);
dc_status_t
shearwater_predator_extract_dives (dc_device_t *device, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata);
dc_status_t
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context);
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -42,7 +42,7 @@ dc_status_t
suunto_d9_device_reset_maxdepth (dc_device_t *device);
dc_status_t
suunto_d9_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
suunto_d9_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
#ifdef __cplusplus
}

View File

@ -26,6 +26,10 @@
extern "C" {
#endif /* __cplusplus */
/* use these defines to detect Subsurface specific features */
#define SSRF_LIBDC_VERSION 1
#define SSRF_CUSTOM_SERIAL 1
#define DC_VERSION "@DC_VERSION@"
#define DC_VERSION_MAJOR @DC_VERSION_MAJOR@
#define DC_VERSION_MINOR @DC_VERSION_MINOR@

View File

@ -63,7 +63,8 @@ libdivecomputer_la_SOURCES = \
ringbuffer.h ringbuffer.c \
checksum.h checksum.c \
array.h array.c \
buffer.c
buffer.c \
custom_serial.c
if OS_WIN32
libdivecomputer_la_SOURCES += serial.h serial_win32.c

View File

@ -20,6 +20,12 @@
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#include <libdivecomputer/atomics_cobalt.h>
#include <libdivecomputer/units.h>
@ -139,6 +145,9 @@ atomics_cobalt_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *dateti
}
#define BUFLEN 16
static dc_status_t
atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
{
@ -153,6 +162,9 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
dc_tank_t *tank = (dc_tank_t *) value;
double atmospheric = 0.0;
char buf[BUFLEN];
dc_field_string_t *string = (dc_field_string_t *) value;
if (parser->atmospheric)
atmospheric = parser->atmospheric;
else
@ -218,6 +230,29 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
return DC_STATUS_DATAFORMAT;
}
break;
case DC_FIELD_STRING:
switch(flags) {
case 0: // Serialnr
string->desc = "Serial";
snprintf(buf, BUFLEN, "%c%c%c%c-%c%c%c%c", p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]);
break;
case 1: // Program Version
string->desc = "Program Version";
snprintf(buf, BUFLEN, "%.2f", array_uint16_le(p + 30) / 100.0);
break;
case 2: // Boot Version
string->desc = "Boot Version";
snprintf(buf, BUFLEN, "%.2f", array_uint16_le(p + 32) / 100.0);
break;
case 3: // Nofly
string->desc = "NoFly Time";
snprintf(buf, BUFLEN, "%0u:%02u", p[0x52], p[0x53]);
break;
default:
return DC_STATUS_UNSUPPORTED;
}
string->value = strdup(buf);
break;
default:
return DC_STATUS_UNSUPPORTED;
}

80
src/custom_serial.c Normal file
View File

@ -0,0 +1,80 @@
/*
* libdivecomputer
*
* Copyright (C) 2015 Claudiu Olteanu
* base on code that is Copyright (C) 2008 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 <libdivecomputer/custom_serial.h>
#include <serial.h>
#include "context-private.h"
const dc_serial_operations_t native_serial_ops = {
.open = serial_open,
.close = serial_close,
.read = serial_read,
.write = serial_write,
.flush = serial_flush,
.get_received = serial_get_received,
.get_transmitted = serial_get_transmitted,
.set_timeout = serial_set_timeout
};
void
dc_serial_init(dc_serial_t *device, void *data, const dc_serial_operations_t *ops)
{
memset(device, 0, sizeof (*device));
device->data = data;
device->ops = ops;
}
dc_status_t
dc_serial_native_open(dc_serial_t **out, dc_context_t *context, const char *devname)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
dc_serial_t *serial_device = (dc_serial_t *) malloc (sizeof (dc_serial_t));
if (serial_device == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
}
// Initialize data and function pointers
dc_serial_init(serial_device, NULL, &native_serial_ops);
// Open the serial device.
int rc = serial_open (&serial_device->port, context, devname);
if (rc == -1) {
ERROR (context, "Failed to open the serial port.");
free (serial_device);
return DC_STATUS_IO;
}
// Set the type of the device
serial_device->type = DC_TRANSPORT_SERIAL;
*out = serial_device;
return DC_STATUS_SUCCESS;
}

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2008 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -174,6 +175,33 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
return rc;
}
dc_status_t
dc_device_custom_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descriptor, dc_serial_t *serial)
{
dc_status_t rc = DC_STATUS_SUCCESS;
dc_device_t *device = NULL;
if (out == NULL || descriptor == NULL || serial == NULL)
return DC_STATUS_INVALIDARGS;
switch (dc_descriptor_get_type (descriptor)) {
case DC_FAMILY_HW_OSTC3:
rc = hw_ostc3_device_custom_open (&device, context, serial);
break;
case DC_FAMILY_SHEARWATER_PREDATOR:
rc = shearwater_predator_device_custom_open (&device, context, serial);
break;
case DC_FAMILY_SHEARWATER_PETREL:
rc = shearwater_petrel_device_custom_open (&device, context, serial);
break;
default:
return DC_STATUS_INVALIDARGS;
}
*out = device;
return rc;
}
int
dc_device_isinstance (dc_device_t *device, const dc_device_vtable_t *vtable)

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2013 Jef Driesen
* Copyright (C) 2014 Anton Lundin
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -90,7 +91,7 @@ typedef enum hw_ostc3_state_t {
typedef struct hw_ostc3_device_t {
dc_device_t base;
serial_t *port;
dc_serial_t *serial;
unsigned char fingerprint[5];
hw_ostc3_state_t state;
} hw_ostc3_device_t;
@ -186,7 +187,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
// Send the command.
unsigned char command[1] = {cmd};
int n = serial_write (device->port, command, sizeof (command));
int n = device->serial->ops->write (device->serial->port, command, sizeof (command));
if (n != sizeof (command)) {
ERROR (abstract->context, "Failed to send the command.");
return EXITCODE (n);
@ -194,7 +195,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
// Read the echo.
unsigned char echo[1] = {0};
n = serial_read (device->port, echo, sizeof (echo));
n = device->serial->ops->read (device->serial->port, echo, sizeof (echo));
if (n != sizeof (echo)) {
ERROR (abstract->context, "Failed to receive the echo.");
return EXITCODE (n);
@ -213,7 +214,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
if (input) {
// Send the input data packet.
n = serial_write (device->port, input, isize);
n = device->serial->ops->write (device->serial->port, input, isize);
if (n != isize) {
ERROR (abstract->context, "Failed to send the data packet.");
return EXITCODE (n);
@ -227,7 +228,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
unsigned int len = 1024;
// Increase the packet size if more data is immediately available.
int available = serial_get_received (device->port);
int available = device->serial->ops->get_received (device->serial->port);
if (available > len)
len = available;
@ -236,7 +237,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
len = osize - nbytes;
// Read the packet.
n = serial_read (device->port, output + nbytes, len);
n = device->serial->ops->read (device->serial->port, output + nbytes, len);
if (n != len) {
ERROR (abstract->context, "Failed to receive the answer.");
return EXITCODE (n);
@ -255,7 +256,7 @@ hw_ostc3_transfer (hw_ostc3_device_t *device,
if (cmd != EXIT) {
// Read the ready byte.
unsigned char answer[1] = {0};
n = serial_read (device->port, answer, sizeof (answer));
n = device->serial->ops->read (device->serial->port, answer, sizeof (answer));
if (n != sizeof (answer)) {
ERROR (abstract->context, "Failed to receive the ready byte.");
return EXITCODE (n);
@ -289,37 +290,90 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
device_init (&device->base, context, &hw_ostc3_device_vtable);
// Set the default values.
device->port = NULL;
device->serial = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
int rc = serial_open (&device->port, context, name);
if (rc == -1) {
int rc = dc_serial_native_open (&device->serial, context, name);
if (rc != DC_STATUS_SUCCESS) {
ERROR (context, "Failed to open the serial port.");
free (device);
return DC_STATUS_IO;
return rc;
}
// Set the serial communication protocol (115200 8N1).
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
rc = serial_configure (device->serial->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
if (rc == -1) {
ERROR (context, "Failed to set the terminal attributes.");
serial_close (device->port);
device->serial->ops->close (device->serial->port);
free (device);
return DC_STATUS_IO;
}
// Set the timeout for receiving data (3000ms).
if (serial_set_timeout (device->port, 3000) == -1) {
if (serial_set_timeout (device->serial->port, 3000) == -1) {
ERROR (context, "Failed to set the timeout.");
serial_close (device->port);
device->serial->ops->close (device->serial->port);
free (device);
return DC_STATUS_IO;
}
// Make sure everything is in a sane state.
serial_sleep (device->port, 300);
serial_flush (device->port, SERIAL_QUEUE_BOTH);
serial_sleep (device->serial->port, 300);
device->serial->ops->flush (device->serial->port, SERIAL_QUEUE_BOTH);
device->state = OPEN;
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
}
dc_status_t
hw_ostc3_device_custom_open (dc_device_t **out, dc_context_t *context, dc_serial_t *serial)
{
if (out == NULL || serial == NULL || serial->port == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
hw_ostc3_device_t *device = (hw_ostc3_device_t *) malloc (sizeof (hw_ostc3_device_t));
if (device == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
}
// Initialize the base class.
device_init (&device->base, context, &hw_ostc3_device_vtable);
// Set the default values.
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Set the serial reference
device->serial = serial;
if (serial->type == DC_TRANSPORT_SERIAL) {
// Set the serial communication protocol (115200 8N1).
int rc = serial_configure (device->serial->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
if (rc == -1) {
ERROR (context, "Failed to set the terminal attributes.");
device->serial->ops->close (device->serial->port);
free (device);
return DC_STATUS_IO;
}
}
// Set the timeout for receiving data (3000ms).
if (device->serial->ops->set_timeout (device->serial->port, 3000) == -1) {
ERROR (context, "Failed to set the timeout.");
device->serial->ops->close (device->serial->port);
free (device);
return DC_STATUS_IO;
}
// Make sure everything is in a sane state.
serial_sleep (device->serial->port, 300);
device->serial->ops->flush (device->serial->port, SERIAL_QUEUE_BOTH);
device->state = OPEN;
@ -359,17 +413,17 @@ hw_ostc3_device_init_service (hw_ostc3_device_t *device)
int n = 0;
// We cant use hw_ostc3_transfer here, due to the different echos
n = serial_write (device->port, command, sizeof (command));
n = device->serial->ops->write (device->serial->port, command, sizeof (command));
if (n != sizeof (command)) {
ERROR (context, "Failed to send the command.");
return EXITCODE (n);
}
// Give the device some time to enter service mode
serial_sleep (device->port, 100);
serial_sleep (device->serial->port, 100);
// Read the response
n = serial_read (device->port, output, sizeof (output));
n = device->serial->ops->read (device->serial->port, output, sizeof (output));
if (n != sizeof (output)) {
ERROR (context, "Failed to receive the echo.");
return EXITCODE (n);
@ -431,14 +485,14 @@ hw_ostc3_device_close (dc_device_t *abstract)
rc = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
serial_close (device->port);
device->serial->ops->close (device->serial->port);
free (device);
return rc;
}
}
// Close the device.
if (serial_close (device->port) == -1) {
if (device->serial->ops->close (device->serial->port) == -1) {
free (device);
return DC_STATUS_IO;
}

View File

@ -20,6 +20,12 @@
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#include <libdivecomputer/hw_ostc.h>
#include "libdivecomputer/units.h"
@ -57,6 +63,13 @@
#define OSTC3_GAUGE 2
#define OSTC3_APNEA 3
#define OSTC3_ZHL16 0
#define OSTC3_ZHL16_GF 1
#define UNSUPPORTED 0xFFFFFFFF
typedef struct hw_ostc_parser_t hw_ostc_parser_t;
typedef struct hw_ostc_sample_info_t {
unsigned int type;
unsigned int divisor;
@ -72,6 +85,12 @@ typedef struct hw_ostc_layout_t {
unsigned int salinity;
unsigned int duration;
unsigned int temperature;
unsigned int battery;
unsigned int desat;
unsigned int fw_version;
unsigned int deco_info1;
unsigned int deco_info2;
unsigned int decomode;
} hw_ostc_layout_t;
typedef struct hw_ostc_gasmix_t {
@ -82,6 +101,7 @@ typedef struct hw_ostc_gasmix_t {
typedef struct hw_ostc_parser_t {
dc_parser_t base;
unsigned int frog;
unsigned int serial;
// Cached fields.
unsigned int cached;
unsigned int version;
@ -117,6 +137,12 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc = {
43, /* salinity */
47, /* duration */
13, /* temperature */
34, /* battery volt after dive */
17, /* desat */
32, /* fw_version */
49, /* deco_info1 */
50, /* deco_info1 */
51, /* decomode */
};
static const hw_ostc_layout_t hw_ostc_layout_frog = {
@ -128,6 +154,12 @@ static const hw_ostc_layout_t hw_ostc_layout_frog = {
43, /* salinity */
47, /* duration */
19, /* temperature */
34, /* battery volt after dive */
23, /* desat */
32, /* fw_version */
49, /* deco_info1 */
50, /* deco_info2 */
51, /* decomode */
};
static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
@ -139,6 +171,12 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
70, /* salinity */
75, /* duration */
22, /* temperature */
50, /* battery volt after dive */
26, /* desat */
48, /* fw_version */
77, /* deco_info1 */
78, /* deco_info2 */
79, /* decomode */
};
static unsigned int
@ -260,7 +298,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
}
dc_status_t
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int frog)
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int frog)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;
@ -288,6 +326,7 @@ hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int fr
parser->gasmix[i].oxygen = 0;
parser->gasmix[i].helium = 0;
}
parser->serial = serial;
*out = (dc_parser_t *) parser;
@ -380,6 +419,8 @@ hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
return DC_STATUS_SUCCESS;
}
#define BUFLEN 16
static dc_status_t
hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
{
@ -404,9 +445,12 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
dc_field_string_t *string = (dc_field_string_t *) value;
unsigned int salinity = data[layout->salinity];
if (version == 0x23)
salinity += 100;
char buf[BUFLEN];
if (value) {
switch (type) {
@ -497,6 +541,56 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
return DC_STATUS_UNSUPPORTED;
}
break;
case DC_FIELD_STRING:
switch(flags) {
case 0: /* battery */
string->desc = "Battery at end";
snprintf(buf, BUFLEN, "%.2f", array_uint16_le (data + layout->battery) / 1000.0);
break;
case 1: /* desat */
string->desc = "Desat time";
snprintf(buf, BUFLEN, "%0u:%02u", array_uint16_le (data + layout->desat) / 60,
array_uint16_le (data + layout->desat) % 60);
break;
case 2: /* fw_version */
string->desc = "FW Version";
snprintf(buf, BUFLEN, "%0u.%02u", data[layout->fw_version], data[layout->fw_version + 1]);
break;
case 3: /* serial */
string->desc = "Serial";
snprintf(buf, BUFLEN, "%u", parser->serial);
break;
case 4: /* Deco model */
string->desc = "Deco model";
if ((version == 0x23 && data[layout->decomode] == OSTC3_ZHL16) ||
(version == 0x22 && data[layout->decomode] == FROG_ZHL16) ||
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC || data[layout->decomode] == OSTC_ZHL16_CC)))
strncpy(buf, "ZH-L16", BUFLEN);
if ((version == 0x23 && data[layout->decomode] == OSTC3_ZHL16_GF) ||
(version == 0x22 && data[layout->decomode] == FROG_ZHL16_GF) ||
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC_GF || data[layout->decomode] == OSTC_ZHL16_CC_GF)))
strncpy(buf, "ZH-L16-GF", BUFLEN);
else
return DC_STATUS_DATAFORMAT;
break;
case 5: /* Deco model info */
string->desc = "Deco model info";
if ((version == 0x23 && data[layout->decomode] == OSTC3_ZHL16) ||
(version == 0x22 && data[layout->decomode] == FROG_ZHL16) ||
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC || data[layout->decomode] == OSTC_ZHL16_CC)))
snprintf(buf, BUFLEN, "Saturation %u, Desaturation %u", layout->deco_info1, layout->deco_info2);
if ((version == 0x23 && data[layout->decomode] == OSTC3_ZHL16_GF) ||
(version == 0x22 && data[layout->decomode] == FROG_ZHL16_GF) ||
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC_GF || data[layout->decomode] == OSTC_ZHL16_CC_GF)))
snprintf(buf, BUFLEN, "GF %u/%u", data[layout->deco_info1], data[layout->deco_info2]);
else
return DC_STATUS_DATAFORMAT;
break;
default:
return DC_STATUS_UNSUPPORTED;
}
string->value = strdup(buf);
break;
default:
return DC_STATUS_UNSUPPORTED;
}

View File

@ -82,6 +82,9 @@ dc_device_set_events
dc_device_set_fingerprint
dc_device_write
dc_serial_init
dc_device_custom_open
cressi_edy_device_open
cressi_leonardo_device_open
mares_nemo_device_open

View File

@ -20,6 +20,8 @@
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libdivecomputer/oceanic_atom2.h>
#include <libdivecomputer/units.h>
@ -86,6 +88,7 @@ struct oceanic_atom2_parser_t {
unsigned int model;
unsigned int headersize;
unsigned int footersize;
unsigned int serial;
// Cached fields.
unsigned int cached;
unsigned int divetime;
@ -109,7 +112,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)
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;
@ -151,6 +154,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
parser->headersize = 5 * PAGESIZE;
}
parser->serial = serial;
parser->cached = 0;
parser->divetime = 0;
parser->maxdepth = 0.0;
@ -318,6 +322,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
return DC_STATUS_SUCCESS;
}
#define BUF_LEN 16
static dc_status_t
oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
@ -366,9 +371,11 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
dc_field_string_t *string = (dc_field_string_t *) value;
unsigned int oxygen = 0;
unsigned int helium = 0;
char buf[BUF_LEN];
if (value) {
switch (type) {
@ -452,6 +459,17 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
return DC_STATUS_DATAFORMAT;
}
break;
case DC_FIELD_STRING:
switch(flags) {
case 0: /* Serial */
string->desc = "Serial";
snprintf(buf, BUF_LEN, "%06u", parser->serial);
break;
default:
return DC_STATUS_UNSUPPORTED;
}
string->value = strdup(buf);
break;
default:
return DC_STATUS_UNSUPPORTED;
}

View File

@ -66,7 +66,7 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
break;
case DC_FAMILY_SUUNTO_VYPER2:
case DC_FAMILY_SUUNTO_D9:
rc = suunto_d9_parser_create (&parser, context, device->devinfo.model);
rc = suunto_d9_parser_create (&parser, context, device->devinfo.model, device->devinfo.serial);
break;
case DC_FAMILY_SUUNTO_EONSTEEL:
rc = suunto_eonsteel_parser_create(&parser, context, device->devinfo.model);
@ -98,7 +98,7 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
if (device->devinfo.model == REACTPROWHITE)
rc = oceanic_veo250_parser_create (&parser, context, device->devinfo.model);
else
rc = oceanic_atom2_parser_create (&parser, context, device->devinfo.model);
rc = oceanic_atom2_parser_create (&parser, context, device->devinfo.model, device->devinfo.serial);
break;
case DC_FAMILY_MARES_NEMO:
case DC_FAMILY_MARES_PUCK:
@ -111,11 +111,11 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
rc = mares_iconhd_parser_create (&parser, context, device->devinfo.model);
break;
case DC_FAMILY_HW_OSTC:
rc = hw_ostc_parser_create (&parser, context, 0);
rc = hw_ostc_parser_create (&parser, context, device->devinfo.serial, 0);
break;
case DC_FAMILY_HW_FROG:
case DC_FAMILY_HW_OSTC3:
rc = hw_ostc_parser_create (&parser, context, 1);
rc = hw_ostc_parser_create (&parser, context, device->devinfo.serial, 1);
break;
case DC_FAMILY_CRESSI_EDY:
case DC_FAMILY_ZEAGLE_N2ITION3:
@ -128,10 +128,10 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
rc = atomics_cobalt_parser_create (&parser, context);
break;
case DC_FAMILY_SHEARWATER_PREDATOR:
rc = shearwater_predator_parser_create (&parser, context);
rc = shearwater_predator_parser_create (&parser, context, device->devinfo.serial);
break;
case DC_FAMILY_SHEARWATER_PETREL:
rc = shearwater_petrel_parser_create (&parser, context);
rc = shearwater_petrel_parser_create (&parser, context, device->devinfo.serial);
break;
case DC_FAMILY_DIVERITE_NITEKQ:
rc = diverite_nitekq_parser_create (&parser, context);

View File

@ -418,8 +418,10 @@ serial_configure (serial_t *device, int baudrate, int databits, int parity, int
// Apply the new settings.
if (tcsetattr (device->fd, TCSANOW, &tty) != 0) {
#if 0 // who cares
SYSERROR (device->context, errno);
return -1;
#endif
}
// Configure a custom baudrate if necessary.

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2013 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -41,30 +42,61 @@ dc_status_t
shearwater_common_open (shearwater_common_device_t *device, dc_context_t *context, const char *name)
{
// Open the device.
int rc = serial_open (&device->port, context, name);
int rc = dc_serial_native_open (&device->serial, context, name);
if (rc == -1) {
ERROR (context, "Failed to open the serial port.");
return DC_STATUS_IO;
}
// Set the serial communication protocol (115200 8N1).
rc = serial_configure (device->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
rc = serial_configure (device->serial->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
if (rc == -1) {
ERROR (context, "Failed to set the terminal attributes.");
serial_close (device->port);
device->serial->ops->close (device->serial->port);
return DC_STATUS_IO;
}
// Set the timeout for receiving data (3000ms).
if (serial_set_timeout (device->port, 3000) == -1) {
if (serial_set_timeout (device->serial->port, 3000) == -1) {
ERROR (context, "Failed to set the timeout.");
serial_close (device->port);
device->serial->ops->close (device->serial->port);
return DC_STATUS_IO;
}
// Make sure everything is in a sane state.
serial_sleep (device->port, 300);
serial_flush (device->port, SERIAL_QUEUE_BOTH);
serial_sleep (device->serial->port, 300);
device->serial->ops->flush (device->serial->port, SERIAL_QUEUE_BOTH);
return DC_STATUS_SUCCESS;
}
dc_status_t
shearwater_common_custom_open (shearwater_common_device_t *device, dc_context_t *context, dc_serial_t *serial)
{
// Set the serial reference
device->serial = serial;
if (serial->type == DC_TRANSPORT_SERIAL) {
// Set the serial communication protocol (115200 8N1).
int rc = serial_configure (device->serial->port, 115200, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
if (rc == -1) {
ERROR (context, "Failed to set the terminal attributes.");
device->serial->ops->close (device->serial->port);
return DC_STATUS_IO;
}
}
// Set the timeout for receiving data (3000ms).
if (device->serial->ops->set_timeout (device->serial->port, 3000) == -1) {
ERROR (context, "Failed to set the timeout.");
device->serial->ops->close (device->serial->port);
return DC_STATUS_IO;
}
// Make sure everything is in a sane state.
serial_sleep (device->serial->port, 300);
device->serial->ops->flush (device->serial->port, SERIAL_QUEUE_BOTH);
return DC_STATUS_SUCCESS;
}
@ -74,7 +106,7 @@ dc_status_t
shearwater_common_close (shearwater_common_device_t *device)
{
// Close the device.
if (serial_close (device->port) == -1) {
if (device->serial->ops->close (device->serial->port) == -1) {
return DC_STATUS_IO;
}
@ -154,7 +186,7 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
#if 0
// Send an initial END character to flush out any data that may have
// accumulated in the receiver due to line noise.
n = serial_write (device->port, end, sizeof (end));
n = device->serial->ops->write (device->serial->port, end, sizeof (end));
if (n != sizeof (end)) {
return EXITCODE(n);
}
@ -183,7 +215,7 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
// Flush the buffer if necessary.
if (nbytes + len + sizeof(end) > sizeof(buffer)) {
n = serial_write (device->port, buffer, nbytes);
n = device->serial->ops->write (device->serial->port, buffer, nbytes);
if (n != nbytes) {
return EXITCODE(n);
}
@ -201,7 +233,7 @@ shearwater_common_slip_write (shearwater_common_device_t *device, const unsigned
nbytes += sizeof(end);
// Flush the buffer.
n = serial_write (device->port, buffer, nbytes);
n = device->serial->ops->write (device->serial->port, buffer, nbytes);
if (n != nbytes) {
return EXITCODE(n);
}
@ -224,7 +256,7 @@ shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char d
int n = 0;
// Get a single character to process.
n = serial_read (device->port, &c, 1);
n = device->serial->ops->read (device->serial->port, &c, 1);
if (n != 1) {
return EXITCODE(n);
}
@ -243,7 +275,7 @@ shearwater_common_slip_read (shearwater_common_device_t *device, unsigned char d
case ESC:
// If it's an ESC character, get another character and then
// figure out what to store in the packet based on that.
n = serial_read (device->port, &c, 1);
n = device->serial->ops->read (device->serial->port, &c, 1);
if (n != 1) {
return EXITCODE(n);
}

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2013 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -24,6 +25,7 @@
#include "device-private.h"
#include "serial.h"
#include "libdivecomputer/custom_serial.h"
#ifdef __cplusplus
extern "C" {
@ -34,12 +36,15 @@ extern "C" {
typedef struct shearwater_common_device_t {
dc_device_t base;
serial_t *port;
dc_serial_t *serial;
} shearwater_common_device_t;
dc_status_t
shearwater_common_open (shearwater_common_device_t *device, dc_context_t *context, const char *name);
dc_status_t
shearwater_common_custom_open (shearwater_common_device_t *device, dc_context_t *context, dc_serial_t *serial);
dc_status_t
shearwater_common_close (shearwater_common_device_t *device);

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2013 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -110,6 +111,40 @@ shearwater_petrel_device_open (dc_device_t **out, dc_context_t *context, const c
}
dc_status_t
shearwater_petrel_device_custom_open (dc_device_t **out, dc_context_t *context, dc_serial_t *serial)
{
dc_status_t rc = DC_STATUS_SUCCESS;
if (out == NULL || serial == NULL || serial->port == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
shearwater_petrel_device_t *device = (shearwater_petrel_device_t *) malloc (sizeof (shearwater_petrel_device_t));
if (device == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
}
// Initialize the base class.
device_init (&device->base.base, context, &shearwater_petrel_device_vtable);
// Set the default values.
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
rc = shearwater_common_custom_open (&device->base, context, serial);
if (rc != DC_STATUS_SUCCESS) {
free (device);
return rc;
}
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
}
static dc_status_t
shearwater_petrel_device_close (dc_device_t *abstract)
{

View File

@ -2,6 +2,7 @@
* libdivecomputer
*
* Copyright (C) 2012 Jef Driesen
* Copyright (C) 2015 Claudiu Olteanu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -96,6 +97,40 @@ shearwater_predator_device_open (dc_device_t **out, dc_context_t *context, const
}
dc_status_t
shearwater_predator_device_custom_open (dc_device_t **out, dc_context_t *context, dc_serial_t *serial)
{
dc_status_t rc = DC_STATUS_SUCCESS;
if (out == NULL || serial == NULL || serial->port == NULL)
return DC_STATUS_INVALIDARGS;
// Allocate memory.
shearwater_predator_device_t *device = (shearwater_predator_device_t *) malloc (sizeof (shearwater_predator_device_t));
if (device == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
}
// Initialize the base class.
device_init (&device->base.base, context, &shearwater_predator_device_vtable);
// Set the default values.
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
rc = shearwater_common_custom_open (&device->base, context, serial);
if (rc != DC_STATUS_SUCCESS) {
free (device);
return rc;
}
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
}
static dc_status_t
shearwater_predator_device_close (dc_device_t *abstract)
{

View File

@ -20,6 +20,12 @@
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#include <libdivecomputer/shearwater_predator.h>
#include <libdivecomputer/shearwater_petrel.h>
@ -61,6 +67,7 @@ struct shearwater_predator_parser_t {
unsigned int ngasmixes;
unsigned int oxygen[NGASMIXES];
unsigned int helium[NGASMIXES];
unsigned int serial;
};
static dc_status_t shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
@ -89,7 +96,7 @@ static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
dc_status_t
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int petrel)
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int petrel)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;
@ -103,6 +110,7 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
// Initialize the base class.
parser->petrel = petrel;
parser->serial = serial;
if (petrel) {
parser_init (&parser->base, context, &shearwater_petrel_parser_vtable);
parser->samplesize = SZ_SAMPLE_PETREL;
@ -128,16 +136,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)
shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial)
{
return shearwater_common_parser_create (out, context, 0);
return shearwater_common_parser_create (out, context, serial, 0);
}
dc_status_t
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context)
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial)
{
return shearwater_common_parser_create (out, context, 1);
return shearwater_common_parser_create (out, context, serial, 1);
}
@ -188,6 +196,8 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d
}
#define BUFLEN 16
static dc_status_t
shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
{
@ -291,7 +301,9 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
dc_field_string_t *string = (dc_field_string_t *) value;
unsigned int density = 0;
char buf[BUFLEN];
if (value) {
switch (type) {
@ -325,6 +337,24 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
break;
case DC_FIELD_DIVEMODE:
*((dc_divemode_t *) value) = shearwater_predator_parser_get_divemode (parser);
case DC_FIELD_STRING:
switch(flags) {
case 0: // Battery
string->desc = "Battery at end";
snprintf(buf, BUFLEN, "%.1f", data[9] / 10.0);
break;
case 1: // Serial
string->desc = "Serial";
snprintf(buf, BUFLEN, "%08x", parser->serial);
break;
case 2: // FW Version
string->desc = "FW Version";
snprintf(buf, BUFLEN, "%2x", data[19]);
break;
default:
return DC_STATUS_UNSUPPORTED;
}
string->value = strdup(buf);
break;
default:
return DC_STATUS_UNSUPPORTED;
@ -390,9 +420,11 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
// Status flags.
unsigned int status = data[offset + 11];
// PPO2
sample.ppo2 = data[offset + 6] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
// PPO2 -- only return PPO2 if we are in closed circuit mode
if (data[offset + 11] & 0x10 == 0) {
sample.ppo2 = data[offset + 6] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
}
if ((status & OC) == 0) {
// Setpoint

View File

@ -20,7 +20,8 @@
*/
#include <stdlib.h>
#include <string.h> // memcmp
#include <string.h> // memcmp, strdup
#include <stdio.h> // snprintf
#include <libdivecomputer/suunto_d9.h>
@ -62,6 +63,7 @@ typedef struct suunto_d9_parser_t suunto_d9_parser_t;
struct suunto_d9_parser_t {
dc_parser_t base;
unsigned int model;
unsigned int serial;
// Cached fields.
unsigned int cached;
unsigned int mode;
@ -188,7 +190,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)
suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;
@ -205,6 +207,7 @@ suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
// Set the default values.
parser->model = model;
parser->serial = serial;
parser->cached = 0;
parser->mode = AIR;
parser->ngasmixes = 0;
@ -289,6 +292,7 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
return DC_STATUS_SUCCESS;
}
#define BUFLEN 16
static dc_status_t
suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
@ -304,6 +308,9 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
return rc;
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_field_string_t *string = (dc_field_string_t *) value;
char buf[BUFLEN];
if (value) {
switch (type) {
@ -349,6 +356,17 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
return DC_STATUS_DATAFORMAT;
}
break;
case DC_FIELD_STRING:
switch (flags) {
case 0: /* serial */
string->desc = "Serial";
snprintf(buf, BUFLEN, "%08u", parser->serial);
break;
default:
return DC_STATUS_UNSUPPORTED;
}
string->value = strdup(buf);
break;
default:
return DC_STATUS_UNSUPPORTED;
}

View File

@ -21,8 +21,14 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
/* Wow. MSC is truly crap */
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#include <libdivecomputer/suunto_eonsteel.h>
#include "context-private.h"
@ -68,6 +74,7 @@ struct type_desc {
#define MAXTYPE 512
#define MAXGASES 16
#define MAXSTRINGS 16
typedef struct suunto_eonsteel_parser_t {
dc_parser_t base;
@ -82,6 +89,7 @@ typedef struct suunto_eonsteel_parser_t {
dc_gasmix_t gasmix[MAXGASES];
dc_salinity_t salinity;
double surface_pressure;
dc_field_string_t strings[MAXSTRINGS];
} cache;
} suunto_eonsteel_parser_t;
@ -568,6 +576,7 @@ static void sample_gas_switch_event(struct sample_data *info, unsigned short idx
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.value = o2 | (he << 16);
sample.event.flags = idx;
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
}
@ -868,6 +877,19 @@ suunto_eonsteel_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback
return DC_STATUS_SUCCESS;
}
static dc_status_t get_string_field(suunto_eonsteel_parser_t *eon, unsigned idx, dc_field_string_t *value)
{
if (idx < MAXSTRINGS) {
dc_field_string_t *res = eon->cache.strings+idx;
if (res->desc && res->value) {
*value = *res;
return DC_STATUS_SUCCESS;
}
}
return DC_STATUS_UNSUPPORTED;
}
// Ugly define thing makes the code much easier to read
// I'd love to use __typeof__, but that's a gcc'ism
#define field_value(p, set) \
@ -905,6 +927,8 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi
case DC_FIELD_ATMOSPHERIC:
field_value(value, eon->cache.surface_pressure);
break;
case DC_FIELD_STRING:
return get_string_field(eon, flags, (dc_field_string_t *)value);
default:
return DC_STATUS_UNSUPPORTED;
}
@ -980,6 +1004,22 @@ static int add_gas_he(suunto_eonsteel_parser_t *eon, unsigned char he)
return 0;
}
static int add_string(suunto_eonsteel_parser_t *eon, const char *desc, const char *value)
{
int i;
eon->cache.initialized |= 1 << DC_FIELD_STRING;
for (i = 0; i < MAXSTRINGS; i++) {
dc_field_string_t *str = eon->cache.strings+i;
if (str->desc)
continue;
str->desc = desc;
str->value = strdup(value);
break;
}
return 0;
}
static float get_le32_float(const unsigned char *src)
{
union {
@ -1003,7 +1043,16 @@ static int traverse_device_fields(suunto_eonsteel_parser_t *eon, const struct ty
const unsigned char *data, int len)
{
const char *name = desc->desc + strlen("sml.DeviceLog.Device.");
if (!strcmp(name, "SerialNumber"))
return add_string(eon, "Serial", data);
if (!strcmp(name, "Info.HW"))
return add_string(eon, "HW Version", data);
if (!strcmp(name, "Info.SW"))
return add_string(eon, "FW Version", data);
if (!strcmp(name, "Info.BatteryAtStart"))
return add_string(eon, "Battery at start", data);
if (!strcmp(name, "Info.BatteryAtEnd"))
return add_string(eon, "Battery at end", data);
return 0;
}
@ -1063,6 +1112,9 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty
if (!strcmp(name, "Gases.Gas.Helium"))
return add_gas_he(eon, data[0]);
if (!strcmp(name, "Gases.Gas.TransmitterID"))
return add_string(eon, "Transmitter ID", data);
if (!strcmp(name, "SurfacePressure")) {
unsigned int pressure = array_uint32_le(data); // in SI units - Pascal
eon->cache.surface_pressure = pressure / 100000.0; // bar
@ -1070,6 +1122,21 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty
return 0;
}
if (!strcmp(name, "Algorithm"))
return add_string(eon, "Deco algorithm", data);
if (!strcmp(name, "DiveMode"))
return add_string(eon, "Dive Mode", data);
/* Signed byte of conservatism (-2 .. +2) */
if (!strcmp(name, "Conservatism")) {
char buffer[10];
int val = *(signed char *)data;
snprintf(buffer, sizeof(buffer), "P%d", val);
return add_string(eon, "Personal Adjustment", buffer);
}
return 0;
}
@ -1096,6 +1163,8 @@ static int traverse_header_fields(suunto_eonsteel_parser_t *eon, const struct ty
eon->cache.maxdepth = d;
return 0;
}
if (!strcmp(name, "DateTime"))
return add_string(eon, "Dive ID", data);
return 0;
}