Merge with upstream libdivecomputer from Jef.
This fixes some sleeping functions, and also implements support for the
Tecdiving DiveComputer.eu dive computers.
There's also various minor cleanups. Most notable is perhaps the
unification of the Uwatec dive computer backends.
* git://github.com/libdivecomputer/libdivecomputer:
Initialize the socket library for the bluetooth discovery
Fix the length of the Suunto D6i gas change event
Add support for the Tecdiving DiveComputer.eu
Fix the Mac OS X timer implementation
Add the average depth to the xml output
Skip the handshake for BLE communication
Unify the Uwatec Smart, Meridian and G2 backends
Re-organize the packet send/receive code
Use symbolic constants for the commands
Implement an rfcomm filter function
Remove the filter for HW OSTC's without bluetooth
Implement the sleep function for IrDA and bluetooth
This adds the string field interface to the Suunto D9 family.
It's really just the proper serial number handling. From Dirk's
original commit:
"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"
so thus just serial number.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Add a new type to distinguish between closed circuit (CCR) and
semi-closed circuit (SCR) diving. Some dive computers from HW and
DiveSystem/Ratio support this.
Because the CCR/SCR abbreviations are more commonly used, let's take the
opportunity to also rename the existing DC_DIVEMODE_CC. To preserve
backwards compatibility, a macro is added to map the old name to the new
one.
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Allthough most dive computers always use local time and don't support
timezones at all, there are a few exceptions. There are two different
sources of timezone information:
- Some of the newer Uwatec/Scubapro devices use UTC internally and also
support a timezone setting. This UTC offset is currently taken into
account to obtain the dive date/time, but the UTC offset itself is
lost.
- Uwatec/Scubapro and Reefnet devices rely on the clock of the host
system to synchronize the internal device clock and calculate the
dive date/time. The consequence is that the resulting date/time is
always in the timezone of the host system.
In order to preserve this timezone information, the dc_datetime_t
structure is extended with a new "timezone" field, containing the UTC
offset in seconds. Devices without timezone support will set the field
to the special value DC_TIMEZONE_NONE.
The dc_datetime_localtime() and dc_datetime_gmtime() functions will
automatically populate the new field with respectively the local
timezone offset and zero. The dc_datetime_mktime() function will take
into account the new timezone field for the conversion to UTC. The
special value DC_TIMEZONE_NONE is interpreted as zero.
The vendor_product_parser_create() and vendor_product_device_open()
functions should be called indirectly, through the generic
dc_device_open() and dc_parser_new() functions. And the
vendor_product_extract_dives() functions are internal functions that
should never have been part of the public api in the first place.
Just like the D4i and D6i, the new header is a few bytes larger. The
correct variant can again be detected by means of the logbook id tag at
the start of the header.
One of the newer D4i and D6i firmware versions (for example v1.5.9),
introduces a new variant of the data format. The new dive header is 8
bytes larger. The correct variant can be detected by means of the
logbook id tag at the start of the header.
Both the allocation and initialization of the object data structure is
now moved to a single function. The corresponding deallocation function
is intended to free objects that have been allocated, but are not fully
initialized yet. The public cleanup function shouldn't be used in such
case, because it may try to release resources that haven't been
initialized yet.
Instead of freeing the object data structure in the backend specific
cleanup function, the memory is now freed automatically in the base
class function. This reduces the amount of boilerplate code in the
backends. Backends that don't allocate any additional resources, do no
longer require a cleanup function at all.
The new gasmix sample contains the index of the active gas mix.
This new sample is intended as a replacement for the existing gas change
events (SAMPLE_EVENT_GASCHANGE and SAMPLE_EVENT_GASCHANGE2). To maintain
backwards compatibility, the legacy events are marked as deprecated but
not removed yet.
The newest Suunto models (e.g. D4i, D6i, D9tx and DX) support a few
additional events (type 0x15 and higher), which are not supported yet
because their interpretation isn't known.
Due to a nasty bug, these unkown events result in "ghost" events. When
such an unknown event is encountered, the sample type field isn't set
explicitely. Therefore it simply retains the value from the previous
sample, whatever that might be. If the previous sample happens to be an
event as well, then the unknown event will show up as a duplicate event.
But if the previous sample is not an event, then the resulting event
type is undefined.
This is fixed by always resetting the event type explicitely. Those
unknown events are also suppressed now and no longer delivered to the
application.
Allthough I haven't observed this bug with the Suunto Eon and Vyper,
they could be affected too.
For the older models, gas mixes are disabled by setting their oxygen
percentage byte to 0x00 or 0xFF. Trying to parse such a byte as a valid
percentage results in an invalid gas mix.
Because the device doesn't allow you to enable a gas mix if the previous
gas mix has already been disabled, we can simply stop parsing the gas
mixes once the first disabled gas mix has been found.
The gas mode should not only be taken into account for parsing the gas
mix definitions, but also for the initial gas mix. Because the logic
needs to be kept in sync, it's convenient to have all related code in a
single place, and cache the value.
Because the gas mode takes precedence over the individual gas mix
definitions, we can simplify the code by taking the gas mode into
account immediately when parsing the gas mixes.
The initial gas mix index has been confirmed for the D6i only. For the
other two models, it's an educated guess that the byte offset will be
identical.
The Suunto dive computers record gas change events in the profile data.
But because there is no gas change event stored on the first sample, the
application doesn't know which gas mix is in use, until the very first
gas change event occurs.
For the Suunto HelO2, the index of the initial gas mix is stored in the
dive header. This is most likely also the case for the other models, but
I haven't found yet where exactly it is stored. As a temporary solution,
we simply assume the initial gas mix is the first gas in the list with
available gas mixes. This should be a reasonable assumption for most
dives.
Fixes ticket #2
The gas mix data is used from multiple functions, and the code to parse
that data is duplicated in each function. Because this is error prone,
the code is moved to a single place, and the data cached in the parser.
This event is on when accumulating deco time. Once you reach the floor
deco time will start decreasing and the event will stop. Going below the
floor again will re-activate the event.
Signed-off-by: Michael Andreen <harv@ruin.nu>
The Suunto DX has support for 8 gas mixes (OC) and 3 diluents (CC).
Because it's still unknown how rebreather dives are stored, we simply
return all 11 gas mixes. For the rest, the DX data format is very
similar to that of the existing Suunto models, with only a few
different offsets here and there.
When the number of parameters is zero, there are no sample values, and
the offset variable is never increased. The result is an infinite loop.
In practice this shouldn't happen because there should always be at
least one sample value (e.g. depth). But if a new data format is
available, which is not yet supported by the parser, we might be trying
to interpret the wrong byte.
Currently, each backend has it's own function to verify whether the
object vtable pointer is the expected one. All these functions can be
removed in favor of a single isintance function in the base class,
which takes the expected vtable pointer as a parameter.
Functions which are called through the vtable, don't need to verify the
vtable pointer, and those checks are removed.
The term "backend" can be confusing because it can refer to both the
virtual function table and the device/parser backends. The use of the
term "vtable" avoids this.
After the new firmware upgrade, up to three gas mixes are available
instead of only two. This causes the parsing to fail because there is
now an extra 6 byte gasmix block in the header.
Unfortunately, we can't rely on the firmware version to detect whether
this extra gasmix is present or not. In theory the dive computer can
contain dives in both the old and the new format. Because the firmware
version is a property of the device, and not stored inside each dive,
using the firmware version would either cause the old or the new dives
to fail parsing. This appears to be the approach DM4 is using.
According to some sources on the internet, the logbook gets erased
during the firmware update. However, according to the memory dumps I
received, that appears to be incorrect. The old dives are still
present, and it seems it's only DM4 that fails to download them.
So we need an alternative solution. After a detailed analysis of all
the Suunto dives at my disposal, I noticed something interesting. The
first 5 bytes of each dive are almost static. There are only 5
different variations:
0061906216
0061A06216
0062909118
0062C07118
0063C07118
The interpretation of these bytes is currently unknown, but the second
byte might be some kind of data format version. Each model always has
the same value here, and for the D6i it changes after the firmware
update:
0x61: D4, D6, D9, Cobra 2, Cobra3, Vyper 2, Vyper Air
0x62: D4i, D6i (old firmware), D9tx, HelO2
0x63: D6i (new firmware)
This can't be coincidence, so we use this byte to detect the presence
of the extra gasmix.
The HelO2, D4i, D6i and D9tx all use the same data format for the gas
mixes. The only difference is the number of gas mixes and the initial
byte offset. With this knowledge, we can easily use the same code for
all models. An additional advantage is that because the profile
configuration data is stored immediately after the gasmix section, we
can also replace the hardcoded offset with a simple calculation.
This macro was used to compensate for the fact that the 4 bytes at the
start of each dive, containing the previous and next dive pointers, are
stripped. With the SKIP macro the byte offset remained the same as in
the documentation. Nowadays, this compatibility isn't necessary anymore
and it only makes interpreting the raw binary data more difficult.
The second gas change event (type 0x06) contains both the oxygen and
helium percentages. These are now reported correctly with the new
GASCHANGE2 event.
The D9 family has begin and end of the deco event and we can therefore
convert this to the deco sample. For compatibility with existing software
we keep the events around.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When the gas model setting is set to air, the individual gas mix
definitions retain their previous (non-air) values. This is convenient
to avoid having to adjust the gas mixes again on your next nitrox or
mixed gas dive. But the consequence is that for air dives, the gas model
should take precedence over the individual gas mix definitions, and a
single mix with air is returned instead.
I forgot to update the device and parser initialization functions to
store the context pointer into the objects. As a result, the internal
context pointers were always NULL.
The public api is changed to require a context object for all
operations. Because other library objects store the context pointer
internally, only the constructor functions need an explicit context
object as a parameter.
Adding the "dc_" namespace prefix (which is of course an abbreviation
for libdivecomputer) should avoid conflicts with other libraries. For
the time being, only the high-level device and parser layers are
changed.