| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
| |
found device via return value
While we keep the device instance temporarily alive within discoveredDevices until next removeDiscoveredDevices() eg at startDiscover(),
we only keep it within persistent sharedDevices list if at least one deviceFound implementation returns true.
This allows user to minimize the sharedDevices footprint when rejecting the device
w/o being required to call device.remove().
|
|
|
|
| |
darray)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(performance and CoW correctness)
Merging jaulib's darray and cow_darray into direct_bt.
As explained in jaulib, motivation behing darray + cow_darray
is to allow fine grained controll over the CoW's storage
to have certain guarantess on its operation.
Iterator and push_back() enhancments are a few of these.
Fixes performed while replacing:
- DBTDevice getGATTServices(): Take the copy as it will be returned.
- GATTHandler removeAllAssociatedCharacteristicListener(): Try to delete all matching!
Don't stop loop after found and erased first, continue.
Also return number of erased elements, not just true.
- DBTManager ctor: Don't work on CoW snapshot, work on CoW
- Simplified many loops / iterations
|
|
|
|
| |
compatible API)
|
|
|
|
| |
implementation w/o RTTI
|
|
|
|
| |
for 2nd argument; Remove operator<(..)
|
|
|
|
|
|
|
|
|
| |
allocations to one
smart_ptr change series, commit #5
This series started with commit cafd8d1f3689135eae36854a9cca4def690045fd,
see for details.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
as const reference instead of std::shared_ptr to GATTCharacteristicListener
No extra (shared POctets) copy is needed nor desired here.
+++
smart_ptr change series, commit #4
This series started with commit cafd8d1f3689135eae36854a9cca4def690045fd,
see for details.
+++
Contemplated whether to even drop the 'AttPDUMsg::getSpecialized(rbuffer.get_ptr(), static_cast<jau::nsize_t>(len))'
for these callbacks, as a copy is not needed.
However, the ATTPDUMsg constructor validate data consistency, which would need to be replaced (-> more work).
Hence keep this portion as is, may revisit for very tight resources on certain embedded devices.
Note: The GATTCharacteristicListener for Native -> Java also perform one copy into a new byte array.
This can't be avoided w/o some NIO rework.
However, let's have all these thoughts noted here .. just in case.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
instead of shared_ptr; Callbacks use 'const <T> &' now.
smart_ptr change series, commit #2
This series started with commit cafd8d1f3689135eae36854a9cca4def690045fd,
see for details.
Refined MgmtMsg clone template and added same to HCIPacket and SMPPDUMsg.
Notable: To have this clone template to work, the default copy-constructor
should not be deleted. Hence removing the const qualifier from timestamp
and manual default/deleted directives.
+++
At this point, all high frequent objects (ATT, HCI w/ SMP, Mgmt events)
use std::unique_ptr and therefor reduce a certain overhead.
Further, this constraint also removes a potential 'build in' leaks,
in case a callback method keeps the shared_ptr instance.
Now, callbacks only received the const reference and if so desired,
need to create a copy themselves.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
shared_ptr; MgmtEvent Callbacks use 'const MgmtEvent&' now.
smart_ptr change series, commit #2
This series started with commit cafd8d1f3689135eae36854a9cca4def690045fd,
see for details.
Due to using unique_ptr<MgmtEvent>, we cannot pass them to the user (loss of ownership via std::move).
Hence it must be enough to pass a reference to the direct constant type.
In case a user needs to cache the event for later, a copy must be created,
see 'template<class T> MgmtMsg::clone(const T& source) noexcept' for this purpose.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
std::shared_ptr for more efficancy; Use std::make_unique where possible
smart_ptr change series, commit #1
For high frequent objects, it is desired to reduce resources and overhead as much as possible.
unique_ptr has zero overhead, while shared_ptr own a little storage for the reference counter.
Using unique_ptr forces us to move the instance from the receiving reading thread to the ringbuffer
and moving it out later. Hence the changes in jau::ringbuffer earlier.
Using std::make_unique is not really required, as unique_ptr has no resource overhead,
hence 'unique_ptr( new Something() )' is only one allocation.
However, this smart_ptr change series will review all smart pointer use cases
and in case a shared_ptr is required like DBTDevice of GATTCharacteristic elements of GATTServices etc,
we shall use std::make_shared to fold two allocations into one.
Note: 'shared_ptr( new Something() )' implies two allocations.
Current implementation state allows these optimizations,
as the use cases for these data types are well understood.
Earlier it was not feasible to undertake constraining efforts,
as it was not clear whether other actors like to share a resource, like a uuid_t for example.
|
|
|
|
| |
See commit bc9d1c0d2942ce24019b432198f2d4c0d00aee19
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
EUI48: add hash-code, fast compare, include static const ANY_*DEVICE)
- added Hash specialization in namespace std for hash-map (C++)
BDAddressAndType: Added, to be utilizes as actual unique device address having EUI48 + BDAddressType
- fully self sufficient w/ comparison, hash and matching methods
- added Hash specialization in namespace std for hash-map (C++)
Goal for BDAddressAndType is to replace separate EUI48 + BDAddressType,
providing BluetoothDevice / DBTDevice with a unique single key entry.
This will allow us to properly use a hash-map (new for our C++ code)
Further we emphasize on the unique key contract, which requires the BDAddressAndType,
as EUI48 is not enough.
|
|
|
|
|
|
|
| |
- Added SMPSignatureResolvingKeyInfo (native + Java) key retrieval
- Rename SMPKeyDist -> SMPKeyType: For general use, e.g. new query 'SMPKeyType getAvailableSMPKeys(const bool responder)'
- Added SMPKeyType.java
- Added DBTDevice::getAvailableSMPKeys(const bool responder): Allowing user to act upon specific keys when available (native + java)
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
if SMPKeyDist::ENC_KEY not done yet
MgmtEvent::Opcode::NEW_LONG_TERM_KEY shall become handy when using Secure Connections (SC),
as the generated / derived LTKs will not be transported via SMP.
Also:
- DBTDevice::clearSMPStates(): Clear keys
- Extract checkPairingKeyDistributionComplete(..) for hciSMPMsgCallback() and updatePairingState()
|
| |
|
| |
|
|
|
|
|
|
|
| |
mask, determining key role; ...
DBTDevice::setLongTermKeyInfo() writes given key to pairing_data.ltk_resp or pairing_data.ltk_init
to reflect proper state.
|
|
|
|
|
|
|
|
|
|
|
|
| |
[get/set]LongTermKeyInfo(..), tested with DBTScanner10.java
Java + Native test are now on par, may share the LTK binary file in example.
On loading a pre-existing key when device found and before connecting,
BlueZ/Kernel will try the uploaded key and no pairing procedure is being performed.
This tested with explicit unpair before uploading the LTK,
to ensure the pre-existing keys have been deleted.
|
| |
|
|
|
|
| |
boolean; Add Java implementation for SMPLongTermKeyInfo
|
|
|
|
| |
TODO: Use it everywhere possible)
|
| |
|
|
|
|
| |
identity during pairing
|
|
|
|
| |
Use SMPLongTermKeyInfo; Add IRK and CSRK state.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
platform agnostic setting (auth + sc)
New Mgmt*KeyType:
- MgmtLinkKeyType for MgmtLinkKeyInfo
- MgmtLTKType (incl deduction from boolean use_auth and use_sc) for MgmtLongTermKeyInfo
- MgmtCSRKType for MgmtSignatureResolvingKeyInfo
New/Updated Mgmt*KeyInfo:
- MgmtLinkKeyInfo for MgmtLoadLinkKeyCmd, MgmtEvtNewLinkKey
- MgmtLongTermKeyInfo for MgmtLoadLongTermKeyCmd (added to DBTManager and tested), MgmtEvtNewLongTermKey
- MgmtIdentityResolvingKeyInfo for MgmtLoadIdentityResolvingKeyCmd, MgmtEvtNewIdentityResolvingKey
- MgmtSignatureResolvingKeyInfo for MgmtEvtNewSignatureResolvingKey
New Event Types:
- MgmtEvtNewSignatureResolvingKey
|
|
|
|
| |
API doc
|
|
|
|
| |
processing (next step)
|
|
|
|
|
|
|
|
| |
stream w/o endian conversion, ...
MgmtLongTermKey: Also add note about master field (confusion, IMHO inverted logic from mgmt),
as well as using more natural field names and apply same data representation as SMP types
aligned w/ btmon's SMP types (not btmon's MGMT types).
|
|
|
|
|
|
| |
byte stream w/o endian conversion, ...
hence implement all put/get method of its implementations using non-endian conversion 1:1 read/write operations.
|
|
|
|
| |
into the buffer w/o TROctets
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
using mutex + condition-wait; Lock-free DBTDevice::setConn*Security*(..) ..
DBTAdapter::[un]lockConnect[Any](..): New single device connect-command impl using mutex + condition-wait;
- previous atomic use was too complicated
- only provide lockConnect(.., SMPIOCapability) and unlockConnect[Any](),
the former gets called at connect with cached SMPIOCapability user value
and the latter gets called ASAP after successful connection and L2CAP config
or at failure / power-off.
- to debug locking, set direct_bt.debug.adapter.lock environment variable,
e.g. setenv("direct_bt.debug", "true,adapter.lock", 1 /* overwrite */);
Lock-free DBTDevice::setConn*Security*(..) ..
- check constrains (already connected etc)
- cache SMPIOCapability for lockConnect() @ connect*() command
- cache BTSecurityLevel for L2CAP config when connected
Provide [DBT|Bluetooth]Device::setConnSecurityBest(..) for convenience.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We need to lock all Connect Commands starting with
[1] - connectLE or connectBREDR, or
[2] - setConn*Security* for SMPIOCapability (FIXME)
The release ASAP on
- success after connect from within DBTDevice::processL2CAPSetup(..)
- disconnect or connect-failure or power-off
TODO: Above [2] locking at setConn* shall be remove by
cashing the attribute and locking at [1] connect* command.
This shall give a more natural API and expected behavior.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
and UNPAIR_DEVICE: DBTManager <-> DBTDevice
PAIR_DEVICE's COMMAND_COMPLETE reply -> Synthetic pending event PAIR_DEVICE_COMPLETE (MgmtEvtPairDeviceComplete)
- Testing disclosed that Mgmt's pairDevice(..) is not suitable nor stable
- within our workflow: SCAN - FOUND - *CONNECT or PAIR* ..
- Can't call adapter.stopDiscovery() after FOUND, otherwise pairDevice() fails
- Not able to set all scan params (even though connection params can be frontloaded)
- Not producing proper PRE_PAIRED behavior (ALREADY_PAIRED doesn't allow us to GATT process)
The above despite the very usable way of setting SMPIOCapability per connection
w/o our hacky blocked per adapter setting (one connect command at one time).
However, having it supported for testing, allowed us to compare with our workflow
and just using connect.
|
|
|
|
| |
within latter (general HCIStatusCode use)
|
|
|
|
| |
string representation)
|
|
|
|
| |
and add bit-operator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
HCIEventType::ENCRYPT_CHANGE: mgmtEvHCIEncryptionChangedHCI / DBTDevice::updatePairingState(..):
- BT Core Spec v5.2: Vol 4, Part E HCI: 7.7.8 HCIEventType::ENCRYPT_CHANGE
- Allow HCIEventType::ENCRYPT_CHANGE to toggle state to COMPLETED
if no SMP pairing in process (maybe REQUESTED_BY_RESPONDER at maximum).
This indicates: PairingMode::PRE_PAIRED (new).
DBTDevice::processL2CAPSetup():
- Directly process processDeviceReady(..) if !l2cap_auth,
skipping AUTH_FAILURE having no security.
DBTDevice::processDeviceReady(..):
- sleep 100ms if in PairingMode::PRE_PAIRED mode (magic)
- upair() if connectGATT() fails _and_ in PairingMode::PRE_PAIRED mode
DBTDevice::hciSMPMsgCallback
- Better DBG_PRINT alternative (use multiline)
- Track SMPKeyDist from initiator and responder to identify end of Phase 3 (distribution)
- Complete Phase 3: SMP Key & Value Distribution phase -> COMPLETED
- TODO: Facility to have keys persisting.
|
| |
|
|
|
|
| |
jau::environment::get().debug
|
|
|
|
| |
connected as used for security setup @ connect
|
|
|
|
|
|
| |
overloaded variant and simplified API entries.
setConnSecurityLevel(..) no more sets SMPIOCapability, only advise in API doc to avoid complexity.
|
|
|
|
|
|
|
| |
(however, link to its value fails)
Note: I had no success to have doxygen produce links to 'enum class' values,
i.e. '::BTSecurityLevel::NONE' and all permutations of '::' and '#' did not succeed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
L2CAPComm::open() BT_SECURITY deadlock
Re-enable auth-failure (try w/o security) from hciSMPMsgCallback()
Resolve L2CAPComm::open() BT_SECURITY deadlock
- set sec_level after connect() within L2CAPComm::open()
- see macro SET_BT_SECURITY_POST_CONNECT in L2CAPComm.cpp
- L2CAPComm::setBTSecurityLevel() ignores unchanged BT_SECURITY value.
Otherwise it fails on BTSecurityLevel::NONE, don't ask - don't know, even after BlueZ/Kernel review.
Working w/ DBTScanner10:
- Device w/o security: No special settings in commandline
- Device w/ Secure Connection SMP: Only set passkey in commandline
- Device w/ legacy encryption only (no auth): Set BTSecurityLevel::ENC_ONLY or SMPIOCapabilities::NO_INPUT_NO_OUTPUT or both.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
SMPIOCapability: Like force JUST_WORKS by BTSecurityLevel::ENC_ONLY or SMPIOCapability::NO_INPUT_NO_OUTPUT
To allow non-auth encryption mode, user _must_ set BTSecurityLevel, SMPIOCapability or both appropriately.
Otherwise BlueZ/Kernel will chose authenticated SMP negotiation.
- DBTDevice::setConnSecurityLevel(): Will adjust SMPIOCapability automatically, if not yet set
- DBTDevice::setConnIOCapability() and DBTDevice::setConnSecurity(): Perform plain setting
- DBTDevice::processL2CAPSetup(): Sets BTSecurityLevel appropriately either if no-auth SMPIOCapability::NO_INPUT_NO_OUTPUT is chosen,
or based on LE_Enc feature bit and/or SC capability.
Using new HCI ENCRYPT_CHANGE and ENCRYPT_KEY_REFRESH_COMPLETE, for non-auth BTSecurityLevel::ENC_ONLY
endpoint to set SMPPairingState::PROCESS_COMPLETED + PairingMode::JUST_WORKS.
Note: In the non-auth legacy mode, the SMP (ACL.SMP) is not being used.
....
|
|
|
|
|
|
|
|
| |
still SMPIOCapability::KEYBOARD_ONLY for PairingMode::PASSKEY_ENTRY
Use the following methods to read/write SMPIOCapability per adapter (dev_id):
+ bool setIOCapability(const uint16_t dev_id, const SMPIOCapability io_cap, SMPIOCapability& pre_io_cap) noexcept;
+ SMPIOCapability getIOCapability(const uint16_t dev_id) const noexcept;
|