Merge upstream updates from Jef Driesen:
- Deepblu Cosmiq+ support has been merged upstream
- Oceans S1 support has been merged upstream
- Various new models supported: Cressi Donatello, Scubapro G2 TEK, new
Excursion v6+ firmware.
- misc core changes, most notably supporting a new annoying specialized
binary format for "decomode", because Jef still can't deal with
strings.
- lots of small details
* https://github.com/libdivecomputer/libdivecomputer: (58 commits)
Keep open-circuit and diluent gas mixes separately
Parse some extra gas mix information
Limit the index to the fixed gas mixes
Handle dives without a valid gas mix more explicit
Ignore all gas mixes for freedives
Always include all gas mixes defined in the header
Add support for the new Excursion v6+ firmware
Add support for the HP CCR tank pressure
Use the correct field for the setpoint sample
Add support for the Oceans S1
Add support for the Deepblu Cosmiq+
Add missing functions for accessing big/little endian values
Move the snprintf functions to the platform module
Repeat the handshake every few packets
Enable big page support
Remove the model number from the vtpro struct
Add the model number to the version table
Move all model numbers to the common header
Remove a duplicated include statement
Add support for the 300bar pressure sensor
...
The OSTC stores either the OC gas mixes or the CCR diluents depending on
the dive mode. For CCR dives, there is also bailout to an OC gas
possible, and those gas mixes are added dynamically to the manual gas
mixes.
The Shearwater dive computers store both the configured OC gas mixes and
CCR diluents in the header.
In both cases, the gas change events should reference the correct type
of gas mix. This patch takes care of that.
Keep track of the gas mix type, and whether the gas mix is enabled or
not. Right now this extra information isn't really used for anything
yet, but it's available for future use.
The index in the gas change event should refer to the one of the fixed
gas mixes. All gas mixes with a higher index are either manual or
bailout gas mixes, and are reported with different events containing an
O2 and He percentages instead.
Dives without a valid gas mix in the sample data (e.g. both the O2 and
He set to zero) are currently ignored by accident. Because the
o2_previous and he_previous variables were initialized to zero, those
invalid gas mixes were not processed.
Add an explicit check for such gas mixes to make this more obvious.
For freedives it makes no sense to report any gas mixes. The freedives
also use a different sample format, which doesn't generate any gas
change events.
Especially among technical divers, it's not uncommon to carry spare
tanks that will only be used in emergency situations (for example a
rebreather with one or more bailout tanks). Since those gas mixes are
not used throughout the dive, they were also not reported to the
application.
Fixed by reporting all configured gas mixes. Applications can still
obtain the previous result after manually inspecting the gas switch
events in the samples and filtering out the unused gas mixes.
This partially reverts commit c8b166dadbf961e17a9bd1cc28db3d92832ddf72.
DECLARE_FIELD() uses array_uint_endian() to turn an integer type into
the right endianness. It's all conditional on being an integer type,
but the compiler still sees the assignment (with a cast) for other
types, and complains about casting the 'unsigned int' return value to a
pointer, even when that case is not actually dynamically ever taken.
Fix the compiler warning by just changing the return type of this
conversion function to 'unsigned long' instead, which will match the
size of pointers on all relevant architectures.
Don't look at that macro too closely, you'll go blind.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
As a CCR diver I would like to see the ability to properly track the 'on
loop' / 'bailed out to open circuit' status directly in Subsurface,
because this is an important (or even the most important) bit of status
information during a CCR dive. This should extend to the use of the
correct ppO2 / gas mix in the deco ceiling / tissue model calculation.
My idea for how to do this would be to track the 'type' ('diluent' / 'OC
bailout') for every gasmix / tank that is reported by the dive computer.
Most CCR capable dive computers that I am familiar with require the user
to enter two different gas lists for diluent and bailout, so this should
work with the existing libdivecomputer API for these. Unfortunately I
think making this change in Subsurface will require a bit of work, as
the libdivecomputer field capable of tracking the 'type' of a gas or
tank (`cache->tankinfo[]`) does not seem to be consumed at all in
Subsurface.
So this just provides a prerequisite for the change in Subsurface by
populating `tankinfo[]`. In addition to this it also triggers a message
on every switch from CC to OC and back, at least giving a visual
indication of these diver triggered events. The messages can probably
be removed from libdivecomputer again once 'loop status' tracking has
been added to Subsurface.
Also included is a fix of the tab expansion mess that I created in
commit 2129403 ("Added facility to detect and interpret manual setpoint
switches for Garmin Descent computers"). Apologies for this, I've
switched to using a custom `.vimrc` for this project now.
[ Edited up the commit message a bit further - Linus ]
Signed-off-by: Michael Keller <github@ike.ch>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Push accesses to cached fields down into `field-cache.c` from parsers
that use the field cache.
As a result, all cached fields will be available to Subsurface in
computer models that use the field cache.
In particular this means that the proper use type (diluent / OC bailout)
of tanks will be shown for the Garmin Descent dive computers once that
is merged.
[ Edited commit message and massaged the deepblu and Eon Steel parsers
to not complain about unhandled switch statement cases. - Linus ]
Signed-off-by: Michael Keller <github@ike.ch>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The new Excursion v6 firmware supports some new commands for accessing
the dive index, and also uses a completely new data format. To preserve
backwards compatibility in the download logic to some extent, some
critical fields such as the profile length, remain stored at identical
offsets.
The new data format now contains a version field to allow for future
modifications. This version field is located at byte offset 3, which
corresponds to the highest byte of the 32 bit dive number in the old
format. Thus, unless someone manages to reach 16M dives, this field will
always be zero for the old format.
Co-authored-by: Ryan Gardner <ryebrye@gmail.com>
For the HP CCR mode, the O2 and diluent tank pressure was stored in the
T1 and T2 tank pressure fields. Starting from log version 14 they moved
to dedicated fields in the EXT sample, next to the T3 and T4 tank
pressure. Thus the maximum number of tanks increased from 4 to 6.
The Oceans S1 uses a plaintext and line based communication protocol
over BLE. The larger payloads, which also contain plaintext data, are
transferred using the XMODEM-CRC protocol.
Based-on-code-by: Linus Torvalds <torvalds@linux-foundation.org>
The Deepblu Cosmiq+ uses a plaintext and line based communication
protocol over BLE, where the binary payload data is encoded as
hexadecimal characters.
Based-on-code-by: Linus Torvalds <torvalds@linux-foundation.org>
There are functions for reading 8, 16, 24 and 32-bit big and little
endian values, but the corresponding functions for writing such values
are not always available. The 64-bit variants are also missing.
Moving the implementation of the snprintf wrapper functions to the
platform module allows to re-use the same implementation throughout the
entire codebase.
The Oceanic Pro Plus 4 appears to "disconnect" somehow after about 30
seconds. The BLE connection remains up, but the dive computer simply
stops responding to commands. The download fails with a timeout error,
and the end-user can only download a few dives at most.
The Android DiverLog+ application appears to keep the connection alive
by re-sending the version and handshake commands once in a while. Copy
this behaviour by repeating those two commands every 50 read requests.
During testing, that's approximately every 25 seconds.
Note that both commands are required, sending only one of them does not
fix the problem.
The Oceanic Pro Plus 4 appears to support the big page B4 and B8 read
commands, but with some strange twists:
* When sending the B8 read command, a 256 byte packet is received. The
checksums of the packet are valid, but the upper half of the payload
data is always filled with zero bytes. That means we can't use this
command.
* The B4 read command appears to use a 2 byte checksum instead of the
normal 1 byte checksum. That means we can use this command with a
small model specific tweak.
The model number is now also available in the common struct. There is no
need to store it twice. The auto-detected model number from the version
table is also more reliable than the one passed by the caller.
With the model number in the version table, the version string can be
mapped to the corresponding model number. This allows to implement some
model specific behaviour already before being able to read the model
number.
In most cases, there is a simple one to one relationship between the
version string and the model number, but there are also a few
exceptions:
* For the Sherwood Wisdom 2 and 3, and the Beuchat Mundial 2 and 3,
each variant has a different model number, but the first part of the
version string is identical. The difference is in the firmware
version part. Handling this correctly requires two entries in the
table.
* For the Oceanic OC1 there are 3 different model numbers, and only 2
different version strings. That means there is no correct mapping
possible.
Some iX3M models support a dual mode Buhlmann and VPM decompression
algorithm. Currently libdivecomputer is only capable of reporting one of
those two algorithms, but that's still better than returning an error.
The garmin FIT file parser verified that a string entry fit in the field
size, but it turns out that the check is wrong: a FIT file string field
is not necessarily NUL-terminated at all, and it's ok to have a string
that fills the entire field.
We never actually then use the string length we just checked, so with
the checks being bogus, all of this code just goes away. But let's
update the debug printout to follow these rules.
This makes parsing the example FIT file that Cédric sent us work just
fine (at least superficially, in that I don't see anything obviously
wrong with the result: I don't actually know what Cédric's dive was
supposed to look like to verify).
Reported-by: Cédric BAREYT <bareytcedric@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Also improved the display of setpoint information - switch mode is shown, and auto switch depth is only shown in auto mode.
All of this has been tested.
Signed-off-by: Michael Keller <github@ike.ch>
When no dives are present, the maximum value for the progress events is
set to zero, which triggers an assert. Fixed by letting the progress
events reach 100% instead.
In the latest G2 firmware v2.0, the size of the BLE packets increased to
101 bytes (with a one byte header and 100 bytes of actual payload). This
caused the download to fail, because the internal buffer was suddenly
too small for those larger packets.
These larger packets are most likely due to an update in the BLE stack
of the dive computer. Originally, the maximum BLE packet size was just
20 bytes (excluding the 4 byte L2CAP header and 3 bytes GATT header),
but BLE 4.2 increased the maximum packet size to 244 bytes (or 251 bytes
with the headers).
The USB HID code path keeps using the same fixed size packets as before.
The first byte of the BLE packets does no longer contain the size of the
payload. Since BLE supports variable sized packets, we can simply ignore
this byte and obtain the payload size from the BLE packet size.
This is adding support for parsing the setpoint information in logfiles downloaded from Garmin Descent devices.
The Garmin devices do not have support for ppO2 sensor input, so they only work in 'fixed setpoint' mode for CCR dives, and dive data records do not contain actual ppO2 values.
The ppO2 values are retrofitted to the dive data based on 'setpoint change' events reported by the device. With this change CCR dives downloaded from a Garmin device are correctly classified as CCR dive, and the calculated ceiling / tissue loading graphs are accurate and match the deco stops reported by the device.
Before this change, CCR dives were classified as open circuit dives, often resulting in a massively overstated calculated ceiling.
This has been tested for logs with only automated setpoint changes - more test dives are needed to reverse engineer the log file format for manual setpoint changes, as the setpoint fields are not documented in Garmin's documentation for the FIT file format.
Signed-off-by: Michael Keller <github@ike.ch>
The bookmark value is a bitfield indicating the type of bookmark:
1 - Pressed the bookmark button during a dive
2 - Reset the stopwatch
4 - Unknown
8 - Unknown
The hidapi based implementation returns as soon as the first packet is
received, while the libusb based implementation tries to read the
requested number of bytes. That fails with a timeout if the requested
number of bytes is larger than the size of a single packet and no
further packets are received.
Avoid this problem by limiting the size to the maximum packet size.
At the moment, trying to download an old dive for which the profile data
has already been overwritten with newer data fails. This used to work
fine, but around hwOS firmware v3.10, the behaviour described in commit
76187c550a806fe422920eb8795fa687244513f1 changed.
When downloading the compact/full headers, the firmware always sends the
headers without inspecting their content. Next, libdivecomputer uses the
length field in these headers to determine how many bytes to expect when
downloading the dive. However, when downloading the entire dive, the
hwOS firmware now checks whether the profile data of the dive is still
available. If that's no longer the case, the firmware sends a modified
dive header (with the begin/end pointer fields reset to zero, and the
length field reduced to 8 bytes), along with an empty dive profile.
Since libdivecomputer expects to receive the full profile as indicated
in the original header, the download fails with a timeout.
To workaround this problem, download the dive data in two steps. First,
download the 256 byte header and check whether it has been modified. If
that's the case, reduce the length to that of the 5 byte empty profile.
The header check is also updated to exclude the modified fields. For the
progress events, just pretend the full profile has been downloaded.
Not only the two byte end-of-profile marker 0xFDFD is a valid empty dive
profile, but also a profile with the length field present and set to 8
bytes. In that case the actual length will be just 5 bytes.
When downloading the compact headers (which is the default for recent
hwOS firmware), it's not possible to compare the entire dive header, but
we can at least the check the fields that are available.
Also return an error if the verification fails.
The Aqualung i770R appears to have 6M instead of 4M (high) memory.
Confirmed by trying to read past the 6M limit, which fails with a NAK
response. This amount also matches with the capacity stated in the
manual (6553 hours of profile data at a 60 second sample rate).
It looks like the Scubapro G2 firmware update to v2.0 ended up
increasing the BLE packet size, which broke our downloader.
The logic is shared with the USB HID code, and the way USB HID works is
that the packet is fixed at 64 bytes, and the first byte contains the
actual payload size. So you could have up to 63 bytes of actual data
per packet, and that used to be the limit for the BLE side too.
However, now that the BLE side has bigger packets, using a 64-byte
packet buffer broke horribly, and caused the new 101-byte BLE packets
(one byte of odd data, and 100 bytes of actual payload) to be read as a
64-byte packet followed by a 37-byte one, and that just didn't work at
all.
At the same time, we cannot just increase the receive packet size,
because that makes src/usbhid.c very unhappy at least for the USE_LIBUSB
case, because using a bigger buffer for "libusb_interrupt_transfer()"
will then wait for more than one packet to arrive. Which obviously
doesn't happen when you only get a small reply, and so it all goes
south.
Fixing src/usbhid.c to only ever ask for 64 bytes at a time is probably
the right thing to do, but this instead just makes the Uwatec downloader
look at what protocol it uses instead. So if it's USB HID, we use a
64-bit buffer, and for BLE we use a maximum buffer size that then gets
filled in with whatever the actual packet size was.
Reported-by: <jmejul13@gmail.com>
Link: https://groups.google.com/d/msgid/subsurface-divelog/5d653bbd-5cad-4522-bb46-9e0319e465bbn%40googlegroups.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The memcpy and related functions expects a valid pointer, even if the
size is zero. Most libc implementations will handle a NULL pointer just
fine, but that's not guaranteed.
Simply skip the call when there is nothing to copy.