aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/direct_bt/DBTAdapter.hpp16
-rw-r--r--api/direct_bt/DBTManager.hpp9
-rw-r--r--api/direct_bt/MgmtTypes.hpp82
-rw-r--r--src/direct_bt/DBTAdapter.cpp13
-rw-r--r--src/direct_bt/DBTManager.cpp21
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;