| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
and procedured WIP
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
RANDOM; L2CAPComm uses device->getAddressType()
Map BLERandomAddressType::STATIC_PUBLIC -> HCILEPeerAddressType::RANDOM
This only works for a static random address not changing at all,
i.e. between power-cycles - hence a temporary hack.
We need to use 'resolving list' and/or LE Set Privacy Mode (HCI) for all devices.
+++
L2CAPComm uses device->getAddressType(), i.e. no need for a (wrong) public argument flag.
|
|
|
|
| |
HCILEPeerAddressType/HCILEOwnAddressType String representation + API doc
|
|
|
|
|
| |
# Conflicts:
# api/direct_bt/linux_kernel_types.hpp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
HCIAddressType..., Move EUI48 into direct_bt namespace
Add BLERandomAddressType
Exposed in DBTDevice and BluetoothDevice C++ and Java.
See "BT Core Spec v5.2: Vol 6 LE, Part B Link Layer Specification: 1.3.2 Random device Address"
+++
Distinguish HCIAddressType -> HCILEPeerAddressType + HCILEOwnAddressType
As used for HCIHandler::le_create_conn(..)
See "BT Core Spec v5.2: Vol 4, Part E Host Controller Interface (HCI) Functionality: 7.8.12: LE Create Connection command"
DBTDevice::connectLE(..) translates its own BDAddressType -> HCILEPeerAddressType
using BLERandomAddressType (BDAddressType, address).
Currently only HCILEPeerAddressType::STATIC_PUBLIC is allowed
and passed through.
+++
Move EUI48 into direct_bt namespace
|
|
|
|
|
|
| |
Used 32bit machine: Raspbian 10.4 'buster', armv7l (armhf), g++ 8.3.0, OpenJDK 11.0.7
Note that main development occurs on GNU/Linux Debian 11 'bullseye', amd64, g++ 9.3.0, OpenJDK 11.0.7
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
pp are not owner of their resepctive backreference
Even though the Java GC is capable to resolve circular references
as long they are not specifically being hold by a running thread,
we use WeakReference for a more clean lifecycle description.
This is aligned to the C++ changes of commit dfdfd883f52e8d31c005d0f8ae42bbe6dd60c2b8
Further, also have 'DBTDevice -> DBTAdapter' backreference being weak for completion.
Further, DBTDevice.remove() also removes itself from DBTAdapter's discoveredDevice list.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
owner of their resepctive backreference
GATTHandler, GATTService, pp are not owner of their resepctive backreference,
hence use std::weak_ptr for backreferences in general and validate on usage (nullptr, if destructed).
No DBTDevice has been ever destructed after using GATTHandler and discovering all GATT services.
In contrast to Java, C++ has no magic GC and hence shared_ptr use_count gets only increased
when emplying circular backreferences - none gets destructed.
Current ownership relationship is:
DBTAdapter -> DBTDevice -> GATTHandler -> GATTService ...
each contains a backreference, now using a weak_ptr.
Result is that depending on the use-case, DBTDevice instances are destructed:
- Using device->remove(): Immediately
- No explicit device->remove(): Adapter keeps sharedDevices, destruction occurs at end.
|
|
|
|
|
|
| |
if already discovered
Should max return 1, however, analyzing issue having no more devices being discovered.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Use HCIHandler *connect*/disconnect incl related events (Drop DBTManager in this regard)
> Add CONNECT_FAILED HCI listener mgmtEvConnectFailedHCI
-- Issuing a DISCONNECT event
> DBTAdapter: mgmtEvDeviceConnectedHCI
-- Always pass through, just issue WARNING if not a new_connect (TBD)
> DBTAdapter: mgmtEvDeviceDisconnectedHCI + mgmtEvDeviceConnectedHCI
-- removeConnectedDevice pre event issuing
-- removeDiscoveredDevice post event issuing
> DBTDevice:
-- Add isConnectIssued to differentiate isConnected on event
-- Only use HCIHandler's *connect*/disconnect
-- disconnect(..) no more issues removeConnectedDevice, rely ion correct event issuing/handling,
as performed in time @ mgmtEvDeviceDisconnectedHCI...
-- remove() issues removeConnectedDevice and removeDiscoveredDevice pre releaseSharedInstance
to ensure a clean tracking state. The whole purpose of this command.
+++
Enhance native + java test
After disconnect() wait (poll) until no more connected, before issuing remove(),
this shall ensure proper workflow pre remove() - validation of disconnect command.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
support incl HCI connection handle
We move *connect* and disconnect from DBTManager to HCIHandler,
as we need full control of the connection tracker due to:
- expose HCI connection handle to match actual session for disconnect
- control the disconnect on IOError (no command, purge tracker element and send event)
DBTManager::disconnect:
- no more used
- still aligned the 'send event' on ioerror code path
HCIHandler, DBTManager:
- Own callbacks for verbose mode only added in VERBOSE_ON compilation
|
|
|
|
| |
synchronized
|
|
|
|
| |
This potentially avoid a SIGSEGV in case of an error, i.e. destructed device instance.
|
|
|
|
| |
exception and return an empty list (on error/exception)
|
|
|
|
|
|
|
|
|
| |
sequential processing is ensured
GATTHandler servers one device, however, applications may utilize multithreading
and concurrent command requests may lead to wrong replies.
Similar to DBTManager and HCIHandler, top-level entries shall be synchronized.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
availability via retrieval of GATT info
Issues a ping to the device, validating whether it is still reachable.
This method could be periodically utilized to shorten the underlying OS disconnect period
after turning the device off, which lies within 7-13s.
In case the device is no more reachable, disconnect will be initiated due to the occurring IO error.
+++
Implementation attempts to read the mandatory APPEARANCE CharacteristicValue
of the mandatory GENERIC_ACCESS service.
|
|
|
|
|
|
|
|
|
|
|
| |
processed, allowing deviceFound event after disconnect.
The remaining device within adapter's discoveredDevicesList caused the 'mgmtEvDeviceFoundCB'
to not expose the disconnected device via AdapterStatusListener callbacks.
Only a stop- and startDiscovery would have resolved such 'timing' issue.
Therefor, we shall assume a disconnected device not to be discovered yet
and hence enable it to be found again.
|
|
|
|
| |
and have hciConnHandle atomic for threading integrity.
|
|
|
|
|
|
|
|
| |
hasIOError, allowing atomic compare_exchange_strong w/o mutex
Using an atomic threshold via compare_exchange_strong allows us to avoid using a mutex and ease complexity.
The State had been reduced to a tri-state earlier, hence the atomic<bool> tuple is sufficient.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
'bool disconnectDevice'
disconnectDevice shall not always occure w/ GATTHandler::disconnect, i.e.:
- when issuing DBTDevice::disconnectGATT() as it is already called from DBTDevice::disconnect(..)
- via GATTHandler dtor
This avoid unnecessary recursions, which should fail anyways as first disconnect
shall make subsequent disconnect calls return early.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
return immediately (2/2)
Adjust using HCIHandler changes, see commit 9900ef4b93c191c0ac4fa8f941e06a5a8045257c
- DBTAdapter listens to HCIHandler callbacks: *connected* and *disconnected*
using same callback implementations as for DBTManager.
- DBTDevice::notifyConnect receives the actual connection handler
and will be called for all connected callbacks (DBTManager and HCIHandler)
- DBTDevice adjusted return values for *connect* and *disconnect*,
no more connection handle available immediately.
Further changes:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
return immediately (1/2)
It has been observed that under certain circumstances a command like 'le_create_conn'
will timeout after having received the CMD_STATUS message while waiting for the
final completion reply LE_CONN_COMPLETE.
Such delay may even cause a disconnect in case the application is blocked
until command returns.
Here, under BlueZ Kernel, the HCI implementation issues a disconnect
and adds the device to the white-list for the adapter to complete the pending connection.
This is not desired!
Therefor, the only correct methodology is to utilize asynchronous reply
on delayed commands, i.e. commands with replies other than CMD_STATUS or CMD_COMPLETED.
Here we issue the command request and only wait for the immediate CMD_STATUS reply,
which HCIStatusCode will be returned.
The newly added MgmtEventCallback facility is utilized to forward received pending
(completion) events to added listeners.
This implementation benefits from HCIHandler's already existing reader thread.
Even in case HCIHandler won't receive the (completion) event due to
BlueZ Kernel Mgmt interception and handling,
the application will succeed as it will receive the event via callback
either from DBTManager or HCIHandler.
MgmtEventCallback has been chosen because:
- Enable existing DBTManager callback listener
- Allowing to receive the event either by DBTManager or HCIHandler
- Potential reimplementation of DBTManager using HCIHandler
- MgmtEvent types are easier to digest semantically
- MgmtEvent::Opcode value range is limited and more suitable for an array
Further details:
- HCIHandler translates supported HCIEvent to MgmtEvent.
- MgmtEvtDeviceConnected holds optional hci_conn_handle (manual creation)
- MgmtEvtDeviceConnectFailed holds optional HCIStatusCode (manual creation)
- DBTManager reader: Use mutex and reference instead of MgmtAdapterEventCallbackList copy.
|
|
|
|
| |
HCIEventType and HCIMetaEventType
|
|
|
|
| |
hciAddrType)' translation
|
|
|
|
|
|
|
| |
JavaAnonObj implementation JavaGlobalObj
JavaAnonObj is now a full virtual interface.
JavaGlobalObj gets default spec for copy and move ctor and assignment.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
sendWithReply(..)
Overall experience w/ 'reply confusion', e.g.
- START_DISCOVERY-1 -> CMD_COMPLETE (STOP_DISCOVERY-2)
- STOP_DISCOVERY-2 -> CMD_COMPLETE (START_DISCOVERY-1)
Other command/reply confusion also occured, i.e. CONNECT/DISCOVERY, etc.
As the API and user space will operate multi threaded
and event based, the replies would need to be matched
to their respective commands.
Event though sending out commands is synchronized,
orderly replies received in the ringbuffer
would rely on the device/adapter to act synchronous.
This is not the case!
HCI replies may occur at a later time, i.e. CMD_STATUS being returned immediately
for a pending CMD_COMPLETED.
The BlueZ Manager communication aggregates HCI commands and hence acts similar.
For now we synchronize all sendWithReply(..)
so that all commands and their complete replies must be finished before the next.
To remove this enforced synchonization, we could replace the ringbuffer
with a list to find matching replies for the waiting commands.
In case the synchronization proves to be a performance burden (scaling),
we might chose such approach.
|
| |
|
|
|
|
|
|
|
|
| |
command-reply timeout, smaller ringbuffer w/ 64 entries for sync-commands
Manager utilizes HCI commands, hence the command-complete reply may take its sweet time up to 2-3s.
As we prepare to only use synchron commands/replies, a ringbuffer of size 64 is more than enough.
|
|
|
|
| |
6.7 static holds true
|
|
|
|
| |
startup: Ensure mgmtReaderThread is running
|
| |
|
|
|
|
| |
avoiding race condition on discovery state
|
|
|
|
|
|
|
| |
lastUpdate: getLastUpdateTimestamp()
For performance measurement discovery -> gatt complete,
we need to use the last discovery timestamp, since the device could have been created earlier.
|
|
|
|
|
|
|
|
|
|
| |
code; use atomic<ScanType> avoiding race conditions
C++/Java: Only update the discovering state for false in DISCOVERING listener if keepAlive == false.
C++ like Java pendant, only perform start/stop discovery in appropriate discovery state
C++ expose discovery state 'currentScanType'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
keepAlive default := true
Using startDiscovery(keepAlive=true) and stopDiscovery()
is the recommended workflow for a reliable discovery process.
Without keepAlive=true, we already experienced a too short discovery cycle
where the subsequent manual startDiscovery restart will purge
the already discovered devices via removeDiscoveredDevices().
Hence keepAlive=true is strongly indicated for increased reliability
especially when _not_ using the AdapterStatusListener,
since adapter.getDevices() may simply come too late.
|
|
|
|
| |
system timeouts.
|
|
|
|
| |
GATTHandler::State for L2CAPComm::State
|
|
|
|
|
|
|
|
|
|
|
| |
pass_replies_only_filter=true will setup the socket and meta-event filter for each command/reply negotiation,
reducing received events to the bare minimum.
BlueZ kernel hci-socket will filter the events according to the set hci_ufilter mask
as well as HCIHandler filters the le-meta events using our (now atomic) metaev_filter_mask.
HCIHandler can operate in pass_replies_only_filter=false, i.e. catch all mode,
as it may become desired to reimplement the DBTManager module.
|
|
|
|
| |
avoiding memcpy and explicit template type declaration @ caller
|
|
|
|
| |
MgmtEvtUserPasskeyRequest
|
| |
|
|
|
|
| |
section with reference to used algo
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Misc..
Introduce HCITypes + HCIHandler: Providing C++ basics for full HCI support
============================================================================
- HCITypes defines the HCI command and event data structures,
similar to MgmtTypes and ATTPDUTypes.
For more coding efficiency we use template command and event classes, allowing to reuse
the HCIIoctl struct types being wrapped in the C++ classes
for flow and lifecycle control.
HCITypes further includes all essential 'enum class' command opcodes, event types etc,
ensuring type safety.
- HCIHandler defines the command/event workflow similar to GATTHandler and DBTManager.
One HCIHandler per DBTAdapter is being used, each HCIHandler using its
event reader thread and ringbuffer.
Socket event filtering and manual le-meta filtering ensures reduced workload (DoS safety).
Similar to HCITypes, we use template function to utilize
the template command and event classes, reuising the HCIIoctl struct types...
HCIHandler can be extended for more functionality as well as used to implement
our own DBTManager, i.e. Reducing HCIEvents to MgmtEvents with callback support.
At least this is a viable option now, if so desired (non-linux, etc).
- HCIComm: Contains the core I/O functionality only, dropped all semantic HCI code.
The latter resides in HCIHandler now.
- DBTAdapter now uses HCIHander instead of HCIComm, renamed field to simply 'hci'
Misc..
=======
- reduced all ringbuffer capacity to 128 from 256
- Moved Mgmt*EventCallback from DBTManager to MgmtTypes,
as we might want to reuse the MgmtTypes incl callbacks
for alternative DBTManager implementations.
- Added 'enum class' to underlying number type conversion pattern:
<NumberType> number('enum class type')
Avoiding the many static_cast<NumberType>(..) directives.
- align all Type -> String method names: 'get<Type>String(Type)'
- BasicTypes: Add safe uint32_t bitfield mask helper
|
|
|
|
| |
to 30ms from 2.5ms
|
| |
|
|
|
|
| |
for manually triggering connected (testing)
|