The current BLE read reads just one 20 bype packet. That packet size is set
in ble_serial_ops, so, without being able to test on anything other than
a OSTC3, I assume that this holds for other BLE DCs too. So, I think is
is weird that those interfaces work with the current read() of just one
packet at the time.
As we need a blocking read (at least for the OSTC parser), just read all
data that is available on the input. And when we think we are done, give
the QtEventloop control to see if there is more, and process that incoming
data as well. All this basically implements a blocking read.
CAVEAT 1: This might break the reading from the currently working BLE devices.
CAVEAT 2: With this, I still cannot read the OSTC3 completely. For
developers familiar with the HW transfer protocol: it just stops while
reading the first full dive (header + profile) command 0x66, despite
correctly reading about 5Kb of data before. For some
reason, I do not believe that this is related to this commit.
CAVEAT 3: All above tested on Linux Desktop with bluez stack, and
confirmed NOT to work on Android 7.1.2, build with Qt 5.9.0, And
yes, I know 5.9.1 recommended.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
1) As the OSTC sends data to the BLE central role (the SSRF client) over 2
characteristics, we have to filter the administrative credit data from
the actual dive data that it received. The characteristcStateChanged
function is adapted for this.
2) We have to be sure that the Terminal Client I/O is fully defined during
opening the connecton to the OSTC. From 6d505b24f0c15 we can see
that the last step in setting up the terminal interface is the grant
of credits. This is done by writing to the proper (the only one, with
id = 0x2902) descriptor of the credits RX characteristic. The here
added slot is triggered on the completion of write of credits marking
the final stage of the setup.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
The current "select the correct BLE service to talk to" is flawed.
It assumes that the first found non-standard UUID is the right one
and apparently it is for some DCs. But not for the HW devices.
The HW devices use a "standard" ie. approved by the Bluetooth
SIG, controller, that comes with a UUID that our code currently
considers standard so not to be the right one.
This (simple) commit selects the right service for HW. The UUID
is hard coded, and this is ok, because it is tied to the hardware
used by HW. Futher, it does not change anything for other BLE
devices.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This initalizes the Terminal I/O client as described in paragraph 3 of
http://www.telit.com/fileadmin/user_upload/products/Downloads/sr-rf/BlueMod/TIO_Implementation_Guide_r04.pdf
This is for all Heinrichs Weikamp computers, that use referenced BT/BLE hardware
module from Telit Wireless Solutions (Formerly Stollmann E+V GmbH). The 16 bit
UUID 0xFEFB (or a derived 128 bit UUID starting with 0x0000FEFB is a
clear indication that the OSTC is equipped with this BT/BLE hardware.
Furthermore, most devices equipped with this BT/BLE hardware have BT addresses
starting with 00:80:25:...
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This seems really long, but one user appeared to get a response after
almost 10 seconds. So going with 12 for some margin of error.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This should be much more robust in getting us the correct Bluetooth address
and the correct vendor / product for our selection.
When we pick a paired device, we extract the address right from its name.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This really doesn't help us as we can't associate a vendor/product with
devices we don't recognize, so we can't download from them, anyway.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For DCs that support both BT and LE, allow the user to connect to both
interface layers. Maybe not usefull in the end (as BT is faster
than LE), but as long as BT on Android is WIP is it very useful
to be able to connect to the interface layer we like.
Just add it to the Paired Devices list twice. The normal way, and
the LE: prepend way.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This really needs to be done differently - we need a structured way
to associate a transport mechanism with each of the dive computers
we support.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Right now we have a quirk for Shearwater devices to set the random
address flag, but also to handle the differences at read/write time.
With this, I can finally download from both the Suunto EON Steel and the
Shearwater Perdix AI with the same binary.
It's not *pretty*, but it works.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
I hate changing the IO interfaces this often, but when I converted the
custom serial interface to the more generic custom IO interface, I
intentionally left the legacy serial operations alone, because I didn't
want to change something I didn't care about.
But it turns out that leaving them with the old calling convention
caused extra problems when converting the bluetooth serial code to have
the BLE GATT packet fall-back, which requires mixing two kinds of
operations.
Also, the packet_open() routine was passed a copy of the 'dc_context_t',
which makes it possible to update the 'dc_custom_io_t' field on the fly
at open time. That makes a lot of chaining operations much simpler,
since now you can chain the 'custom_io_t' at open time and then
libdivecomputer will automatically call the new routines instead of the
old ones.
That dc_context_t availability gets rid of all the
if (device && device->ops)
return device->ops->serial_xyz(..);
hackery inside the rfcomm routines - now we can just at open time do a simple
dc_context_set_custom_io(context, &ble_serial_ops);
to switch things over to the BLE version of the serial code instead.
Finally, SSRF_CUSTOM_IO v2 added an opaque "dc_user_device_t" pointer
argument to the custom_io descriptor, which gets filled in as the
custom_io is registered with the download context. Note that unlike
most opaque pointers, this one is opaque to *libdivecomputer*, and the
type is supposed to be supplied by the user.
We define the "dc_user_device_t" as our old "struct device_data_t",
making it "struct user_device_t" instead. That means that the IO
routines now get passed the device info showing what device they are
supposed to download for.
That, in turn, means that now our BLE GATT open code can take the device
type it opens for into account if it wants to. And it will want to,
since the rules for Shearwater are different from the rules for Suunto,
for example.
NOTE! Because of the interface change with libdivecomputer, this will
need a flag-day again where libdivecomputer and subsurface are updated
together. It may not be the last time, either.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We rather use wait in combination with spinning the event loop.
Signed-off-by: Alex Blasche <alexander.blasche@qt.io>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
If a device has more than one service the order of service discovery
determined the selection of the service that we intend to interact
with. This assumption is not accurate and is even platform dependent.
Thinking ahead, it is likely that some devices may require us to keep
track and interact with multiple services at the time.
The new logic still suffers from the fact that there is no way
to select the correct service for interaction. This will require
higher level stack changes.
Signed-off-by: Alex Blasche <alexander.blasche@qt.io>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
toUtf8() creates a temporary char* representation which is assigned to
uuid. As soon the object created by toUtf8() gets destroyed, the uuid
pointer points to releases memory.
The intention is to check that we don't have one of the standard
16bit Bluetooth uuids. That's the purpose of QBluetoothUuid::toUInt16().
Signed-off-by: Alex Blasche <alexander.blasche@qt.io>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This is somewhat hacky, but it allows at least the Shearwater
libdivecomputer backend to continue to treat even the BLE GATT model as
just a serial protocol.
What it does is create a special "emulate serial behavior over the
packetized BLE protocol" helper layer, that qtserialbluetooth falls back
on when rfcomm is not available.
NOTE! This still requires some BLE packet code changes to work with the
odd way that Shearwater sets up their BLE GATT communication. So note
that no further patches are necessary to *libdivecomputer*, but some
updates are needed for the subsurface qt-ble.cpp code.
I have those updates in my tree, and this code is all tested on my
Perdix AI, but those patches are currently too ugly to commit as-is.
I've cleaned up this "fake serial" code sufficiently, that cleanup comes
next.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This seems a bit odd, but it actually has three different reasons for it:
- It's a visual indication of BT LE mode for users
- the rfcomm code only works with legacy BT support, and if we scan a
device that only does LE, we want the custom serial code to instead
automatically fall back on a "emulate serial over LE packets" model.
- we want rfcomm to remain the default for devices that do both legacy
BT _and_ LE, but we want people to have the ability to override the
choice manually. They can now do so by just editing the address
field and adding the "LE:" prefix manually, and it automatically gets
saved for next time.
So while a bit hacky, it's actually a very convenient model that not
only works automatically, but allows the manual override.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is some very early and hacky code to be able to access BLE-enabled
dive computers that use the GATT protocol to send packets back and forth
(which seems to be pretty much all of them: a vendor-specific GATT
service with a write characteristic and a notification characteristic
for reading).
For testing only. But it does successfully let me download dives from
my EON Steel and my Scubapro G2.
NOTE! There are several very hacky pieces in here, including just
"knowing" that the write characteristic is the first one, and the
notification characteristic is second. The code should actually check
the properties rather than have those kinds of hardcoded assumptions.
It also checks "vendor specific" by looking at the UUID string
representation, and knowing that the standard ones start with zero.
Crazily, there doesn't seem to be any normal way to test for this,
although I guess that maybe the uuid.minimumSize() function could be
used.
There are other nasty corners. Don't complain, send me patches.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Instead of being "custom serial", it's a IO model that allows serial or
packet modes, independently of each other (ie you can have a bluetooth
device that does serial over BT rfcomm and packet-based communication
over BLE GATT with the same serial operations that describe both cases).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This way in the en_US locale we no longer get shown the odd "dive(s)"
and instead get correct singular and plural forms.
Most of the patch is just a reindentation as it removes the if clause
that used to do the special case of NOT loading a translation for the
en_US case.
Right now we start with a trivial en_US translation file. My guess is
that this will be overwritten once we do the next round of "new strings,
new translations".
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Currently, only a small number of dive computers can be downloaded from
the mobile app. Only present the supported ones to the user. So, currently
restricted to classic BT. Not sure about FTDI support at this point.
Version 2 of the same commit after review from Dirk. Fundamentally,
support is as follows: Android: BT, BLE, and FTDI. iOS: BLE only. For
all other OSses, this commit has no changes. As the BLE backend is
not yet ready, no support on iOS yet.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Translate all of them, but also remove some redundant or possibly
misleading messages. These are now seen by users, not just developers
trying to debug the code.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The old system of cloud access updates with fake percentages just wasn't
helpful. Even worse, it hid a lot important information from the user.
This should be more useful (but it will require that we localize the
messages sent from the git progress notifications and make them more
'user ready').
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
MAX_TANK_INFO is a new macro in dive.h to define the
maximum number of tank_info_t objects.
TankInfoModel's data() and setData() now check for valid
row indexes before accessing the tank_info[] array directly.
Without this patch TankInfoMode::data() can cause a SIGSEGV.
Reported-by: Pedro Neves <nevesdiver@gmail.com>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This changeset fixes 5 issues specific to importing from Liquivision dive logs:
Issue #1: Buffer overrun causes segmentation fault.
At the end of a dive record, untranslatable data is skipped and the file is
scanned for the start of the next dive. This scan was implemented without
regard to buffer size and so the scan ran over the buffer boundary when trying
to scan for the next record after importing the last record in the file.
Issue #2: Incorrect identification of the primary sensor.
The primary tank pressure transmitter was being identified by using the sensor
ID reported in the first pressure event record encountered. When diving with
multiple transmitters (buddy, student, or group transmitters), this is often
not the case and results in the buddy or other group transmitter's pressure
data being imported instead of the primary's.
Through empirical observation of several multi-sensor logs, I identified a
previously unhandled event code (0x10) as marking a sensor identification
event record. Parsing this record allows the primary and other sensors
to be definitively identified regardless of which one sends the first pressure
event.
Issue #3: Sensor values added to the sample collection regardless of sensor ID.
When processing events, the code previously dropped through to create a sample
for every pressure event record, regardless of which sensor ID that event is
associated with. Pressure events for sensors other than the primary are now
ignored and omitted from the sample collection.
Issue #4: Duplicate samples when pressure event time syncs with sample time.
The sample index (d) was not incremented in this specific case resulting in
a duplicate sample (for the same sample time) being created when processing
the next pressure event record.
Issue #5: Unsigned time difference results in erroneous interpolated samples.
When interpolating/extrapolating depth and temperature values for a between-
samples pressure event, a signed time value is subtracted from an unsigned time
value, resulting in an unsigned term. This term is used as a scaling factor
and should be signed to allow for a negative value. Currently, negative values
are instead treated as large unsigned values which result in erroneous scaled
depth and temperature values.
Signed-off-by: Robert Bodily <robert@bodily.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Major functional change in this commit is the addition of found static BT devices
to the internal administration (on Android), in a way that is equivalent to
mobile-on-desktop. So, in both cases, the list of devices in the app are
as in the list of devices on the host OS (Linux or Android). To minimize code
duplication, the btDeviceDiscovered slot is split in two parts, the part to
act as slot for the Qt BT discovery agent (Linux, so mobile-on-desktop), and
the part only needed for Android.
Remaining to be fixed: the correct handling of the QML UI selection of
vendor/product. The first default dive computer is correctly detected,
all paired devices from the virtual vendow can be selected, but clicking
through vendors results in non logical selections. It is obvious why
this is, but a fix is not straigforward at this point.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This adds a central function to convert a BT name to a vendor/product pair
known to Subsurface. This allows interfacing from a paired BT dive
computer, without actively selecting its type, but by selecting it
from the list of paired BT devices. So, after this, downloading from
multiple (paired) DCs is also possible.
And not the niced piece of code ...
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This seems a very trivial commit, but it is not. It appears that on an Android
build, with defined(Q_OS_ANDROID) the Q_OS_LINUX variable is also defined.
This results in a very tricky discovery process: 1) the JNI stuff pulls the paired
devices from the local BT controller, and 2) The QT discovry agent gets active
BT devices. 1) is a static list, that is, not dependent on actual
visual/discoverable BT devices; it is just cached data from the phone. 2) On
Android, this results in a list of actively visible (paired and not paired)
devices. On desktop, however (with QT/bluez BT stack) the QT discovery agent
just gets the list of paired devices, so more or less equivalent to the situation
described under 1) for Android.
Ok, a long story, but just do not do a discovery on Android at all. Basically,
we need the BT address, device name, and possibly a specific SPP service UUID. This are
fixed and known for HW and Shearwater at this point, so there is no need for a
(lengthy) discovery process, and making sure the the dive computer is discoverable
at the moment the app wants to construct its data to show in the UI. So, the
static list of paired devices is all we need.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
It's possible that the user has more than one dive computer with the
same name paired with their computer / device. So let's just add the
address to the name to make it possible to tell those apart.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Added a list of paired BT devices for the "Paired BT Devices" vendor. The
devices under this vendor represent all BT devces that can be found
from the local BT interface. Some special processing is required, as
the BT provided data is (obviously) missing the specific data needed
to open a BT device using libdc code. This processing is not in
this commit, but will follow. This commit is preparation for that.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
After the recent refactoring of QMLManager to btdiscovery, the
manager.getBtAddress() got superseeded by
downloadThread.data().getDetectedDeviceAddress(). Corrected this
here.
Futher some debug output is modified, so that it report the proper
function names.
This corrects the download from an automatically detected OSTC 3.
Manul selection of the same device from the fake vendor "Paired
BT Devices" does not work, however. Still work to be done in
that area.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For reasons unknown to me, the DCDeviceData instance was freed way too early,
and used afterwards, obviously resulting in a SIGSEGV. This commit creates
the DCDeviceData as a direct child of the QMLManager instance, ensuring
it does not get freed prematurely.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The following call in weight_string():
str = QString("%1").arg(lbs, 0, 'f', lbs >= 40.0 ? 0 : 1);
will make values in lbs larger or equal to 40 to have no fractional
part and be rounded to nearest, while values less than 40 will have one
decimal place.
fixes#412
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The format option "%m" doesn't work for MINGW/Windows and is reported as
an unknown conversation type and this sscanf() call would not work.
The alternative is to malloc() enough space manually - e.g.
strlen(input) + 1.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This shouldn't be part of the UI (qmlmanager), but part of our
overall handling of dive computers and BT devices.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
While it seemed logical to use the advertized service UUID that doesn't
appear to be working - instead using this hard coded UUID seems to do
the trick. I now did a successful download from my Shearwater Petrel.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The Cochran logs the first 10 to 20 minutes (configurable) of
surface interval in case the diver re-submerges.
Signed-off-by: John Van Ostrand <john@vanostrand.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Older models allowed for configuration sample frequency; This patch adds
detection of sample frequency (profile_period) for cochran log file
imports.
Signed-off-by: John Van Ostrand <john@vanostrand.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We remember the offered service uuids as we detect the device and then
try the first one - likely this needs to be fixed / tuned to pick the
right one if multiple uuids are offered.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The linear search to determine that a just downloaded dive was already
downloaded, started from the oldest dive in the logbook. It is, however
more likely that a just downloaded dive is one of the most recently
downloaded. So, just search backwards. Just a trivial performance
improvement.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Searching why the mobile app also downloads pre existing dives, it appears
that in the mobile app, the preexisting attribute is 0, where it should be the
number of dives before the download. This is easily solved by adding the correct
setting on the download thread. This solves the issue of downloading pre existing
dives.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
For this I had to also make the DCDeviceData accessible,
and for that it needed to be a pointer.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Set the descriptor when starting the thread, this removes
code from the desktop code and makes everything in sync always.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Keeping the Desktop and QML versions of Subsurface
using the same codebase will keep the code saner,
this change makes the Desktop version use the
DCDeviceData helper sturct that encapsulates
the device_data_t member for easy access on the
QML. This also helped move a bit of initializations
from the UI to the Core - and that's always good.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
this class encapsulates the device_data_t from libdivecomputer
in a way that permit us to use it on QML.
this will be needed to prepare the data for the download thread.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
fill_computer_list() creates a Qt friendly
structure that contains all of the necessary
information about dive computers and it's
devices, and it's needed both in Qml and Widgets
to allow the user to download their dives.
This patch makes it possible to use the code
in QML without duplication.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is important to not duplicate code for the Qml
view. Now the DownloadFromDiveComputer widget is mostly
free from important code (that has been upgraded to the
core folder), and I can start coding the QML interface.
There are still a few functions on the desktop widget
that will die so I can call them via the QML code later.
I also touched the location of a few globals (please, let's
stop using those) - because it was declared on the
desktop code and being used in the core.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Corrected problem where dive profiles would include post dive
surface interval samples.
Added detection for corrupt dives.
Signed-off-by: John Van Ostrand <john@vanostrand.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This combines the display with EADD since this is the same
value with a different unit. And show it for air dives as
well.
Suggested by Jan Mulder & Anton Lundin
Signed-off-by: Robert C. Helling <helling@atdotde.de>
In the planner, the SAC is prescribed, so there is little
use in plotting it (as the color of the cylinder pressure
line). Rather use the color to show the density of breathing
gas.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This appears to be critical for work of breathing so it might be
worthwhile to compute. So far only in infobox.
For background, see
https://www.youtube.com/watch?v=QBajM3xmOtc
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Update the function to create the dive duration string in a way that
it can be used also in info and stats tab and added some more flexibility.
Changed layout for <1h freedives to "0:05:35" (w/o units) or "5:35min"
(with units and :) or "5min 35sec" (with units with space).
Add a new function to create the surface interval string.
Completely remove old function get_time_string() and get_time_string_s().
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
As a last minute addition, and for peace of mind and soul, add just
another size check, to run before reading values from buffer.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
datatrak_import() is the main function called from parse_file(), but
dt_dive_parser() is where the hard work is done, for both, drop file
seeking/reading and use memory pointers instead.
datatrak_import() now returns 0 on success or 1 on failure and abort
import if parser function fails instead of keeping on trying.
dt_dive_parser() emits a warning if libdc_model is zero (manual dives).
Do not parse profiles if libdc_model is zero, for unknown models we set
a fake 0xEE value coverted to Aladin Air X/Z libdc model number. Func
now takes a pointer to a buffer and moves along the dive, when done
returns a pointer to the actual memory position or NULL if something
went wrong.
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>