diff options
author | Sven Gothel <[email protected]> | 2020-05-02 03:15:31 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-05-02 03:15:31 +0200 |
commit | 6b7c067e29f8f81b80919c267beca1e05b098216 (patch) | |
tree | ccba74eb42652507d210368d06b3eff1d834d7f2 | |
parent | 3df6239693ae0acdb0a067646fbacb99fcc2e5fe (diff) |
DBTManager::disconnect(..): send explicit MgmtEvtDeviceDisconnected to listener
It has been recognized that our disconnect command will not result in a MgmtEvtDeviceDisconnected
received from the BlueZ Kernel. Hence sending it out ourselves to listening clients.
-rw-r--r-- | api/direct_bt/DBTManager.hpp | 3 | ||||
-rw-r--r-- | api/direct_bt/MgmtTypes.hpp | 29 | ||||
-rw-r--r-- | src/direct_bt/DBTDevice.cpp | 2 | ||||
-rw-r--r-- | src/direct_bt/DBTManager.cpp | 19 |
4 files changed, 49 insertions, 4 deletions
diff --git a/api/direct_bt/DBTManager.hpp b/api/direct_bt/DBTManager.hpp index 27e6a561..812db1b1 100644 --- a/api/direct_bt/DBTManager.hpp +++ b/api/direct_bt/DBTManager.hpp @@ -110,6 +110,7 @@ namespace direct_bt { bool mgmtEvNewConnectionParamCB(std::shared_ptr<MgmtEvent> e); bool mgmtEvDeviceWhitelistAddedCB(std::shared_ptr<MgmtEvent> e); bool mgmtEvDeviceWhilelistRemovedCB(std::shared_ptr<MgmtEvent> e); + void sendMgmtEvent(std::shared_ptr<MgmtEvent> event); public: /** @@ -199,7 +200,7 @@ namespace direct_bt { const uint16_t min_ce_length=0x0001, const uint16_t max_ce_length=0x0001, const uint8_t initiator_filter=0); - bool disconnect(const int dev_id, const EUI48 &peer_bdaddr, const BDAddressType peer_mac_type); + bool disconnect(const int dev_id, const EUI48 &peer_bdaddr, const BDAddressType peer_mac_type, const uint8_t reason=0); /** MgmtEventCallback handling */ diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp index b99e9999..48dd38ae 100644 --- a/api/direct_bt/MgmtTypes.hpp +++ b/api/direct_bt/MgmtTypes.hpp @@ -324,6 +324,11 @@ namespace direct_bt { } }; + /** + * uint16_t opcode, + * uint16_t dev-id, + * uint16_t param_size + */ class MgmtEvent { public: @@ -417,6 +422,22 @@ namespace direct_bt { pdu.check_range(0, MGMT_HEADER_SIZE+getParamSize()); checkOpcode(getOpcode(), CMD_COMPLETE, PHY_CONFIGURATION_CHANGED); } + MgmtEvent(const Opcode opc, const uint16_t dev_id, const uint16_t param_size=0) + : pdu(MGMT_HEADER_SIZE+param_size), ts_creation(getCurrentMilliseconds()) + { + // checkOpcode(opc, READ_VERSION, SET_BLOCKED_KEYS); + + pdu.put_uint16(0, opc); + pdu.put_uint16(2, dev_id); + pdu.put_uint16(4, param_size); + } + MgmtEvent(const Opcode opc, const uint16_t dev_id, const uint16_t param_size, const uint8_t* param) + : MgmtEvent(opc, dev_id, param_size) + { + if( param_size > 0 ) { + memcpy(pdu.get_wptr(MGMT_HEADER_SIZE), param, param_size); + } + } virtual ~MgmtEvent() {} int getTotalSize() const { return pdu.getSize(); } @@ -712,6 +733,14 @@ namespace direct_bt { { checkOpcode(getOpcode(), DEVICE_DISCONNECTED); } + MgmtEvtDeviceDisconnected(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType, uint8_t reason) + : MgmtEvent(DEVICE_DISCONNECTED, dev_id, 6+1+1) + { + pdu.put_eui48(MGMT_HEADER_SIZE, address); + pdu.put_uint8(MGMT_HEADER_SIZE+6, addressType); + pdu.put_uint8(MGMT_HEADER_SIZE+6+1, reason); + } + const EUI48 getAddress() const { return EUI48(pdu.get_ptr(MGMT_HEADER_SIZE)); } // mgmt_addr_info BDAddressType getAddressType() const { return static_cast<BDAddressType>(pdu.get_uint8(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info diff --git a/src/direct_bt/DBTDevice.cpp b/src/direct_bt/DBTDevice.cpp index cb78fbc4..ccc534d6 100644 --- a/src/direct_bt/DBTDevice.cpp +++ b/src/direct_bt/DBTDevice.cpp @@ -244,7 +244,7 @@ void DBTDevice::disconnect(const uint8_t reason) { { // Actually issuing DISCONNECT post HCI DBTManager & mngr = adapter.getManager(); - mngr.disconnect(adapter.dev_id, address, addressType); + mngr.disconnect(adapter.dev_id, address, addressType, reason); } std::shared_ptr<DBTDevice> thisDevice = getSharedInstance(); diff --git a/src/direct_bt/DBTManager.cpp b/src/direct_bt/DBTManager.cpp index cad3100f..5a49ef2d 100644 --- a/src/direct_bt/DBTManager.cpp +++ b/src/direct_bt/DBTManager.cpp @@ -96,6 +96,16 @@ void DBTManager::mgmtReaderThreadImpl() { mgmtReaderRunning = false; } +void DBTManager::sendMgmtEvent(std::shared_ptr<MgmtEvent> event) { + const MgmtEvent::Opcode opc = event->getOpcode(); + MgmtEventCallbackList mgmtEventCallbackList = mgmtEventCallbackLists[opc]; + DBG_PRINT("DBTManager::sendMgmtEvent: Event %s -> %zd callbacks", event->toString().c_str(), mgmtEventCallbackList.size()); + for (auto it = mgmtEventCallbackList.begin(); it != mgmtEventCallbackList.end(); ++it) { + MgmtEventCallback callback = *it; + callback.invoke(event); + } +} + static void mgmthandler_sigaction(int sig, siginfo_t *info, void *ucontext) { INFO_PRINT("DBTManager.sigaction: sig %d, info[code %d, errno %d, signo %d, pid %d, uid %d, fd %d]", sig, info->si_code, info->si_errno, info->si_signo, @@ -486,7 +496,7 @@ uint16_t DBTManager::create_connection(const int dev_id, return 0; } -bool DBTManager::disconnect(const int dev_id, const EUI48 &peer_bdaddr, const BDAddressType peer_mac_type) { +bool DBTManager::disconnect(const int dev_id, const EUI48 &peer_bdaddr, const BDAddressType peer_mac_type, const uint8_t reason) { MgmtDisconnectCmd req(dev_id, peer_bdaddr, peer_mac_type); DBG_PRINT("DBTManager::disconnect: %s", req.toString().c_str()); std::shared_ptr<MgmtEvent> res = send(req); @@ -497,7 +507,12 @@ bool DBTManager::disconnect(const int dev_id, const EUI48 &peer_bdaddr, const BD DBG_PRINT("DBTManager::disconnect res: %s", res->toString().c_str()); if( res->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) { const MgmtEvtCmdComplete &res1 = *static_cast<const MgmtEvtCmdComplete *>(res.get()); - return MgmtStatus::SUCCESS == res1.getStatus(); + if( MgmtStatus::SUCCESS == res1.getStatus() ) { + // explicit disconnected event + MgmtEvtDeviceDisconnected *e = new MgmtEvtDeviceDisconnected(dev_id, peer_bdaddr, peer_mac_type, reason); + sendMgmtEvent(std::shared_ptr<MgmtEvent>(e)); + return true; + } } else { DBG_PRINT("DBTManager::disconnect res: NULL"); return false; |