The Atomic Aquatics Cobalt backend uses 8K data packets. Since a hexdump
of such a data packet needs at least twice the size of the binary data,
the internal log buffer should be increased to 16K bytes.
Due to the integer promotion rules of the C language, the unsigned char
values are promoted to a signed integer (and not an unsigned integer)
before being shifted. But the result of a left shift on a signed type is
undefined if the resulting value can't be represented in the signed
type.
GCC's Undefined Behavior Sanitizer (ubsan), enabled with the option
-fsanitize=undefined, detects this type of problem at runtime with the
following warning: "left shift of X by Y places cannot be represented in
type 'int'".
Fixed with an explicit cast to unsigned integer.
It appears that the Aqualung i770R looks almost the same as the Pro Plus
X, but has an additional pO2 field for each gas by the O2 field, which
impacts the offset calculations.
This fixes the dive truncation that happened with long dives due to the
removal of extra padding (commit a2100843b9cf: "Remove extra padding
from the end of the profile"). It turns out the rest of the profile was
in bits 13-15 (with bit 12 being something else).
The packetization format for the BLE communication used to be that the
first byte of the BLE GATT payload was the size of the payload (1-19
bytes).
That seems to no longer be true as of fw version 1.4. It is still the
size of the payload for the simple small reply packets, but for the long
data stream it ends up being an odd sequence of 13 different values that
are almost - but not quite - 19 apart.
Whatever. Modify our strict "length byte must make sense" rule to be
more of a guidline than a hard rule. This makes the download succeed
again.
Very weird.
Reported-by: Adric Norris <landstander668@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Unfortunately there are several devices with an invalid ringbuffer begin
pointer. In such cases, the strict validation of the pointer causes the
download to fail, without being able to download any dives at all.
Since the begin pointer is only needed to detect the start of the oldest
dive, we can fall back to downloading the entire profile ringbuffer.
Usually we can still detect the start of the oldest dive in some other
(indirect) way. For example when reaching past the end of the
ringbuffer, or the presence of invalid pointers in the linked list
structure. The result is that, we'll be able to download at least some
dives before hitting some other error.
The RTS signal needs to be low before it is raised, and not just set.
This ensures that the PIC inside the Pelagic PC interface is reset and
the initialization sequence always starts cleanly, regardless of the
previous state of the signal.
Reported-By: Bill Perry <bperrybap@opensource.billsworld.billandterrie.com>
Even after removing the pages padded with 0xFF bytes, there are still
some invalid sample pages present at the end of the profile. But it
turns out the number of valid profile pages is stored in the logbook
entry.
The only caveat is that the number of pages appears to be stored as a 12
bit number, which limits the total profile size to only 64Kb. We don't
known what happens for larger dives.
The libusb and hidapi pkg-config files already add the subdirectory to
the header search path with:
-I/usr/include/libusb-1.0
-I/usr/include/hidapi
Therefore, using the subdirectory in the include statement is wrong. In
practice, this usualy works fine by accident, because the base directory
(/usr/include) is typically listed in the default search path of the
compiler. But that's not always true. For example when cross-compiling
or when using the PKG_CONFIG_LIBDIR environment variable.
The Smart Air uses almost the same data format as the Quad Air. Only the
4 bytes containing the dive mode and number of samples moved from the
beginning of the header to the end. This is a change adopted from the
regular Smart.
For older OSTC dives, using logbook format version 0x20, the average
depth is not available in the dive header. It's only available since
version 0x21, which increased the header size from 47 to 57 bytes.
The Oceanic Pro Plus X is quite different from the previous models. The
profile data is now stored in a dedicated memory area, and hence there
are a few important differences:
Reading data from the new profile memory area is done with a new F6
command. This new command is very similar to the existing B8 command,
but accesses a completely different memory area. In order to integrate
those two memory areas as transparantly as possible into the existing
infrastructure, a virtual memory space is introduced. The lower part of
the virtual memory is mapped onto the main memory area, while the upper
part is mapped onto the new profile memory area.
The page size of the new profile memory area also increased from 16 to
256 bytes. If the profile size is not an exact multiple of 256 bytes,
the dive computer pads the profile data with 0xFF bytes.
The other changes are the usual Oceanic device specific changes.
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.
In the error handling code, the dc_buffer_free() function can be called
with an unitialized "buffer" variable as parameter. Fixed by adding an
extra label.
Reported-By: Linus Torvalds <torvalds@linux-foundation.org>
On Windows, the WSAStartup() function needs to be called, to initialize
the socket library, before using any of the other WSA socket functions.
This includes the functions used for the bluetooth device discovery.
The Mac OS X timer implementation returned timestamps with nanoseconds
as unit instead of microseconds.
Reported-by: Rick Balsano <rick.balsano@gmail.com>
The Scubapro LogTrak application doesn't send the handshake commands for
BLE communication. Also the Aladin Sport Matrix, which supports only
BLE, responds with a 0x01 byte instead of the expected 0x01 byte and
that causes the handshaking to fail. Thus simply omit the handshaking
for BLE communication.
Reported-by: Berthold Stöger <berthold.stoeger@tuwien.ac.at>
The Uwatec Smart, Meridian and G2 backends are almost identical, except
for the low-level packet sending and receiving code. With the new I/O
layer, those three backends can easily be unified in a single backend.
The Meridian and G2 are completely removed, only the family types are
kept for backwards compatibility.
The Aladin Tec (and Tec 2G) sample descriptor table supports up to two
event bytes, but there is only a single event descriptor. This missing
descriptor causes a fatal error during parsing. Add a dummy descriptor
to avoid the error.
Instead of reading data packets, the code is actually sending some
random data to the dive computer! A small typo with bad consequences!
This is a critical bug because it not only causes the download to fail,
but also appears to change random settings on the dive computer. I
suspect that the garbage data that gets send to the dive computer
happens to contain some valid write settings commands.
For most I/O stream implementations the serial communication specific
functions are meaningless. Implementing them as no-ops allows the dive
computer backends the call the I/O stream functions unconditionally.
However, implementing the no-op with a dummy function returning
DC_STATUS_SUCCESS, does not only add some (small) overhead at runtime,
but also requires many such functions. This is inconvenient and the same
result can easily be obtained by using a NULL pointer instead.
The consequence is that the logic is reversed now. To obtain the
previous behaviour of returning the DC_STATUS_UNSUPPORTED error code
again, you'll need to implement a dummy function. But that's fine
because it's the less common case.
I/O functions with output parameters, should always initialize those
output parameters, even when an error is returned. This prevents the
(accidental) use of uninitialized variables, whenever the caller forgets
to check the return code.
As a nice side effect, the use of a local variable guarantees that the
underlying I/O implementation will always receive a valid pointer.
When two or more identical (or very similar) dive computers are
connected, the USB VID/PID can be ambiguous. That's because the VID/PID
identifies the type of the USB device, and not the individual device.
But each USB HID device descriptor returned by the device discovery
represents a single connected device, and thus guarantees to open the
correct USB device.
To obtain the same behaviour as before, an application can simply open
the first discovered device.