summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-11-14 08:20:10 +0100
committerSven Gothel <[email protected]>2020-11-14 08:20:10 +0100
commitfc602c4dc6676def5e8b1b936bb84e6e5eda6642 (patch)
treeddbdbca8ed142da46bde4fc59702f01e9459c76d /api
parente20e6ce54b2de540eda060f2a3f4defec26a1c17 (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.hpp26
-rw-r--r--api/direct_bt/DBTDevice.hpp108
-rw-r--r--api/direct_bt/HCIHandler.hpp2
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;
/**