diff options
author | Sven Gothel <[email protected]> | 2020-11-14 08:20:10 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-11-14 08:20:10 +0100 |
commit | fc602c4dc6676def5e8b1b936bb84e6e5eda6642 (patch) | |
tree | ddbdbca8ed142da46bde4fc59702f01e9459c76d /api | |
parent | e20e6ce54b2de540eda060f2a3f4defec26a1c17 (diff) |
Wire HCIACLData::l2cap_frame/SMPPDUMsg from HCIHandler -> DBTAdapter -> DBTDevice incl deduction of SMPPairingState and PairingMode
- Added: AdapterStatusListener::devicePairingState(...): Notifying user about a changed PairingState
- HCIHandler's HCISMPMsgCallback: Pass HCIACLData::l2cap_frame, allowing final receiver (DBTDevice)
to learn about initiator/responder role.
- DBTAdapter
-- Added Mgmt SMP related callbacks
-- Added SMPMsgCallback from HCIHandler, to be forwarded to DBTDevice for actual SMPPairingState handling,
tracking state and SMPPDUMsg details.
- DBTDevice
-- Add API to set/get pairing passkey and numeric comparison
-- Expose current SMPPairingState
-- DBTDevice hciSMPMsgCallback(..): Track underlying PairingState details, received from HCIHandler -> DBTAdapter -> this,
and deduce PairingMode via getPairingMode(..) using both devices AuthReqs, IOCaps and OOBFlag.
Diffstat (limited to 'api')
-rw-r--r-- | api/direct_bt/DBTAdapter.hpp | 26 | ||||
-rw-r--r-- | api/direct_bt/DBTDevice.hpp | 108 | ||||
-rw-r--r-- | api/direct_bt/HCIHandler.hpp | 2 |
3 files changed, 118 insertions, 18 deletions
diff --git a/api/direct_bt/DBTAdapter.hpp b/api/direct_bt/DBTAdapter.hpp index 35081820..616a1883 100644 --- a/api/direct_bt/DBTAdapter.hpp +++ b/api/direct_bt/DBTAdapter.hpp @@ -129,6 +129,18 @@ namespace direct_bt { virtual void deviceConnected(std::shared_ptr<DBTDevice> device, const uint16_t handle, const uint64_t timestamp) = 0; /** + * An already connected DBTDevice's SMPPairingState has changed. + * <p> + * If currentMode == PairingMode::NONE, the device is not paired, otherwise it is paired using the given PairingMode. + * </p> + * @param device the device which PairingMode has been changed. + * @param state the current SMPPairingState of the connected device, see DBTDevice::getCurrentPairingState() + * @param mode the current PairingMode of the connected device, see DBTDevice::getCurrentPairingMode() + * @param timestamp the time in monotonic milliseconds when this event occurred. See BasicTypes::getCurrentMilliseconds(). + */ + virtual void devicePairingState(std::shared_ptr<DBTDevice> device, const SMPPairingState state, const PairingMode mode, const uint64_t timestamp) = 0; + + /** * DBTDevice got disconnected * @param device the device which has been disconnected with zeroed connection handle. * @param reason the HCIStatusCode reason for disconnection @@ -224,6 +236,7 @@ namespace direct_bt { uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t supervision_timeout); friend HCIStatusCode DBTDevice::connectBREDR(const uint16_t pkt_type, const uint16_t clock_offset, const uint8_t role_switch); + friend void DBTDevice::hciSMPMsgCallback(std::shared_ptr<DBTDevice> sthis, std::shared_ptr<const SMPPDUMsg> msg, const HCIACLData::l2cap_frame& source) noexcept; friend std::vector<std::shared_ptr<GATTService>> DBTDevice::getGATTServices() noexcept; bool addConnectedDevice(const std::shared_ptr<DBTDevice> & device) noexcept; @@ -254,7 +267,18 @@ namespace direct_bt { bool mgmtEvDeviceDiscoveringAny(std::shared_ptr<MgmtEvent> e, const bool hciSourced) noexcept; - bool hciSMPMsgCallback(const EUI48& address, BDAddressType addressType, uint16_t handle, std::shared_ptr<const SMPPDUMsg> msg) noexcept; + bool mgmtEvPinCodeRequestMgmt(std::shared_ptr<MgmtEvent> e) noexcept; + bool mgmtEvUserConfirmRequestMgmt(std::shared_ptr<MgmtEvent> e) noexcept; + bool mgmtEvUserPasskeyRequestMgmt(std::shared_ptr<MgmtEvent> e) noexcept; + bool mgmtEvAuthFailedMgmt(std::shared_ptr<MgmtEvent> e) noexcept; + bool mgmtEvDeviceUnpairedMgmt(std::shared_ptr<MgmtEvent> e) noexcept; + + bool updatePairingStateAndMode(std::shared_ptr<DBTDevice> device, + const SMPPairingState old_pstate, const SMPPairingState new_pstate, + const PairingMode old_pmode, const PairingMode new_pmode, uint64_t timestamp) noexcept; + bool hciSMPMsgCallback(const EUI48& address, BDAddressType addressType, + std::shared_ptr<const SMPPDUMsg> msg, const HCIACLData::l2cap_frame& source) noexcept; + bool sendDevicePairingState(std::shared_ptr<DBTDevice> device, const SMPPairingState state, const PairingMode mode, uint64_t timestamp) noexcept; void startDiscoveryBackground() noexcept; void checkDiscoveryState() noexcept; diff --git a/api/direct_bt/DBTDevice.hpp b/api/direct_bt/DBTDevice.hpp index 790522db..1830fd7d 100644 --- a/api/direct_bt/DBTDevice.hpp +++ b/api/direct_bt/DBTDevice.hpp @@ -77,6 +77,19 @@ namespace direct_bt { std::atomic<bool> isConnected; std::atomic<bool> allowDisconnect; // allowDisconnect = isConnected || 'isConnectIssued' + struct PairingData { + SMPPairingState state; + PairingMode mode; + uint32_t passkey; + SMPAuthReqs authReqs_init, authReqs_resp; + SMPIOCapability ioCap_init, ioCap_resp; + SMPOOBDataFlag oobFlag_init, oobFlag_resp; + uint8_t maxEncsz_init, maxEncsz_resp; + }; + PairingData pairing_data; + std::mutex mtx_pairing; + + DBTDevice(DBTAdapter & adapter, EInfoReport const & r); /** Add advertised service (GAP discovery) */ @@ -94,7 +107,6 @@ namespace direct_bt { void notifyDisconnected() noexcept; void notifyConnected(const uint16_t handle) noexcept; - void notifySMPMsg(std::shared_ptr<const SMPPDUMsg> msg) noexcept; /** * Returns a newly established GATT connection. @@ -107,6 +119,13 @@ namespace direct_bt { */ bool connectGATT() noexcept; + void updatePairingStateAndMode(SMPPairingState state, PairingMode mode) noexcept; + + /** + * Forwarded from HCIHandler -> DBTAdapter -> this DBTDevice + */ + void hciSMPMsgCallback(std::shared_ptr<DBTDevice> sthis, std::shared_ptr<const SMPPDUMsg> msg, const HCIACLData::l2cap_frame& source) noexcept; + /** * Will be performed within disconnect() and notifyDisconnected(). */ @@ -128,6 +147,8 @@ namespace direct_bt { */ void disconnectSMP(int caller) noexcept; + void clearSMPStates() noexcept; + /** * Will be performed after connectLE(..) via notifyConnected(), * issuing connectSMP() and connectGATT() off thread. @@ -377,38 +398,93 @@ namespace direct_bt { HCIStatusCode disconnect(const HCIStatusCode reason=HCIStatusCode::REMOTE_USER_TERMINATED_CONNECTION ) noexcept; /** - * The device is securely paired with PasskeyEntry or JustWorks. + * Method sets the given passkey entry, see PairingMode::PASSKEY_ENTRY. + * <p> + * Call this method if the device shall be securely paired with PairingMode::PASSKEY_ENTRY, + * when notified via AdapterStatusListener::devicePairingState(). * <p> - * The device must be connected before pairing, see connectDefault(). + * If returning HCIStatusCode::SUCCESS, caller shall continue listening to AdapterStatusListener::devicePairingState() + * to wait for either SMPPairingState::PROCESS_COMPLETED or SMPPairingState::FAILED. * </p> + * @param passkey used for PairingMode::PASSKEY_ENTRY method. + * Will be encrypted before sending to counter-party. + * + * @return HCIStatusCode::SUCCESS if the command has been accepted, otherwise HCIStatusCode may disclose reason for rejection. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener::devicePairingState() + * @see setPairingPasskey() + * @see setPairingNumericComparison() + * @see getCurrentPairingMode() + * @see getCurrentPairingState() + */ + HCIStatusCode setPairingPasskey(const uint32_t passkey) noexcept; + + HCIStatusCode setPairingPasskeyNegative() noexcept; + + uint32_t getPairingPasskey() const noexcept; + + /** + * Method sets the numeric comparison result, see PairingMode::NUMERIC_COMPARISON. * <p> - * If passkey is an empty string, JustWorks method is being used, otherwise PasskeyEntry. + * Call this method if the device shall be securely paired with PairingMode::NUMERIC_COMPARISON, + * when notified via AdapterStatusListener::devicePairingState(). + * <p> + * If returning HCIStatusCode::SUCCESS, caller shall continue listening to AdapterStatusListener::devicePairingState() + * to wait for either SMPPairingState::PROCESS_COMPLETED or SMPPairingState::FAILED. * </p> - * @param passkey optional secret used for PasskeyEntry method. - * Will be encrypted before sending to counterparty. - * Can be an empty string, in which case JustWork method is used. + * @param equal used for PairingMode::NUMERIC_COMPARISON method. + * Will be encrypted before sending to counter-party. * * @return HCIStatusCode::SUCCESS if the command has been accepted, otherwise HCIStatusCode may disclose reason for rejection. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener::devicePairingState() + * @see setPairingPasskey() + * @see setPairingNumericComparison() + * @see getCurrentPairingMode() + * @see getCurrentPairingState() */ - HCIStatusCode pair(const std::string & passkey); + HCIStatusCode setPairingNumericComparison(const bool equal) noexcept; /** - * Returns a vector of supported PairingMode by the device. + * Returns the current PairingMode used by the device. + * <p> + * If the device is not paired, the current mode is PairingMode::NONE. + * </p> + * <p> + * If the Pairing Feature Exchange is completed, i.e. SMPPairingState::FEATURE_EXCHANGE_COMPLETED, + * as notified by AdapterStatusListener::devicePairingState(), + * the current mode reflects the currently used PairingMode. + * </p> * <p> - * The device must be connected before querying this status, see connectDefault(). FIXME? + * In case the Pairing Feature Exchange is in progress, the current mode is PairingMode::NEGOTIATING. * </p> - * @return vector of supported PairingMode, empty if pairing is not supported. + * @return current PairingMode. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener::devicePairingState() + * @see setPairingPasskey() + * @see setPairingNumericComparison() + * @see getCurrentPairingMode() + * @see getCurrentPairingState() */ - std::vector<PairingMode> getSupportedPairingModes(); + PairingMode getCurrentPairingMode() const noexcept; /** - * Returns a vector of required PairingMode by the device. + * Returns the current SMPPairingState. * <p> - * The device must be connected before querying this status, see connectDefault(). FIXME? + * If the device is not paired, the current state is SMPPairingState::NONE. * </p> - * @return vector of required PairingMode, empty if pairing is not required. + * @see PairingMode + * @see SMPPairingState + * @see AdapterStatusListener::devicePairingState() + * @see setPairingPasskey() + * @see setPairingNumericComparison() + * @see getCurrentPairingMode() + * @see getCurrentPairingState() */ - std::vector<PairingMode> getRequiredPairingModes(); + SMPPairingState getCurrentPairingState() const noexcept; /** * Disconnects this device via disconnect(..) if getConnected()==true diff --git a/api/direct_bt/HCIHandler.hpp b/api/direct_bt/HCIHandler.hpp index aed5ee08..ed1515e1 100644 --- a/api/direct_bt/HCIHandler.hpp +++ b/api/direct_bt/HCIHandler.hpp @@ -148,7 +148,7 @@ namespace direct_bt { }; typedef jau::FunctionDef<bool, const EUI48& /* address */, BDAddressType /* addressType */, - uint16_t /* connectionHandle */, std::shared_ptr<const SMPPDUMsg>> HCISMPMsgCallback; + std::shared_ptr<const SMPPDUMsg>, const HCIACLData::l2cap_frame& /* source */> HCISMPMsgCallback; typedef jau::cow_vector<HCISMPMsgCallback> HCISMPMsgCallbackList; /** |