diff options
-rw-r--r-- | api/direct_bt/DBTAdapter.hpp | 16 | ||||
-rw-r--r-- | api/direct_bt/DBTManager.hpp | 9 | ||||
-rw-r--r-- | api/direct_bt/MgmtTypes.hpp | 82 | ||||
-rw-r--r-- | src/direct_bt/DBTAdapter.cpp | 13 | ||||
-rw-r--r-- | src/direct_bt/DBTManager.cpp | 21 |
5 files changed, 138 insertions, 3 deletions
diff --git a/api/direct_bt/DBTAdapter.hpp b/api/direct_bt/DBTAdapter.hpp index 88e146e8..7cff8f62 100644 --- a/api/direct_bt/DBTAdapter.hpp +++ b/api/direct_bt/DBTAdapter.hpp @@ -264,8 +264,20 @@ namespace direct_bt { */ bool closeHCI(); - /** Add the given device to the adapter's autoconnect whitelist. */ - bool addDeviceToWhitelist(const EUI48 &address, const BDAddressType address_type, const HCIWhitelistConnectType ctype); + /** + * Add the given device to the adapter's autoconnect whitelist. + * <p> + * The given connection parameter will be uploaded to the kernel for the given device first. + * </p> + * <p> + * Method will reject duplicate devices, in which case it should be removed first. + * </p> + */ + bool addDeviceToWhitelist(const EUI48 &address, const BDAddressType address_type, + const HCIWhitelistConnectType ctype, + const uint16_t min_interval=0x000F, const uint16_t max_interval=0x000F, + const uint16_t latency=0x0000, const uint16_t timeout=0x0C80); + /** Remove the given device from the adapter's autoconnect whitelist. */ bool removeDeviceFromWhitelist(const EUI48 &address, const BDAddressType address_type); diff --git a/api/direct_bt/DBTManager.hpp b/api/direct_bt/DBTManager.hpp index 77503998..a0a8bae3 100644 --- a/api/direct_bt/DBTManager.hpp +++ b/api/direct_bt/DBTManager.hpp @@ -243,6 +243,13 @@ namespace direct_bt { bool stopDiscovery(const int dev_id, const ScanType type); /** + * Uploads given connection parameter for given device to the kernel. + */ + bool uploadConnParam(const int dev_id, const EUI48 &address, const BDAddressType address_type, + const uint16_t min_interval=0x000F, const uint16_t max_interval=0x000F, + const uint16_t latency=0x0000, const uint16_t timeout=0x0C80); + + /** * Returns true, if the adapter's device is already whitelisted. */ bool isDeviceWhitelisted(const int dev_id, const EUI48 &address); @@ -257,8 +264,10 @@ namespace direct_bt { * </p> */ bool addDeviceToWhitelist(const int dev_id, const EUI48 &address, const BDAddressType address_type, const HCIWhitelistConnectType ctype); + /** Remove the given device from the adapter's autoconnect whitelist. */ bool removeDeviceFromWhitelist(const int dev_id, const EUI48 &address, const BDAddressType address_type); + /** Remove all previously added devices from the autoconnect whitelist. Returns number of removed devices. */ int removeAllDevicesFromWhitelist(); diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp index eec477e4..6e0b4cb1 100644 --- a/api/direct_bt/MgmtTypes.hpp +++ b/api/direct_bt/MgmtTypes.hpp @@ -418,6 +418,88 @@ namespace direct_bt { const std::string getShortName() const { return pdu.get_string(MGMT_HEADER_SIZE + MgmtConstU16::MAX_NAME_LENGTH); } }; + struct MgmtConnParam { + EUI48 address; + uint8_t address_type; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t timeout; + } __packed; + + /** + * uint16_t param_count 2 + * MgmtConnParam param[] 15 = 1x + * + * MgmtConnParam { + * mgmt_addr_info { EUI48, uint8_t type }, 7 + * uint16_t min_interval; 2 + * uint16_t max_interval; 2 + * uint16_t latency; 2 + * uint16_t timeout; 2 + * } + * uint8_t name[MGMT_MAX_NAME_LENGTH]; + * uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH]; + */ + class MgmtLoadConnParamCmd : public MgmtCommand + { + protected: + std::string valueString() const override { + const int paramCount = getParamCount(); + std::string ps = "count "+std::to_string(paramCount)+": "; + for(int i=0; i<paramCount; i++) { + if( 0 < i ) { + ps.append(", "); + } + ps.append( "[address "+getAddress(i).toString()+", addressType "+getBDAddressTypeString(getAddressType(i))+ + ", interval["+std::to_string(getMinInterval(i))+".."+std::to_string(getMaxInterval(i)) + +"], latency "+std::to_string(getLatency(i))+", timeout "+std::to_string(getTimeout(i))+"]"); + } + return "param[size "+std::to_string(getParamSize())+", data["+ps+"]], tsz "+std::to_string(getTotalSize()); + } + + public: + MgmtLoadConnParamCmd(const uint16_t dev_id, const MgmtConnParam & connParam) + : MgmtCommand(MgmtOpcode::LOAD_CONN_PARAM, dev_id, 2 + 15) + { + int offset = MGMT_HEADER_SIZE; + pdu.put_uint16(offset, 1); offset+= 2; + + pdu.put_eui48(offset, connParam.address); offset+=6; + pdu.put_uint8(offset, connParam.address_type); offset+=1; + pdu.put_uint16(offset, connParam.min_interval); offset+=2; + pdu.put_uint16(offset, connParam.max_interval); offset+=2; + pdu.put_uint16(offset, connParam.latency); offset+=2; + pdu.put_uint16(offset, connParam.timeout); offset+=2; + } + + MgmtLoadConnParamCmd(const uint16_t dev_id, std::vector<std::shared_ptr<MgmtConnParam>> connParams) + : MgmtCommand(MgmtOpcode::LOAD_CONN_PARAM, dev_id, 2 + connParams.size() * 15) + { + int offset = MGMT_HEADER_SIZE; + pdu.put_uint16(offset, connParams.size()); offset+= 2; + + for(auto it = connParams.begin(); it != connParams.end(); ++it) { + std::shared_ptr<MgmtConnParam> connParam = *it; + + pdu.put_eui48(offset, connParam->address); offset+=6; + pdu.put_uint8(offset, connParam->address_type); offset+=1; + pdu.put_uint16(offset, connParam->min_interval); offset+=2; + pdu.put_uint16(offset, connParam->max_interval); offset+=2; + pdu.put_uint16(offset, connParam->latency); offset+=2; + pdu.put_uint16(offset, connParam->timeout); offset+=2; + } + } + uint16_t getParamCount() const { return pdu.get_uint16(MGMT_HEADER_SIZE); } + + const EUI48 getAddress(int idx) const { return EUI48(pdu.get_ptr(MGMT_HEADER_SIZE + 2 + 15*idx)); } // mgmt_addr_info + BDAddressType getAddressType(int idx) const { return static_cast<BDAddressType>(pdu.get_uint8(MGMT_HEADER_SIZE + 2 + 15*idx + 6)); } // mgmt_addr_info + uint16_t getMinInterval(int idx) const { return pdu.get_uint16(MGMT_HEADER_SIZE + 2 + 15*idx + 6 + 1); } + uint16_t getMaxInterval(int idx) const { return pdu.get_uint16(MGMT_HEADER_SIZE + 2 + 15*idx + 6 + 1 + 2); } + uint16_t getLatency(int idx) const { return pdu.get_uint16(MGMT_HEADER_SIZE + 2 + 15*idx + 6 + 1 + 2 + 2); } + uint16_t getTimeout(int idx) const { return pdu.get_uint16(MGMT_HEADER_SIZE + 2 + 15*idx + 6 + 1 + 2 + 2 + 2); } + }; + /** * uint16_t opcode, * uint16_t dev-id, diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp index 70b10994..a96417a4 100644 --- a/src/direct_bt/DBTAdapter.cpp +++ b/src/direct_bt/DBTAdapter.cpp @@ -218,7 +218,18 @@ bool DBTAdapter::closeHCI() return true; } -bool DBTAdapter::addDeviceToWhitelist(const EUI48 &address, const BDAddressType address_type, const HCIWhitelistConnectType ctype) { +bool DBTAdapter::addDeviceToWhitelist(const EUI48 &address, const BDAddressType address_type, const HCIWhitelistConnectType ctype, + const uint16_t min_interval, const uint16_t max_interval, + const uint16_t latency, const uint16_t timeout) { + if( mgmt.isDeviceWhitelisted(dev_id, address) ) { + ERR_PRINT("DBTAdapter::addDeviceToWhitelist: device already listed: dev_id %d, address %s", dev_id, address.toString().c_str()); + return false; + } + + if( !mgmt.uploadConnParam(dev_id, address, address_type, min_interval, max_interval, latency, timeout) ) { + ERR_PRINT("DBTAdapter::addDeviceToWhitelist: uploadConnParam(dev_id %d, address %s, interval[%u..%u], latency %u, timeout %u): Failed", + dev_id, address.toString().c_str(), min_interval, max_interval, latency, timeout); + } return mgmt.addDeviceToWhitelist(dev_id, address, address_type, ctype); } diff --git a/src/direct_bt/DBTManager.cpp b/src/direct_bt/DBTManager.cpp index 7a840791..f7c20c3e 100644 --- a/src/direct_bt/DBTManager.cpp +++ b/src/direct_bt/DBTManager.cpp @@ -506,6 +506,27 @@ bool DBTManager::stopDiscovery(const int dev_id, const ScanType type) { } } +bool DBTManager::uploadConnParam(const int dev_id, const EUI48 &address, const BDAddressType address_type, + const uint16_t min_interval, const uint16_t max_interval, + const uint16_t latency, const uint16_t timeout) { + MgmtConnParam connParam{ address, address_type, min_interval, max_interval, latency, timeout }; + MgmtLoadConnParamCmd req(dev_id, connParam); + DBG_PRINT("DBTManager::uploadConnParam: %s", req.toString().c_str()); + std::shared_ptr<MgmtEvent> res = sendWithReply(req); + if( nullptr == res ) { + DBG_PRINT("DBTManager::uploadConnParam res: NULL"); + } else { + DBG_PRINT("DBTManager::uploadConnParam res: %s", res->toString().c_str()); + if( res->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) { + const MgmtEvtCmdComplete &res1 = *static_cast<const MgmtEvtCmdComplete *>(res.get()); + if( MgmtStatus::SUCCESS == res1.getStatus() ) { + return true; + } + } + } + return false; +} + bool DBTManager::isDeviceWhitelisted(const int dev_id, const EUI48 &address) { for(auto it = whitelist.begin(); it != whitelist.end(); ) { std::shared_ptr<WhitelistElem> wle = *it; |