aboutsummaryrefslogtreecommitdiffstats
path: root/core/qt-ble.cpp
AgeCommit message (Collapse)Author
2021-03-12Use QtBluetooth enums from their namespaceGravatar Andreas Buhr
For increased type safety, some enums have been changed to scoped enums in Qt 6.2, see https://codereview.qt-project.org/c/qt/qtconnectivity/+/337069 https://codereview.qt-project.org/c/qt/qtconnectivity/+/336678 This patch adapts subsurface to this change. Since C++11, enums inject their symbols in both their own and their parent namespace, so this patch can be merged right now. Signed-off-by: Andreas Buhr <andreas.buhr@qt.io>
2020-10-24cleanup: remove dc_user_device_tGravatar Berthold Stoeger
The same structure was defined as "struct dc_user_device_t" and typedefed as "device_data_t". Unify this. Since there are much more of the latter, remove the former. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-17Extend BLE uuid matching to the characteristics, add ignore-listGravatar Linus Torvalds
This extends the uuid matching to the low-level characteristics too, so that we can ignore the McLean Extreme characteristics that aren't interesting. It also renames the uuid matching to be about a "uuid_list" rather than being about the service we're matching, since we're now using it for other uuid's than just services. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-09-17Fix 'uud' typo in BLE uuid matching codeGravatar Linus Torvalds
Silly typo with a missing 'i' in 'uuid' that happened when I wrote this code originally, and that compiled fine thanks to the error being duplicated with cut-and-paste to all relevant places. Fix it now, since I'll extend the uuid matching to the actual characteristics for the McLean Extreme. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-08-22core/BLE: delay characteristics discovery until service discovery completeGravatar Dirk Hohndel
While this code was added as I was trying to work through issues with a BLE stack that turned out to be broken, the failure behavior of that device showed that Qt doesn't like it when we start discovering the details of characteristics while it is still busy discovering services. So instead of handling the services as we find them, let's instead wait until we are done discovering services and then discover the details for all those services. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-08-22core/BLE: provide state and error updates during BLE discoveryGravatar Dirk Hohndel
This simply helps us see some possible errors while trying to talk to a device. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-08-22core/BLE: correct the reference for the Shearwater characteristicGravatar Dirk Hohndel
They use that same UUID on the Peregrine as well. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-05-17BLE: trivial updates to the GATT services listsGravatar Linus Torvalds
Add a couple of known services (Scubapro G2 and Shearwater), and update the names of others that turn out to be used for multiple dive computers. Also add another Broadcom upgrade service UUID. While at it, sort the services numerically to make it easier to see that a UUID already exists, since these service numbers do get used across multiple different devices. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-05-17BLE: add list of known good/bad BLE GATT servicesGravatar Linus Torvalds
We've tried to do this "automagic" service discovery, and it mostly works, but then occasionally it doesn't. Making things worse, I think different platforms end up enumerating services differently, so our "pick the first service that looks like it might be a serial service" ends up working on some platforms, but not necessarily on others. Because "first" might be different. So start a list of known good/bad services - and fall back to the old logic when you can't decide reliably. This fills in juat a few cases that I can easily check myself, and the "details" field for them may be incomplete. For example, I know Nordic Semiconductor has their vendor-specific UUIDs, and they can be found in different devices, so calling them "Nordic UART" and "Nordic Flash" services makes sense. But the "Scubapro i770R" service? It might indeed be specific to the Scubapro i770R. Or it might be a general service UUID that Pelagic uses. Or it might be the service UUID of a particular chip, and found in dive computers from other designs too (and not necessarily in all i770R's either). So this is a preliminary first stab at this, and I'm sure we'll extend the list and possibly improve on the explanations. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-01-27Update to new libdivecomputer versionGravatar Linus Torvalds
Jef has changed the libdivecomputer iostream layer and extended it in two different ways: - iostram's now have a 'poll()' method, which does what the name implies: waits for data to be available with a timeout. - iostreams now have a 'ioctl()' method, which can be used to implement miscellaneous operations. Right now the two ones that you can do are "set latency" (this replaces the old 'set_latency()' method) and "get BLE name" (this replaces our 'get_name()' method that was never part of the upstream libdivecomputer interfaces) Neither of these is all that complicated, and the transition is fairly obvious. HOWEVER. I have absolutely no idea how to do 'poll()' on Windows sockets, and I have no intention of figuring it out. We use a direct socket interface to implement the (non-BLE) RFCOMM bluetooth serial protocol, and I'm not sure why Windows is so special here. I suspect - but cannot test - that we should just switch the Windows RFCOMM implementation over to the use the same QtBluetooth code that we use on other platforms. I assume that the Windows Bluetooth support was originally not sufficiently good for that, but these days we depend on Qt doing BLE for us even on Windows, so presumably FRCOMM works too. That would be a nice cleanup, and would make 'poll()' work on RFCOMM under Windows too. However, since I can't test it, I've not done that, but instead just made the Windows RFCOMM 'poll()' method always return success. That may or may not get the thing limping along. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-08-08Cleanup: move error reporting function declarations to errorhelper.hGravatar Berthold Stoeger
Move the declarations of the "report_error()" and "set_error_cb()" functions and the "verbose" variable to errorhelper.h. Thus, error-reporting translation units don't have to import the big dive.h header file. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-18qt-ble: return DC_STATUS_TIMEOUT rather than DC_STATUS_IO on timeoutGravatar Linus Torvalds
This didn't use to matter, because none of the BLE-using backends did retry on timeout until recently. But Jef started doing packet sending retry for the Mares Icon backend, and now we should make sure to distinguish the "IO failed" from "IO timed out" cases. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-04-12use qDeleteAll()Gravatar Rolf Eike Beer
Signed-off-by: Rolf Eike Beer <eike@sf-mail.de>
2019-04-12get rid of some foreach and Q_FOREACH constructsGravatar Rolf Eike Beer
See https://www.kdab.com/goodbye-q_foreach/ This is reduced to the places where the container is const or can be made const without the need to always introduce an extra variable. Sadly qAsConst (Qt 5.7) and std::as_const (C++17) are not available in all supported setups. Also do some minor cleanups along the way. Signed-off-by: Rolf Eike Beer <eike@sf-mail.de>
2019-01-22BLE debug: make things less verboseGravatar Dirk Hohndel
Unless run with '-v -v -v'. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-10-08qt-ble: add 'get_name()' function to expose the BLE name to libdivecomputerGravatar Linus Torvalds
Some divecomputer backends (ok, right now really only the Aqualung i770R and i300C) want to know the bluetooth name of the dive computer they connect to, because the name contains identifying information like the serial number. This just adds the support for that to our Qt BLE code. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-10-06qt-ble: add support for libdivecomputer 'set_timeout()' functionGravatar Linus Torvalds
Because some BLE operations can be very slow (device and service discovery etc), we have some rather excessive default timeout for BLE (currently set to 12 seconds). But once we actually have started doing IO, that long timeout can be a big performance problem, when the libdivecomputer backend has support for retry and packet loss. For that reason, libdivecomputer has a 'set_timeout()' function that allows the divecomputer backend to say how quickly it expects the dive computer to answer before the backend will start resending packets. Let's just implement that for the actual IO side of BLE too. The default timeout value remains the general BLE timeout, and this only affects the actual IO phase, but it improves things enormously for the case where there is packet loss at that point. For example, on the Aqualung i770R, the timeout for packet loss ends up now being just one second rather than the full 12 seconds of default BLE timeout. Which gets the retry going much faster. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-10-06qt-ble: add support to wait for descriptor write completionGravatar Linus Torvalds
When we enable notifications, we actually want to make sure to wait for that write to have completed before we start communicating with the device, because otherwise we might lose notification events. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-10-06qt-ble: move basic uuid filtering back to service discoveryGravatar Linus Torvalds
In commit 30fb7bf35c9e ("qt-ble: set up infrastructure for better preferred service choice") I moved the service filtering from the addService() callback into the "select_preferred_service()" function that picks the right service for the device. That was nice for debugging, since it meant that we showed the details of _all_ services, but it also meant that we ended up starting service discovery on _all_ services, whether they looked at all interesting or not. And that can make the BLE device discovery process quite a bit slower. The debugging advantage is real, but honestly, service discovery can generally be better done with specialized tools like the Nordic nRF app, so the debugging advantage of just listing all the details of all the services is not really worth the discovery slowdown in general. So move the basic "filter by uuid" back to the service discovery phase, and don't bother starting service detail discovery for the services that we can dismiss immediately just based on the service UUID. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-10-01Bluetooth: use_random_address helper isn't needed on WindowsGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-30Bluetooth: don't use random addresses on WindowsGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-26qt-ble: allow reading of partial packet dataGravatar Linus Torvalds
The existing BLE dive computers treat BLE as the packetized protocol it is, and read whole packets at a time. However, the Mares BlueLink backend treats it as just a basic "serial over BLE" transport, and for historical reasons reads the reply packets in smaller chunks. This allows that kind of IO behavior, where if the divecomputer backend reads just a part of a packet, we'll split the packet, return the part the user asked for, and push back the leftover packet onto the received packet queue. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-09-25qt-ble: add BLE packet debugging codeGravatar Linus Torvalds
This is perhaps overly verbose, but the timing details helped figure out some EON Core download issues, and it's nice to see when things actually happen. It's also good to see when the data actually enters our queues, and when we read and write the packets. That might help debug the issues Fabio is seeing with the Mares Bluelink. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-09-25qt-ble: only connect the signals to the preferred serviceGravatar Linus Torvalds
We used to just find all services and connect the characteristics change signal etc to them all, but we really only care about the actual preferred service that we'll be using. So move the qt ble signal connection to after we've selected the preferred service that we will actually be enabling notifications on and do the writes to. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-09-24qt-ble: re-organize how we pick the GATT characteristics to read and writeGravatar Linus Torvalds
We used to just blindly pick "first" and "last" characteristic from the preferred service, and that was stupid but happened to work for the dive computers we supported. Note that for some of them, "first" and "last" was actually the *same* characteristic, since it could be a single one that supported both. However, this first/last hack definitely doesn't work for the Mares BlueLink BLE dongle, and it's really all pretty wrong anyway. So re-organize the code to actually look at the properties of the characteristics. I don't have a BlueLink to test with, but my EON Core and Shearwater Perdix AI are still happy with this, and the code conceptually makes a lot more sense. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-09-23qt-ble: set up infrastructure for better preferred service choiceGravatar Linus Torvalds
We used to just pick the first non-standard service we found (with a special case for the Heinrichs Weikamp dive computers that have an actual registered standard service). We then waited for that service to finish discovery, and started using it. This changes the logic to wait for _all_ services to finish discovery, and then after that we pick the one we like best. Right now the rule for picking a preferred service is the same one we had before, but the difference is that we now have the full discovery data, so we *could* do something better. Plus this makes our debug messages a lot more legible, when we don't have the mix of overlapping service discovery with the actual IO we do to the preferred service. NOTE! This doesn't much matter for most of the dive computers that we currently support BLE for. They don't tend to have a lot of odd services. But at least both the Mares BlueLink and the Garmin Descent both have multiple services and it's not obvious which one to use, and this will make it not only easier to debug those, it will make it easier to pick the right preferred service descriptor to use. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-09-23qt-ble: use the WAITFOR() macro rather than open-coding wait loopsGravatar Linus Torvalds
This is not only much clearer (and smaller code), but it also lowers the latency for the waiting, since we don't always wait for the full 100ms. Get rid of the now unused "waitfor()" function that just unconditionally waited for 100ms. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-09-06Garmin devices - like Shearwater - want random BLE addressingGravatar Linus Torvalds
We had a special-case for the Shearwater case, let's just make it slightly more generic and add Garmin to the list of vendors that want a random BLE address rather than a static one. The Bluez model of having to state this explicitly - but not giving the information to the user - is completely broken and this is all very annoying, credit goes to Wojciech Więckowski for pointing this out. Of course, right now we don't actually know how to parse the BLE stream from the Garmin Descent, but with this (and some libdivecomputer hackery) I actually get connected and start receiving data. That we then can't parse, but that's hopefully just a libdivecomputer update away. Pointed-out-by: Wojciech Więckowski <xplwowi@gmail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-06-20qt-ble: purge pending read data when writingGravatar Linus Torvalds
This should never happen, since our interface is bassically synchronous, but it could happen with delayed replies that came in just after we decided to re-transmit a command. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-06-20qt-ble: improve responsiveness of waiting for bluetooth dataGravatar Linus Torvalds
Our model of waiting for 100ms before re-checking if we got a packet over BLE resulted in potentially horrendously bad latency for received packets. That isn't just a possible performance issue, it actually seems to cause IO errors with my Suunto EON Core. I'm not entirely sure why, but it might simply be some timing interaction, particularly since the IO errors seemed to primarily happen when the dive computer itself was also busy updating the screen (ie if you pressed buttons on the dive computer to switch to compass mode, for example). So replace the silly hardcoded 100ms "waitFor()" function with a WAITFOR() macro that checks the provided expression every time through the loop, which gets us a much lower latency (we basically check every ten milliseconds). The macro is not beautiful, but it WorksForMe(tm). This makes a huge difference to the reliability of the download for me, and might matter for some other dive computers too. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-05-26core: qt-ble.cpp remove postEvent for all platformsGravatar jan Iversen
the postEvent is only called when downloading from a dc with bluetooth, so in most it does not have an effect on the deleteLater() in the code. there are no reason to do special cleanup while waiting for bluetooth QEvent::DeferredDelete is not supported on iOS. Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-21core: Change Q_UNUSED to no parameter nameGravatar jan Iversen
C++ permits use of parameters without name, which signals unused Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-21iOS: qt-ble.cpp remove unsupported event.Gravatar jan Iversen
QEvent::DeferredDelete is not supported in iOS Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-14Core: introduce new subsurface-string headerGravatar Dirk Hohndel
First small step to shrinking dive.h. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-04-24Convert our custom IO model to new libdivecomputer IO modelGravatar Linus Torvalds
This converts our old custom IO model to the new model that libdivecomputer introduced. This is partly based on Jef's rough patch to make things build, with further work by me. The FTDI code is temporarily disabled here, because it will need to be integrated with the new way of opening devices. The ble_serial code goes away entirely, since now libdivecomputer knows about BLE transport natively, and doesn't need to have any serial wrapper around it. Signed-off-by: Jef Driesen <jef@libdivecomputer.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-04-19Cleanup: Make local function waitFor() of static linkageGravatar Berthold Stoeger
Moreover, remove it from the `extern "C"` block, since extern/static is oxymoronic. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-04-19Coding style: remove superfluous semicolonsGravatar Berthold Stoeger
Remove a semicolon after Q_OBJECT and a few others after the closing braces of while loops. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-04-13BLE debug: show more packagesGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-03-14Cleanup: consistently use qPrintable()Gravatar Berthold Stoeger
Replace constructs of the kind s.toUtf8().data(), s.toUtf8().constData(), s.toLocal8Bit().data(), s.toLocal8Bit.constData() or qUtf8Printable(s) by qPrintable(s). This is concise, consistent and - in principle - more performant than the .data() versions. Sadly, owing to a suboptimal implementation, qPrintable(s) currently is a pessimization compared to s.toUtf8().data(). A fix is scheduled for new Qt versions: https://codereview.qt-project.org/#/c/221331/ Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-02-26Cleanup: Use QString as parameter for [get|save]BtDeviceInfo()Gravatar Berthold Stoeger
Each callsite of saveBtDeviceInfo() has a QString, which is converted to a C-string, passed and immediately converted back. Remove these conversions by taking a reference to QString directly. getBtDeviceInfo() is not as clear. Here, the callsite has a C-string handed down from libdivecomputer. Nevertheless, pass a reference of QString here as well. Firstly, for reasons of symmetry. Secondly, to avoid multiple conversions in the getBtDeviceInfo() functions. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-28Cleanup: Uninitialized scalar fieldGravatar Jan Mulder
CID 208315 Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2017-11-13Better error message on BLE connection timeoutGravatar Berthold Stoeger
On BLE connection timeout a weird error-message was shown, because the controller was still in connecting state and no error string was set. Therefore, handle the timeout case with a special case label. Moreover, remove three unnecessary calls to disconnectFromDevice(), which is called in the destructor of the controller anyway (verified by looking at Qt source). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-02Fix resource leaks in qt-ble.cppGravatar Berthold Stoeger
1) Destroy QLowEnergyService objects in destructor of BLEObject. 2) Let BLE object take ownership of the controller so that the latter can be destroyed in the destructor of the former. This introduces a certain ownership subtlety, which could be solved by allocating the controller object in the BLE object. But let's first do the less intrusive thing. 3) Destroy the BLE object for two error conditions. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-09-20BLE support: simplify write functionGravatar Dirk Hohndel
It seems clearer to bail when list is empty... Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-09-17BLE on non-Apple OSs: switch back to using BT addressGravatar Dirk Hohndel
While this interface is deprecated, too much in our existing code depends on being able to create the QLowEnergyController with just the address. Additionally, createCentral() is new in Qt 5.7 and therefor this broke builds on Linux distros that are still on 5.6. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-09-17BLE: try to pick the correct descriptor to write toGravatar Dirk Hohndel
The ordering on Mac appears to be random, but after looking through the various successful logs of BLE downloads, it seems we always wrote to the ClientCharacteristicConfiguration descriptor. So try to find that one first, and only grab the first descriptor in the list if we didn't find a ClientCharacteristicConfiguration descriptor. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-09-17BLE: create controller from QBtDeviceInfoGravatar Dirk Hohndel
Creating it from an address is a) deprecated and b) impossible on Mac or iOS. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-08-26Another signed/unsigned warningGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-08-01Null check before writing to pointerGravatar Anton Lundin
In the serial api for libdivecomputer is ok to send NULL as the int pointer actual, if you dont't care about how many bytes that where actually read or written. This makes sure we don't crash if the ble backend where ever used with such a backend. Signed-off-by: Anton Lundin <glance@acc.umu.se>
2017-07-11Trivial code cleanupGravatar Jan Mulder
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>