The Mares Horizon is a variant of the Mares Genius, with a few changes
to support SCR dives:
The dive header is slightly modified. There is an extra 8 byte field at
offset 0x18, which causes all later fields to have moved up with the
same amount. This difference is indicated in both the object minor
version (with a change from v0.0 to v0.1), and the logformat.
For the profile data, there is a new SDPT sample type which contains a
bit more information compared to the existing DPRS sample type. This
difference is indicated with a change in the object type (from 0 to 1).
The current implementation assumes a fixed order for the record types (a
DSTR record, a TISS record, zero or more DPRS/SDPT records with an AIRS
record every 4 sample, and finally a DEND record), and either only DPRS
or SDPT records but never a mixture of the two. If these assumptions
turns out to be incorrect, the implementation will need to be changed
significantly. Note that the assumption of the fixed order was already
present for the Genius.
Bluetooth support is currently disabled in the Horizon firmware, but
might be re-enabled in the future.
Since logbook entries with invalid ringbuffer pointers are considered a
fatal error, the download is aborted. The result is that any remaining
entries, located after the invalid entry, can't be downloaded at all.
This can be avoided by skipping the problematic entry instead of
aborting the download.
The Sherwood Sage appears to be very similar to the Aeris A300CS. For
the BLE communication the handshake fails and is disabled.
Reported-By: Nick Shore <support@mac-dive.com>
With just a single table, the version string matching not only becomes
simpler, but adding new layouts also requires no code changes anymore.
For devices that need different layouts depending on the firmware
version (e.g. Oceanic Atom 2.0 and Aeris Manta), the table may contain
multiple entries with the different firmware versions. The only
requirement is that the entry with the highest firmware version must be
listed first.
The patterns used for the version string have the firmware version
masked out because it varies. We can re-use those masks to extract the
firmware version.
The gauge and freedives have a slightly different data format compared
to scuba dives. The main difference is the size of the header and two
new sample types.
The logbook header has 5 bytes extra, which are not present in the dive
header. Those 5 extra bytes contain the dive mode, which is required for
parsing the dive data. Therefore, insert all 5 bytes again and update
the parser.
The remaining 4 bytes appear to be some 32 bit address. They are not
used for anything right now, but are preserved as well in case they are
needed in the future.
The memory buffer already supported appending and prepending data, but
not inserting data anywhere in the buffer. That's exactly what the new
function does. The free space is still maintained at either the start or
the end of the buffer.
The existing check accepts the number of array elements as a valid
index. That's clearly wrong for zero based indexing, and would result in
a buffer overflow.
At some point (possibly around v71 of their firmware), Shearwater implemented
PNF for the Petrel and Petrel 2. Those are of course not air integrated, and
apparently don't support adjustable sample rate, so the log data doesn't include
opening and closing record 5. Instead of failing when those aren't found, we
should simply only access those when they actually exist.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The original Mares Genius support was based on Mares Dive Organizer
2.25, which has a bug in the salinity parsing. The latest version 2.26
has this bug fixed.
Reported-by: Greg McLaughlin <gregm@somemore.com>
The McLean Extreme records a sample every 10 seconds instead of every 20
seconds. This resulted in dive durations that were twice as long as
expected.
Reported-by: David Carron <david_de_carron@hotmail.com>
In one of the Windows system header files, an "interface" macro is
defined as:
#define interface struct
This results in some very strange build errors when also including the
descriptor-private.h header file. That's because the dc_usb_params_t
struct has a member field named "interface":
typedef struct dc_usb_params_t {
unsigned int interface;
unsigned char endpoint_in;
unsigned char endpoint_out;
} dc_usb_params_t;
As a workaround, define the WIN32_LEAN_AND_MEAN macro before including
the windows.h header file. This excludes some less common Windows API
declarations, including the above one.
In commit 57f0ce6d7902117cfc4d0d6b401b516fc93ca488, an extra parameter
was added to the dc_descriptor_filter() function. But I only updated the
libusb code path and forgot to do the same for the hidapi variant.
Commit d1b865d192afc9efde337b5cff8a239366f15565 breaks the OSTC4
firmware upgrade because the OSTC4 expects to receive the service init
command and the service key all at once, before sending any response.
The hwOS firmware still reads the service init command one byte at a
time, and sends the echo immediately after each byte. But in the
meantime, the hwos firmware has also been optimized. The processing time
for an incoming byte is now always faster then the time it takes for the
next byte to physically arrive via the serial line between the USB/BT
chip and the processor. Thus, even without any buffering, sending all
bytes at once should no longer be a problem.
This partially reverts commit d1b865d192afc9efde337b5cff8a239366f15565.
Reported-by: Anton Lundin <glance@acc.umu.se>
Suggested-by: Ralph Lembcke <mail@ralph-lembcke.de>
There is no reason for libusb to ever return a negative number of bytes,
but due to the use of a signed integer, it's technically possible. And
because libdivecomputer returns an unsigned integer, such a negative
number would be reported as a very large size.
Replace the hardcoded libusb based code with the new USB I/O transport.
This enables the use of a custom I/O on platforms where libusb is not
available.
The USB communication is now also implemented as an I/O stream
transport. Unlike most I/O devices, USB communication supports multiple
interfaces and endpoints. This requires some some special care:
In the general case, autodetection isn't really possible without
additional knowledge. Hence the need for the filter parameters to pass
this kind of information.
The implementation assumes two bulk endpoints for the standard
read/write interface. Communication with the control endpoint is
supported through the new DC_IOCTL_USB_CONTROL_{READ,WRITE} ioctl's.
Replace the small helper function to retrieve the function pointer and
then call the function, with another helper function to call the filter
function directly. This way the function pointer doesn't need to be
exposed at all.
When the fingerprint feature isn't used (or with a timestamp of zero),
the response to the SIZE (0xC6) and DATA (0xC4) commands is received
almost instantly:
[0.302704] W: C60000000010270000
[0.366727] R: DCF90F00
[0.367829] W: C40000000010270000
[0.394812] R: E0F90F00
But when the fingerprint feature is used (with a non-zero timestamp),
there is a noticable delay:
[0.341218] W: C64CEB204D10270000
[1.927905] R: FE0B0000
[1.931610] W: C44CEB204D10270000
[5.092081] R: 020C0000
In this particular case, the total amount of dive data was close to 1M
bytes, which pushed the delay over the 3 second timeout, and caused the
download to fail. Increasing the timeout to 5 seconds fixed the problem.
The most likely explanation is that the dive computer needs to scan its
internal logbook to determine which dives and how many bytes to send.
Because that involves reading relative slow flash memory, this can take
up to a few seconds, especially if there are many dives present.
The duration of the delay also depends on the value of the fingerprint
timestamp: the less dives we try to download, the longer the delay! I
suspect that's because the most recent dives are located near the end of
the logbook. Hence, the less dives we request, the more dives the dive
computer needs to skip.
Below are some timings for downloading espectively 792410, 531856 and
270850 bytes from the same dive computer, but with a different
fingerprint value:
[0.216305] W: C6F8D5C84510270000
[0.373511] R: 56170C00
[0.378929] W: C4F8D5C84510270000
[0.661388] R: 5A170C00
[0.236246] W: C620D80F4810270000
[0.559608] R: 8C1D0800
[0.563755] W: C420D80F4810270000
[1.171631] R: 901D0800
[0.246193] W: C654E6434A10270000
[0.826365] R: FE210400
[0.831760] W: C454E6434A10270000
[1.974351] R: 02220400
- Added missing man pages for the new functions.
- Updated the main libdivecomputer man page to reflect the new flow.
- Fixed minor typos in the dc_parser_get_field and
dc_parser_samples_foreach functions.
Instead of assuming that the dive list is presented in a sorted circular
list, sort it properly alphabetically (which also ends up being a
numerical sort for the HEX ascii dive names).
The "search for most recent dive, then splice the list around" case
doesn't work in the general case. It happens to work if you don't
delete any dives, and dives only disappear as they are being overwritten
by new dives when the storage overflows.
But if you delete dives and then create new ones, the dive list will not
be sorted at all, and we should sort it properly when downloading.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
In recent hwos firmware versions, the depth is no longer stored as
pressure (in millibar), but directly as depth (in meters) with the
salinity and gravity factor already applied.
The S_BLOCK_WRITE (0x30) command sends a stream of bytes to the dive
computer. Because the payload has no fixed length and there is no length
field included, the hwOS firmware detects the end of the stream by means
of a 400ms timeout. The main disadvantage of this approach is that a
short hiccup in the communication will be incorrectly detected as the
end of the stream. Hence only a part of the data will get written to
the flash memory, and the remainder of the data will get interpreted as
the next commands.
To avoid this problem, the hwOS firmware v3.09 and later supports a new
S_BLOCK_WRITE2 (0x31) command, which uses a fixed size payload of 256
bytes.
Reported-by: Ralph Lembcke <mail@ralph-lembcke.de>
By reading the firmware version information immediately after entering
download or service mode, we can identify the specific firmware version
and adapt to minor differences in the communication protocol.
The S_BLOCK_WRITE (0x30) command sends a stream of bytes to the dive
computer. Because the payload has no fixed length and there is no length
field included, the hwOS firmware detects the end of the stream by means
of a 400ms timeout. Therefore the ready byte is always delayed by this
400ms timeout.
The same remark applies to the DISPLAY (0x6E) and CUSTOMTEXT (0x63)
commands. But because libdivecomputer always pad the text with zeros and
sends the maximum payload size, we won't hit the timeout.
Reported-by: Ralph Lembcke <mail@ralph-lembcke.de>