summaryrefslogtreecommitdiffstats
path: root/api
Commit message (Collapse)AuthorAgeFilesLines
* Support BDADDR_LE_RANDOM (p1.3): HCIHandler: Earmark notable SPEC sections ↵Sven Gothel2020-07-021-0/+27
| | | | and procedured WIP
* Support BDADDR_LE_RANDOM (p1.2): Map BLERandomAddressType::STATIC_PUBLIC -> ↵Sven Gothel2020-07-021-2/+1
| | | | | | | | | | | | | | 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.
* Support BDADDR_LE_RANDOM (p1.2): Add ↵Sven Gothel2020-07-021-4/+14
| | | | HCILEPeerAddressType/HCILEOwnAddressType String representation + API doc
* aarch64: <sys/param.h> defines __u64 _le64 and __be64Xerxes Rånby2020-07-021-0/+10
| | | | | # Conflicts: # api/direct_bt/linux_kernel_types.hpp
* Support BDADDR_LE_RANDOM (p1): Add BLERandomAddressType, distinguish ↵Sven Gothel2020-07-025-71/+141
| | | | | | | | | | | | | | | | | | | | | | | | | | 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
* Minor armv7l g++ 8.3.0 build fixedSven Gothel2020-07-021-2/+2
| | | | | | 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
* Resolve circular references (p2): Java DBTDevice, GATTHandler, GATTService, ↵Sven Gothel2020-06-294-4/+4
| | | | | | | | | | | | | | 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.
* Resolve circular references (p1): C++ GATTHandler, GATTService, pp are not ↵Sven Gothel2020-06-297-14/+51
| | | | | | | | | | | | | | | | | | | | 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.
* DBTAdapter::mgmtEvDeviceFoundMgmt: Show count of device in discoveredDevices ↵Sven Gothel2020-06-281-0/+1
| | | | | | if already discovered Should max return 1, however, analyzing issue having no more devices being discovered.
* Use HCIHandler *connect*/disconnect; Enhance native + java testSven Gothel2020-06-273-19/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* HCIHandler: Complete HCIConnection Tracker for full *connect* and disconnect ↵Sven Gothel2020-06-273-34/+46
| | | | | | | | | | | | | | | | 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
* DBTAdapter: Unify all findDevice*(..) methods, ensure all list access is ↵Sven Gothel2020-06-271-5/+7
| | | | synchronized
* L2CAPComm/GATTHandler: Use prefetched 'deviceString' for verbose outputSven Gothel2020-06-261-4/+2
| | | | This potentially avoid a SIGSEGV in case of an error, i.e. destructed device instance.
* Align DBTDevice's C++ getGATTServices() w/ Java getServices(): Catch ↵Sven Gothel2020-06-261-2/+8
| | | | exception and return an empty list (on error/exception)
* GATTHandler: Add mtx_command for all public accessible functions, ensuring ↵Sven Gothel2020-06-251-0/+1
| | | | | | | | | 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.
* GATTHandler/DBTDevice (incl Java): Add ping[GATT](), testing device ↵Sven Gothel2020-06-252-0/+30
| | | | | | | | | | | | | | | | 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.
* DBTAdapter:: removeDiscoveredDevice(..) after mgmtEvDeviceDisconnectedCB ↵v2.1.6Sven Gothel2020-06-241-0/+1
| | | | | | | | | | | 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.
* DBTDevice: *connect* + disconnect: Lock via mutex *absent of proper atomic* ↵Sven Gothel2020-06-241-1/+2
| | | | and have hciConnHandle atomic for threading integrity.
* L2CAP/GATT: Replace State with dedicated atomic<bool> isConnected and ↵Sven Gothel2020-06-242-18/+18
| | | | | | | | 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.
* *Ringbuffer: Add 'drop(int count)' method, dropping max count oldest elementsSven Gothel2020-06-242-0/+33
|
* GATTHandler::disconnect(..): Expose full parametrized variant only, adding ↵Sven Gothel2020-06-241-5/+9
| | | | | | | | | | | '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.
* L2CAPComm: Always use blocking mode, remove State::ConnectingSven Gothel2020-06-241-6/+4
|
* Remove dead code: 'DBTAdapter::performDeviceConnected(..)'v2.1.5Sven Gothel2020-06-241-1/+0
|
* HCIHandler: Use async event mechanism for delayed replies, commands shall ↵Sven Gothel2020-06-242-19/+39
| | | | | | | | | | | | | | | | | 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:
* HCIHandler: Use async event mechanism for delayed replies, commands shall ↵Sven Gothel2020-06-242-22/+107
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Add MgmEvent::Opcode::INVALID to have a defined invalid value like ↵Sven Gothel2020-06-241-0/+1
| | | | HCIEventType and HCIMetaEventType
* BTAddress: Add 'BDAddressType getBDAddressType(const HCIAddressType ↵Sven Gothel2020-06-241-0/+1
| | | | hciAddrType)' translation
* Direct-BT: API doc and clarify interface JavaAnonObj, JavaUplink and ↵Sven Gothel2020-06-181-1/+13
| | | | | | | JavaAnonObj implementation JavaGlobalObj JavaAnonObj is now a full virtual interface. JavaGlobalObj gets default spec for copy and move ctor and assignment.
* Threading and transmission robustness: DBTManager, HCIHandler: Synchronize ↵Sven Gothel2020-06-102-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* HCIHandler: Remove unused method sendWithReply(..)Sven Gothel2020-06-101-1/+0
|
* Default Timeout, Ringbuffersize: DBTManager, HCIHandler: Same 3s ↵Sven Gothel2020-06-103-6/+9
| | | | | | | | 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.
* Threading robustness: DBTManager: Add singleton-get mutex, ensuring C++11 ↵Sven Gothel2020-06-101-0/+3
| | | | 6.7 static holds true
* Threading robustness: DBTManager, GATTHandler, HCIHandler: Reader thread ↵Sven Gothel2020-06-103-0/+6
| | | | startup: Ensure mgmtReaderThread is running
* DBTManager: Merge private declaration blocksSven Gothel2020-06-101-9/+8
|
* DBTAdapter (Java/C++): Explicit synchronization on start/stop discovery, ↵Sven Gothel2020-06-101-0/+1
| | | | avoiding race condition on discovery state
* DBTDevice (C++/Java): Expose getLastDiscoveryTimestamp() and rename ↵Sven Gothel2020-06-091-6/+22
| | | | | | | lastUpdate: getLastUpdateTimestamp() For performance measurement discovery -> gatt complete, we need to use the last discovery timestamp, since the device could have been created earlier.
* C++: Utilize 'currentScanType' for start/stop discovery same as for Java ↵Sven Gothel2020-06-091-2/+16
| | | | | | | | | | 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'
* [DBT]Adapter (Java/C++) startDiscovery(bool keepAlive) policy change: ↵Sven Gothel2020-06-091-4/+13
| | | | | | | | | | | | | | | 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.
* L2CAPComm::connect: Retry connect on ETIMEDOUT up to 3, working around rare ↵Sven Gothel2020-06-091-0/+5
| | | | system timeouts.
* L2CAPComm/GATTHandler: User 'enum class' constants for type safety; Drop ↵Sven Gothel2020-06-093-28/+15
| | | | GATTHandler::State for L2CAPComm::State
* HCIHandler: Add 'pass_replies_only_filter' mode (in use now)v2.1.3Sven Gothel2020-06-092-6/+9
| | | | | | | | | | | 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.
* HCIHandler/Types: template process*Cmd: Pass pre-allocated template command, ↵Sven Gothel2020-06-092-16/+72
| | | | avoiding memcpy and explicit template type declaration @ caller
* DBTManager/MgmtTypes: Expose MgmtEvtDeviceBlocked, MgmtEvtDeviceUnblocked, ↵Sven Gothel2020-06-082-22/+51
| | | | MgmtEvtUserPasskeyRequest
* DBTDevice: make 'getSharedInstance()' publicSven Gothel2020-06-081-3/+3
|
* BasicTypes: Rename getUTF8String(..) -> decodeUTF8String(..): Adding API doc ↵v2.1.2Sven Gothel2020-06-041-1/+5
| | | | section with reference to used algo
* Rename HCIErrorCode -> HCIStatusCode for clarity and pleasing the eyesSven Gothel2020-06-046-45/+45
|
* Introduce HCITypes + HCIHandler: Providing C++ basics for full HCI support; ↵Sven Gothel2020-06-0412-231/+1108
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* Specify le_create_connection arguments (API doc) and set default le_scan_* ↵Sven Gothel2020-06-012-7/+19
| | | | to 30ms from 2.5ms
* DisconnectedEvent: Show both reasons, hci and mgmtSven Gothel2020-06-011-2/+4
|
* DBTAdapter::performDeviceConnected(..) leaving (currently dead) code path ↵Sven Gothel2020-06-011-1/+1
| | | | for manually triggering connected (testing)