The USB I/O backend needs some additional information (e.g. interface
number and in/out endpoints) to setup the USB connection. This info is
currently maintained inside the descriptor filter function and gets
passed to the USB backend by means of the filter parameters.
This approach is not only unnecessary complex, but also makes it very
difficult to expose the filter function in the public api because the
data structures for those parameters are private.
Therefore, this data exchange is replaced with a direct mapping between
the USB VID/PID and the configuration info in the USB backend itself.
Passing the descriptor for which the filter function is being called is
a good practice and will also allow to implement some more specific
filtering in the future.
Returning disabled gas mixes to the application mainly results in lots
of unnecessary information. Therefore, remove all disabled gas mixes,
unless they are actively used. Many other dive computers do not even
include disabled gas mixes in the data.
The removal of the disabled gas mixes requires a two pass approach for
parsing the profile data. The first pass is only used to discover which
gas mixes are actively used during the dive. Next, all disabled and not
actively used gas mixes are removed from the list. Since removing one or
more gas mixes also invalidates the index of the remaining gas mixes,
the profile needs to be parsed again to report the new index in the gas
switch samples.
The original one based index is used as the stable gas mix id, used for
looking up the new gas mix index.
The hwOS models support switching to a disabled gas mix. Therefore, the
disabled state is not always a good indication whether a gas mix is used
or not. Look for gas switches during the parsing step instead to keep
track of the actively used gas mixes.
Looking up the gasmix by oxygen and helium content is only needed for
the manual gas mixes. For gas switches to a fixed gas mix, the index is
stored directly in the data.
According to user feedback the ascent warnings on the Cressi Leonardo
are very sensitive. They come in 3 different levels.
This change turns levels 1 and 2 into info events, leaving only 3 as a
warning.
Fixes https://groups.google.com/g/subsurface-divelog/c/qBXF0wmyjKg/m/5qA0_KABCQAJ
Signed-off-by: Michael Keller <github@ike.ch>
The hexdump only includes the command parameters, but not the main
command byte. Since there are many commands without parameters, that's
not very useful.
For dives in HP CCR mode, the oxygen and diluent tanks are stored at a
fixed index. This information is more reliable than using the tank name,
and also prevents the incorrect labeling of one of the other tanks as an
oxygen or diluent tank.
Firmware v84 introduced support for sidemount diving. Users can now
configure the two sidemount tanks as the source for the GTR (Gas Time
Remaining) estimations. We can take advantage of this feature to detect
the sidemount tanks. This is more reliable than using the tank name.
For open-circuit dives, the oxygen and diluent usage doesn't make any
sense at all. But when an open-circuit diver uses the letter 'D' to
indicate a tank for decompression use, it will get incorrectly labeled
as a diluent tank.
Fixed by restricting the oxygen/diluent usage to CCR dives only.
When importing FIT files, we may not have serial numbers or firmware
versions in the result, so don't report them when they don't exist.
Also, add the product name to the FILE message field list, which can
contain relevant information. Not that we report it right now, but now
we *could* do so.
This concludes the Suunto FIT file export saga. It's not great, but it
looks like it should be usable.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
So FIT files seem to have many many different ways to describe time
offsets. And I'm not talking about the overall Garmin time offset of
631065600, which is the conversion from the "Unix Epoch" (Jan 1, 1970)
to the "Garmin Epoch" (Dec 31, 1989).
No, I'm talking just about "device time" to "local time" to "UTC"
conversions.
The DEVICE_SETTINGS message has two different fields for time offsets:
there's a "UTC offset" (presumably this is the timezone the device is
set to), and a "time offset" which we actually use to transform the
recorded time of the dive into the local time that we report.
But the Suunto FIT export doesn't seem to use either of those, and
instead Nick Clark points outthe Suunto FAQ:
"Timestamp fields are deliberately defined as UTC time so that they may
be conveniently displayed in the local time if so desired.
In some instances it is useful to know the UTC offset when the file
was generated (possibly different from when it is decoded). This can
be accomplished by logging a single message containing both a
local_timestamp and a timestamp field. This will establish the UTC
offset of the file.
Presently these fields are predefined for activity and monitoring
messages"
so to get the actual local time, instead of getting it from the
DEVICE_SETTINGS message, we now have to parse the ACTIVITY message, and
take the difference between the regular timestamp and the
"local_timestamp" field.
The great thing about standards is that there are so many to choose
from.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We don't use them, but they seem to be trying to describe what the
developer fields are used for. We may now parse the developer fields
enough to skip over them gracefully, but it looks like we migth some day
want to _really_ parse them, and while I haven't figured it out (at
all!) yet, this may some day help.
For example, we get things like this:
FIELD_DESCRIPTION_name (STRING): "Depth"
FIELD_DESCRIPTION_unit (STRING): "feet"
FIELD_DESCRIPTION_original_mesg (UINT16): 20
FIELD_DESCRIPTION_data_index (UINT8): 0
FIELD_DESCRIPTION_field_definition (UINT8): 0
FIELD_DESCRIPTION_base_type (UINT8): 136
which doesn't tell me anything at all right now, but looks like maybe it
should some day.
It looks like this is defining a developer field for depth in feet
(duh), and the data format may be the same as a RECORD message (20),
which does indeed normally contain the depth (but in mm as an UINT32,
and it's field number 92, so..)
End result: not useful right now, because I'm much too confused about
it. But the debug printout looks interesting.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Not because we use them, but because it makes it clearer from the debug
output that we know what they are and that they aren't interesting..
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This also gets the passing of string values right, even if we don't
actually use this right now.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This was part of me trying to figure out the compressed formats and the
developer fields, it's just noise now.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The ACTIVITY message contains a "local timestamp" in addition to the
regular timestamp. That gives us the timezone information.
Or rather, it would give us the timezone info if we actually used it.
But now we at least parse it, so that we *could* use it.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We end up using the FIT file name as the "fingerprint" for the dive, and
include it at the beginning of the dive data as such. And because of
how Garmin encoded the FIT files, we ended up having a fixed 24-byte
length for this, which is normally the date encoding:
YYYY-MM-DD-HH-MM-SS.FIT
with the terminating NUL character.
Of course, then Garmin started using a short-form encoding too
(presumably due to FAT filesystem limits), and we have magic code to
sort the dates properly, using the name format
YMDHMMSS.FIT
with the numbers encoded in a shorter format (eg "C4ND0302.fit" is
equivalent to "2022-04-23-13-03-02.fit"). See name_cmp() and
parse_short_name() for details.
Anyway, because we use the (zero-padded) 24 characters of the name as
the fingerprint, we used a fixed-size buffer for the filename that was
limited to that maximum size Garmin creates.
But then you download those things, and have multiple vendors, and
suddenly that 24-character limit on the filename is very annoying.
Instead of fixing this in some clean and generic way, let's just raise
the namelength limit to something bigger, and continue to use the first
24 characters of the name for the fingerprint.
Pretty it isn't, but it makes it slightly easier to import random FIT
files that don't conform exactly to the traditional Garmin format.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Since we can now parse FIT files from other vendors than Garmin (ie the
Suunto FIT file export), let's expose this as a generic "FIT file
import" in the dive computer list.
It's all still very much using the Garmin parser, but uses a model ID
that is zero. The only difference that makes is that it also tells the
parser to treat the result as a dive even if it cannot find the actual
dive markers that Garmin uses, since those won't exist in the limited
FIT file export.
This is still somewhat inconvenient, in that you cannot point to the
file itself, you can just point to the directory that contains FIT
files. And right now we have an artifical length limitation on the
filenames, but I'll fix that next.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This was the _actual_ reason why the Suunto FIT file import fell flat on
its face: it adds records with developer fields in them, and I just had
no idea how to parse them.
It turns out that they aren't all *that* horrible to parse: they are
kind of like a special case of the regular FIT event fields.
And no, this does not really parse them: it only parses the layout, and
using that it can then skip the developer fields without causing the
decoder to go all wonky and lose stream synchronization.
At least it works for the specific case of the Suunto FIT files, and the
code makes some amount of sense. The FIT format may be odd, but at the
same time it's most definitely designed for pretty simplistic devices,
so it's not some kind of crazy XML thing.
This gets us parsing those Suunto FIT files at least partially.
That said, it is all very rough indeed, since you have to lie and claim
you're downloading from a Garmin, and have to set up the whole magic
'Garmin/Activity/' directory structure and limit the file size to the 24
characters that Garmin uses.
So this is by no means the real solution.
Considering that Jef doesn't want the Garmin parser in libdivecomputer
anyway, the proper solution might be to move this all to subsurface, and
make it be a "FIT file import" thing instead. Annoying, but on the
other hand it has also been a bit awkward to have it in libdivecomputer.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This turns out to have been another false turn: mis-parsing the FIT file
caused us to think it had compressed records.
So I spent much too much time trying to figure out how those compressed
records actually work. This is the result.
It looks like the only difference between a compressed record and a
regular one is that the compressed record has a single-byte "this is the
record type and the time offset" field at the start. That basically
avoids the need of then having a full 4-byte absolute time for such a
record.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This is an empty stub for the HRM profile message, which isn't actually
used by anything I know of, but came up as a result of some mis-parsing
of odd FIT files generated by the Suunto mobile app.
Losing synchronization in the FIT file then caused the parser to think
it needed this message type, and not having it then caused an early
abort.
While it's not actually needed once parsing things correctly, since I
looked up the message number and name for this message type, let's just
keep it around. It won't hurt, and maybe it avoids me having to look it
up in the future.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Instead of returning an error on unrecognized input when parsing, just
skip to the end of the buffer. This makes at least partially parsed
data available, which can help figure out what ended up happening.
This was part of my "Suunto also does FIT files now, and does them very
differently from Garmin" series. I think I parse the Suunto files right
now, but next time this happens, I'd rather get partial data than no
data at all.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Return `DC_STATUS_UNSUPPORTED` for inactive gas mixes, while retaining
the configured gas information. This makes it possible to mark inactive
gases as such, or completely hide them, without affecting the gas
indices that are referenced in gas switches.
Signed-off-by: Michael Keller <github@ike.ch>
Pull libdivecomputer updates from Michael Keller:
- Add time synchronisation for the Shearwater Teric
- Fix two OSTC4 buglets
* 'add_shearwater_teric_timesync' of https://github.com/mikeller/libdc:
Add Time Synchronisation for the Shearwater Teric.
* 'add_ostc4_dump_error' of https://github.com/mikeller/libdc:
Fix bugs in OSTC4 support.
In commit 1c8cd096b57a876c4fb0afc5113aac05d75d924e the block size was
changed from 64 to 1024 bytes. For bluetooth classic communication, this
shouldn't matter, but for some reason it does cause the OSTC4 firmware
upgrade to fail. Maybe some buffering problem in the OSTC4 firmware or
bluetooth stack?
Change the block size back to 64 bytes.
For open-circuit dives it makes no sense to also include the configured
diluents. Usually those diluents are only present because the diver uses
the same dive computer for both open and closed circuit dives.
Add time synchronisation for the Shearwater dive computers. All models
support setting the local time. Only the Teric has basic support for
time zones, and can set UTC time with a timezone offset.
Co-authored-by: Michael Keller <github@ike.ch>
When the dive computer receives an RDBI or WDBI command it doesn't
support, it sends a 3 byte NAK packet containing an error code. Detect
these NAK packets and use it to return a more appropriate error.
The RDBI (Read Data by Identifier) responses always have a fixed length.
Using a resizable buffer for the API only makes the memory management
more complex than necessary.
Also add some symbolic constants to improve readability.
Fix two bugs in the support for OSTC4:
- change block size for writes back to 64 bytes to prevent buffer
overflow on the dive computer side;
- added 'unsupported' response for the dump command on OSTC4.
Signed-off-by: Michael Keller <github@ike.ch>
Add time synchronisation support for the Shearwater Teric. Unlike the
other Shearwater dive computers this model has basic support for time
zones, so we need to set the time in UTC and configure the time zone
offset.
Signed-off-by: Michael Keller <github@ike.ch>
Merge upstream version 0.8.0 into our libdc fork.
Since we tracked the development branch, we already had merged all the
main changes, but it's been a couple of months since the last upstream
merge, and there were a few new changes upstream:
- Divesoft Freedom and Liberty support
- A couple of iostream abstraction layers: a new 'packet layer' and a
HDLC layer, moving code from low-level dive computer downloaders to
generic iostream layers.
- misc minor updates
* tag 'v0.8.0': (25 commits)
Release version 0.8.0
Fix the date of the v0.7.0 release
Add a missing filter for the Aqualung i750TC
Reduce the BLE output packet size to 20 bytes again
Integrate the new packet I/O in the backends
Add a generic packet I/O implementation
Fix a typo in the documentation
Add support for the Divesoft Freedom and Liberty
Integrate the HDLC stream in the eonsteel backend
Add a generic HDLC I/O implementation
Remove the local endianess functions
Use the correct function to free resources
Add the udev rules to the distribution tarball
Add a README file to the contrib directory
Include the revision in the Visual Studio and Android builds
Don't generate the Windows version resource
Move the Visual Studio project to the contrib directory
Add a basic Android build system
Disable the getopt argument permutation on Android
Move the sign extension function to a common place
...
Add time synchronisation for Shearwater dive computers.
This synchronises the local time, which is all that is supported by all
Shearwater models except for the Teric.
Time synchronisation including the time zone for the Teric still has to
be added.
Signed-off-by: Michael Keller <github@ike.ch>
Replace the numeric type with a name (fresh or salt) and change the
density value into an xml attribute. The type is the primary
information here, while the density value is optional.
The dc_parser_set_data() function allows to re-use a parser object for
multiple dives. The advantages of this feature are actually very limited
in practice. The reduction in memory consumption is almost negligible,
because the amount of internal state in the parser is typically very
small. But the implementation requires some additional complexity
because each backend needs code to reset its internal state. Therefore,
the function is removed and the data and size needs to be passed
directly to the dc_parser_new() and dc_parser_new2() functions instead.
Because keeping a reference to the data has also caused issues in the
past, especially for applications implemented in a garbage collected
language, the data will now also get copied internally.
Only a few dive computer backends (reefnet, aladin and memomouse)
require the clock parameters for parsing the date/time. Therefore,
those parameters are removed from the constructor function and
applications should set the clock parameters with the
dc_parser_set_clock() function instead.
The backend specific calibration function are deprecated. Applications
should use the new replacement functions introduced in commit
6ab140461a3a85fba3803283070427f3be413c79.