| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
[DBT|Bluetooth]Manager, enabling fully event driven workflow w/ adapter add/remove
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
INDEX_REMOVED Mgmt events
C++ DBTManager detects INDEX_ADDED and INDEX_REMOVED Mgmt events
@INDEX_ADDED reception in the event reader, a new processAdapterAdded() thread is spawned
initializing the adapter as usual and maintaining adding its AdapterInfo artifact.
Then all user INDEX_ADDED callbacks are called from this thread,
after the new AdapterInfo entry has been added.
@INDEX_REMOVED here the matching AdapterInfo entry is simply removed
DBTAdapter naturally also listens to INDEX_REMOVED,
simply closing its instance and hence rendering it isValid() = false.
+++
On close(), Java's DBTAdapter will remove itself
from the DBTManager's adapter list.
This removal will happen automatically,
if INDEX_REMOVED is received - see below.
On the Java side, DBTManager listens to:
@INDEX_REMOVED here the matching adapter instance is simply removed
@INDEX_ADDED and @NEW_SETTINGS(POWERED) checks whether the matching adapter instance
exists and creates a new one added to the adapters list if necessary.
@NEW_SETTINGS(POWERED) has been added here as well, since a user could
chose to close the adapter if POWERED off and hence removing itself
from the DBTManager adapter list.
Hence NEW_SETTINGS(POWERED) will add a new adapter instance, if none exists.
+++
Due to this new concurrent use-case of the adapter list,
the list is now a CopyOnWriteArrayList instance supporting lock-free fast reads.
Mutations of the list occur rarely, hopefully ;-).
On the C++, the AdapterInfo is a jau::cow_vector and the callbacks are
store in a jau::cow_vector as well (MgmtAdapterEventCallbackList).
Hence both share the same properties w/ the Java side: Fast lock-free reads.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
[DBT|Bluetooth]Adapter: C++ and Java: Redefine/add state queries:
- isValid(): true if this adapter references are valid and hasn't been DBTAdapter::close() 'ed
- isPowered(): true if DBTAdapter::isValid(), HCIHandler::isOpen() and AdapterSetting::POWERED state is set
- isSuspended(): true if DBTAdapter::isValid(), HCIHandler::isOpen() and AdapterSetting::POWERED state is not set
- dev_id / getDevID(): Added definition, added method + implementation to Java
BluetoothAdapter: Java
- getPowered() -> getPoweredState() - to differentiate with isPowered()
BluetoothManager: Java
- getAdapter(dev_id) added
- setDefaultAdapter(..) implementation removed in DBTManager -> nonsense
- getDefaultAdapter(): DBT: Return 1st isPowered() adapter (redfinition, aligned with C++)
|
|
|
|
| |
environment::startupTimeMilliseconds for startupTimeMillis(), aligning timing.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ScanType for the changedEnabled value; Expose meta ScanType.
The additional information in the callback is essential in a LE + BREDR environment.
User can also see the current meta ScanType.
ScanType is exposed to Java.
Java's BluetoothAdapter also adds 'ScanType getCurrentScanType()', exposing the last sent meta ScanType.
DBTAdapter.java stores the meta ScanType instead of a boolean flag, hence we can react on LE only scanning for example.
DBTAdapter can call all discovery callbacks for all ScanTypes now.
|
|
|
|
| |
avoid 2/2 (tinyb)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
timestamp is uint64_t
- AttPDUMsg
Use size_t where appropriate
- OctetTypes.hpp: TROOctets*
- ATTPDUTypes.hpp: AttPDUMsg*
- HCITypes.hpp: HCIPacket*
- HCIComm.hpp: HCIComm
- L2CAPComm.hpp: L2CAPComm
- MgmtTypes.hpp: MgmtCommand*, MgmtEvent*
- UUID.hpp: uuid_t
- DBTManager, GATTHandler, HCIHandler
- HCIComm.hpp: HCIComm
- BTTypes.hpp
- DBTTypes.hpp
|
|
|
|
| |
settings for all, avoiding confusion.
|
|
|
|
|
|
|
|
| |
that is how it potentially has been deleted!
This fix also gives us the opportunity back to use a simple mutex for mtx_sharedDevices.
Also add dedicated close() for better leak testing.
|
| |
|
| |
|
| |
|
|
|
|
| |
jaucpp, namespace jau
|
|
|
|
| |
i.e. use 1st POWERED adapter
|
|
|
|
| |
in AdapterStatusListener::adapterSettingsChanged(..)
|
|
|
|
| |
atomic-copy in DBTAdapter. Simplify related method[-names]s.
|
|
|
|
|
|
|
| |
procedure incl bring-up back into POWERED functional state
Notable: DBTAdapter::poweredOff() shall not close the HCI connection,
as the unique host HCI channel will survive.
|
|
|
|
|
|
|
| |
AdapterStatusListener::adapterSettingsChanged(..) action ..
POWERED-ON @ AdapterStatusListener::adapterSettingsChanged(..): Only act upon non-initialSetting,
as initial startDiscovery is handled by application code!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
DBTAdapter, [2] use HCIStatusCode for start/stopDiscovery
and well as [2] return boolean for set[Discoverable|Bondable|Powered](..).
AdapterStatusListener needs to pass non-const DBTAdapter to allow actionable modification of adapter state,
e.g. start/stopDiscovery.
HCIStatusCode is desired for start/stopDiscovery, allowing user to read actual HCI status code on failure.
boolean return value for set[Discoverable|Bondable|Powered](..) reflecting general success or failure
on these basic commands.
|
|
|
|
|
|
|
| |
Ability to reset and power-on and off (the latter was already supported)
might help recovering congested or otherwise stuck adapter.
This is experimental work and has to be tested more thoroughly.
|
|
|
|
| |
access with locks
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
notify[Connected|Disconnected]() callbacks or in GATTHandler lifecycle
GATTHandler lifecycle has its own minimal mutex, mtx_gattHandler, no more [ab]using mtx_connect.
To avoid 'lock order' issues and hence potential deadlocks:
- GATTHandler construction happens now via connectGATT() into notifyConnect off-thread for LE devices.
- GATTHandler disconnectGATT() happens at disconnect() upfront above the mtx_connect lock or at notifyDisconnect() the latest.
- notify[Connected|Disconnected]() callbacks don't hold mtx_connect,
as they only set atomic flags and notifyConnected() may issue connectGATT() off-thread (see above)
Have allowDisconnect before isConnected in notify[Connected|Disconnected](), as it is queried before.
Have disconnectGATT() be called last in notifyDisconnected(), as allowDisconnect and isConnected have precedent
and connectGATT() queries both to avoid ctor attempt if not connected or disconnecting.
getGATTService() and pingGATT() now just use getGATTHandler(), implemented merely as 'user methods',
either the GATTHandler was created at notifyConnected() and hence exists or not.
connectGATT(): Add noexcept as GATTHandler ctor is also noexcept; also don't throw an exception.
This renders connectGATT() suitable to be excecuted off-thread.
|
|
|
|
|
|
|
| |
end of processing thread (for main thread exit)
Aligning with commit f03c57b88c9053d730e1f6767f6b305865a54049,
preparing for valgrind testing
|
|
|
|
|
|
|
|
| |
end of processing thread (for main thread exit); ..
Also issue DBTManager::close() to have a proper visibility @ program runtime via valgrind.
Remove the nonsense 3s wait @ test end.
|
|
|
|
| |
public LE'; Add remark re BREDR and LE Secure Connection requirement in comment.
|
|
|
|
|
|
| |
Set all related states, skip all actions.
Also added notion of 'initialSetting' to dbt_scanner10 and DBTScanner10.
|
|
|
|
| |
name aligned with dbt_scanner10.cpp
|
|
|
|
| |
BluetoothManager changes.
|
|
|
|
| |
silence on pairing modes
|
|
|
|
| |
and start discovery in process* function to disconnect right away.
|
|
|
|
| |
and erroneous missing data handle nicely (no crash)
|
|
|
|
|
|
|
| |
on disconnect event
This is possible due to commit a2096bf3baf8fb5fc8ed37ce4bdb1ec1112b6e8d
"LE connection parameters for higher transmission robusteness w/o using a ping-gatt link-loss check"
|
|\ |
|
| |
| |
| |
| |
| |
| |
| | |
List<PairingMode> instead of plain array for direct usability
As user needs to test certain features using contains(PairingMode::XYZ),
returning a list is more straightforward. C++ also returns a vector.
|
|/
|
|
|
|
|
|
|
| |
L2CAP_READER_POLL_TIMEOUT) and new L2CAP_RESTART_COUNT_ON_ERROR for testing
L2CAPHandler's read/write will also issue verbose error-out messages in case the instance is still connected,
i.e. not intentionally pulled by another thread.
This is work in progress.
|
|
|
|
| |
list, oops. Added call to C++/Java example for validation
|
|
|
|
|
|
|
|
|
|
|
| |
PairingModes (C++, Java)
For now, DBTDevice has a NOP implementation, i.e. returning zero length vectors (or arrays in Java)
for supported and required PairingMode.
The pair(String passkey) simply returns HCIStatusCode::INTERNAL_FAILURE;
Intention is to validate the new API entry with our application.
|
|
|
|
| |
clear type names: CharDef and CharVal
|
| |
|
|
|
|
|
|
| |
-dbt_hci, -dbt_gatt', setting their env-vars like ScannerTinyB10.java
Aligning example apps for same experience and invocation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
skipped >= GATTService); GATTHandler owned by DBTDevice, always.
GATTService and childs might need access to their GATTHandler, not just DBTDevice.
This relationship always existed, but was skipped.
Also emphasize that GATTHandler is always owned by DBTDevice, hence has a weak back-reference to the same.
Fixed in ATTPDUTypes C++ Direct-BT API doc overview.
Further impact:
- GATTService has a weak back-reference to GATTHandler instead of DBTDevice,
DBTDevice reference will then be picked up from GATTHandler, the usual.
- GATTHandler::discoverPrimaryServices(..), discoverCompletePrimaryServices(..)
needs to receive GATTHandler's shared_ptr from owner and caller to build the back-reference in GATTService
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
w/ one thread per device
Testing w/ 2 devices in fastest rapid reconnect (using automatic disconnect) on Raspberry-Pi:
(1) Native run-dbt_scanner10.sh -silent_gatt -mac C0:26:DA:01:DA:B1 -mac C0:26:DF:01:E5:CA -disconnect -count 12
(2) Java run-java-scanner10.sh -silent_gatt -mac C0:26:DA:01:DA:B1 -mac C0:26:DF:01:E5:CA -disconnect -count 12
The Java (2) test case disclosed a race condition as follows:
"An application using one thread per device and rapid connect, should either use disconnect() or remove(),
but never issue remove() after disconnect(). Doing so would eventually delete the device being already
in use by another thread due to discovery post disconnect!"
The example code was issuing (1) disconnect and waiting for being diconnected and only then
(2) removing the device. In between the device got discovered already and a new processing thread has started
while the closing previous processing thread is removing the device and hence the underlying DBTDevice.
A user shall either use disconnect() or remove(), period.
|
| |
|
|
|
|
| |
init-list of ctor
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
'connect' lifecycle
Further:
- L2CAPComm
-- disconnect(): Only lock mtw_write if connected and mark noexcept
-- Added '~L2CAPComm() noexcept' for RAII
-- Removed unsued accessors
- GATTHandler
-- Similar treatment as L2CAPComm
- DBTDevice
-- Remove mtx_gatt and its locks, they were not consistent.
Rely on mtx_connect (connectGATT/getGATTServices/disconnect)
and atomic local GATTHandler copy when using.
-- disconnect GATTHandler directly in disconnect, remove explicit method.
-- pingGATT uses local gattHandler copy to avoid parallel disconnect nullptr,
however, it will fail immediately due to disconnection.
|
|
|
|
|
|
| |
detailed GATT info, nor PERF
Testing with multiple devices in parallel, it is useful to be in the most quiet mode - not walking through tons of info dumps.
|
|
|
|
| |
multi device test support like ScannerTinyB10
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
C++ Libs -> none (2x)
Java Jar -> none
Java JNI Libs -> C++ Lib + Java Jar (2x)
C++ Examples -> C++ Libs
Java Examples -> Java Jar
Test -> C++ Lib
+++
scripts/[re]build.sh uses `getconf _NPROCESSORS_ONLN`
for the make -j <number of parallel processes>.
|
|
|
|
|
|
|
|
|
| |
i.e. Debian 10 Buster with GCC 8.3)
GCC 10.1 mostly covers C++20 and is default on Debian 11 Bullseye, we will move there when established.
For now let's use C++17 at least, especially since GCC C++ ABI fixes a few code generation issues
and we intend to further simplify our C++ codebase.
|
|
|
|
| |
The \example tag referring to the example code file must be added to the actual API (header) files.
|