summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/direct_bt/DBTManager.hpp4
-rw-r--r--api/direct_bt/MgmtTypes.hpp906
-rw-r--r--api/direct_bt/SMPHandler.hpp2
-rw-r--r--src/direct_bt/DBTAdapter.cpp9
-rw-r--r--src/direct_bt/DBTManager.cpp136
-rw-r--r--src/direct_bt/MgmtTypes.cpp111
-rw-r--r--src/direct_bt/SMPHandler.cpp7
7 files changed, 715 insertions, 460 deletions
diff --git a/api/direct_bt/DBTManager.hpp b/api/direct_bt/DBTManager.hpp
index 73026b9a..3c07f93b 100644
--- a/api/direct_bt/DBTManager.hpp
+++ b/api/direct_bt/DBTManager.hpp
@@ -257,6 +257,7 @@ namespace direct_bt {
void processAdapterAdded(std::shared_ptr<MgmtEvent> e) noexcept;
void processAdapterRemoved(std::shared_ptr<MgmtEvent> e) noexcept;
bool mgmtEvNewSettingsCB(std::shared_ptr<MgmtEvent> e) noexcept;
+ bool mgmtEvControllerErrorCB(std::shared_ptr<MgmtEvent> e) noexcept;
bool mgmtEvClassOfDeviceChangedCB(std::shared_ptr<MgmtEvent> e) noexcept;
bool mgmtEvDeviceDiscoveringCB(std::shared_ptr<MgmtEvent> e) noexcept;
bool mgmtEvDeviceFoundCB(std::shared_ptr<MgmtEvent> e) noexcept;
@@ -376,7 +377,8 @@ namespace direct_bt {
*/
int getDefaultAdapterDevID() const noexcept;
- bool setMode(const uint16_t dev_id, const MgmtOpcode opc, const uint8_t mode) noexcept;
+ bool setMode(const uint16_t dev_id, const MgmtCommand::Opcode opc, const uint8_t mode, AdapterSetting& current_settings) noexcept;
+ MgmtStatus setDiscoverable(const uint16_t dev_id, const uint8_t state, const uint16_t timeout, AdapterSetting& current_settings) noexcept;
/** Start discovery on given adapter dev_id with a ScanType matching the given BTMode. Returns set ScanType. */
ScanType startDiscovery(const uint16_t dev_id, const BTMode btMode) noexcept;
diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp
index b387881c..af38b9ce 100644
--- a/api/direct_bt/MgmtTypes.hpp
+++ b/api/direct_bt/MgmtTypes.hpp
@@ -95,95 +95,148 @@ namespace direct_bt {
ALREADY_PAIRED = 0x13,
PERMISSION_DENIED = 0x14
};
-
std::string getMgmtStatusString(const MgmtStatus opc) noexcept;
- enum class MgmtOpcode : uint16_t {
- READ_VERSION = 0x0001,
- READ_COMMANDS = 0x0002,
- READ_INDEX_LIST = 0x0003,
- READ_INFO = 0x0004,
- SET_POWERED = 0x0005, // uint8_t bool
- SET_DISCOVERABLE = 0x0006, // uint8_t bool [+ uint16_t timeout]
- SET_CONNECTABLE = 0x0007, // uint8_t bool
- SET_FAST_CONNECTABLE = 0x0008, // uint8_t bool
- SET_BONDABLE = 0x0009, // uint8_t bool
- SET_LINK_SECURITY = 0x000A,
- SET_SSP = 0x000B,
- SET_HS = 0x000C,
- SET_LE = 0x000D, // uint8_t bool
- SET_DEV_CLASS = 0x000E, // uint8_t major, uint8_t minor
- SET_LOCAL_NAME = 0x000F, // uint8_t name[MAX_NAME_LENGTH], uint8_t short_name[MAX_SHORT_NAME_LENGTH];
- ADD_UUID = 0x0010,
- REMOVE_UUID = 0x0011,
- LOAD_LINK_KEYS = 0x0012,
- LOAD_LONG_TERM_KEYS = 0x0013,
- DISCONNECT = 0x0014,
- GET_CONNECTIONS = 0x0015,
- PIN_CODE_REPLY = 0x0016,
- PIN_CODE_NEG_REPLY = 0x0017,
- SET_IO_CAPABILITY = 0x0018,
- PAIR_DEVICE = 0x0019,
- CANCEL_PAIR_DEVICE = 0x001A,
- UNPAIR_DEVICE = 0x001B,
- USER_CONFIRM_REPLY = 0x001C,
- USER_CONFIRM_NEG_REPLY = 0x001D,
- USER_PASSKEY_REPLY = 0x001E,
- USER_PASSKEY_NEG_REPLY = 0x001F,
- READ_LOCAL_OOB_DATA = 0x0020,
- ADD_REMOTE_OOB_DATA = 0x0021,
- REMOVE_REMOTE_OOB_DATA = 0x0022,
- START_DISCOVERY = 0x0023,
- STOP_DISCOVERY = 0x0024,
- CONFIRM_NAME = 0x0025,
- BLOCK_DEVICE = 0x0026,
- UNBLOCK_DEVICE = 0x0027,
- SET_DEVICE_ID = 0x0028,
- SET_ADVERTISING = 0x0029,
- SET_BREDR = 0x002A,
- SET_STATIC_ADDRESS = 0x002B,
- SET_SCAN_PARAMS = 0x002C,
- SET_SECURE_CONN = 0x002D,
- SET_DEBUG_KEYS = 0x002E,
- SET_PRIVACY = 0x002F,
- LOAD_IRKS = 0x0030,
- GET_CONN_INFO = 0x0031,
- GET_CLOCK_INFO = 0x0032,
- ADD_DEVICE_WHITELIST = 0x0033,
- REMOVE_DEVICE_WHITELIST = 0x0034,
- LOAD_CONN_PARAM = 0x0035,
- READ_UNCONF_INDEX_LIST = 0x0036,
- READ_CONFIG_INFO = 0x0037,
- SET_EXTERNAL_CONFIG = 0x0038,
- SET_PUBLIC_ADDRESS = 0x0039,
- START_SERVICE_DISCOVERY = 0x003A,
- READ_LOCAL_OOB_EXT_DATA = 0x003B,
- READ_EXT_INDEX_LIST = 0x003C,
- READ_ADV_FEATURES = 0x003D,
- ADD_ADVERTISING = 0x003E,
- REMOVE_ADVERTISING = 0x003F,
- GET_ADV_SIZE_INFO = 0x0040,
- START_LIMITED_DISCOVERY = 0x0041,
- READ_EXT_INFO = 0x0042,
- SET_APPEARANCE = 0x0043,
- GET_PHY_CONFIGURATION = 0x0044,
- SET_PHY_CONFIGURATION = 0x0045,
- SET_BLOCKED_KEYS = 0x0046
- };
-
- std::string getMgmtOpcodeString(const MgmtOpcode op) noexcept;
-
enum MgmtOption : uint32_t {
EXTERNAL_CONFIG = 0x00000001,
PUBLIC_ADDRESS = 0x00000002
};
- class MgmtCommand
+ class MgmtMsg
{
protected:
POctets pdu;
+ uint64_t ts_creation;
+
+ virtual std::string baseString() const noexcept {
+ return "opcode "+jau::uint16HexString(getIntOpcode())+", devID "+jau::uint16HexString(getDevID());
+ }
+
+ virtual std::string valueString() const noexcept = 0;
+
+ public:
+ MgmtMsg(const uint16_t opc, const uint16_t dev_id, const uint16_t param_size)
+ : pdu(MGMT_HEADER_SIZE+param_size), ts_creation(jau::getCurrentMilliseconds())
+ {
+ pdu.put_uint16_nc(0, opc);
+ pdu.put_uint16_nc(2, dev_id);
+ pdu.put_uint16_nc(4, param_size);
+ }
+
+ MgmtMsg(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : pdu(buffer, buffer_len), ts_creation(jau::getCurrentMilliseconds())
+ {}
+
+ virtual ~MgmtMsg() {}
+
+ uint64_t getTimestamp() const noexcept { return ts_creation; }
+
+ jau::nsize_t getTotalSize() const noexcept { return pdu.getSize(); }
+
+ /** Return the underlying octets read only */
+ TROOctets & getPDU() noexcept { return pdu; }
+
+ uint16_t getIntOpcode() const noexcept { return pdu.get_uint16_nc(0); }
+ uint16_t getDevID() const noexcept { return pdu.get_uint16_nc(2); }
+
+ virtual std::string toString() const noexcept = 0;
+ };
+
+ class MgmtCommand : public MgmtMsg
+ {
+ public:
+ enum class Opcode : uint16_t {
+ READ_VERSION = 0x0001,
+ READ_COMMANDS = 0x0002,
+ READ_INDEX_LIST = 0x0003,
+ READ_INFO = 0x0004,
+ SET_POWERED = 0x0005, // uint8_t bool
+ SET_DISCOVERABLE = 0x0006, // uint8_t bool [+ uint16_t timeout]
+ SET_CONNECTABLE = 0x0007, // uint8_t bool
+ SET_FAST_CONNECTABLE = 0x0008, // uint8_t bool
+ SET_BONDABLE = 0x0009, // uint8_t bool
+ SET_LINK_SECURITY = 0x000A,
+ SET_SSP = 0x000B,
+ SET_HS = 0x000C,
+ SET_LE = 0x000D, // uint8_t bool
+ SET_DEV_CLASS = 0x000E, // uint8_t major, uint8_t minor
+ SET_LOCAL_NAME = 0x000F, // uint8_t name[MAX_NAME_LENGTH], uint8_t short_name[MAX_SHORT_NAME_LENGTH];
+ ADD_UUID = 0x0010,
+ REMOVE_UUID = 0x0011,
+ LOAD_LINK_KEYS = 0x0012,
+ LOAD_LONG_TERM_KEYS = 0x0013,
+ DISCONNECT = 0x0014,
+ GET_CONNECTIONS = 0x0015,
+ PIN_CODE_REPLY = 0x0016,
+ PIN_CODE_NEG_REPLY = 0x0017,
+ SET_IO_CAPABILITY = 0x0018,
+ PAIR_DEVICE = 0x0019,
+ CANCEL_PAIR_DEVICE = 0x001A,
+ UNPAIR_DEVICE = 0x001B,
+ USER_CONFIRM_REPLY = 0x001C,
+ USER_CONFIRM_NEG_REPLY = 0x001D,
+ USER_PASSKEY_REPLY = 0x001E,
+ USER_PASSKEY_NEG_REPLY = 0x001F,
+ READ_LOCAL_OOB_DATA = 0x0020,
+ ADD_REMOTE_OOB_DATA = 0x0021,
+ REMOVE_REMOTE_OOB_DATA = 0x0022,
+ START_DISCOVERY = 0x0023, // MgmtUint8Cmd
+ STOP_DISCOVERY = 0x0024, // MgmtUint8Cmd
+ CONFIRM_NAME = 0x0025,
+ BLOCK_DEVICE = 0x0026,
+ UNBLOCK_DEVICE = 0x0027,
+ SET_DEVICE_ID = 0x0028,
+ SET_ADVERTISING = 0x0029,
+ SET_BREDR = 0x002A,
+ SET_STATIC_ADDRESS = 0x002B,
+ SET_SCAN_PARAMS = 0x002C,
+ SET_SECURE_CONN = 0x002D, // uint8_t 0x00 disabled, 0x01 enables mixed, 0x02 enables only mode; Core Spec >= 4.1
+ SET_DEBUG_KEYS = 0x002E, // uint8_t 0x00 disabled, 0x01 transient, 0x02 persistent
+ SET_PRIVACY = 0x002F,
+ LOAD_IRKS = 0x0030,
+ GET_CONN_INFO = 0x0031,
+ GET_CLOCK_INFO = 0x0032,
+ ADD_DEVICE_WHITELIST = 0x0033,
+ REMOVE_DEVICE_WHITELIST = 0x0034,
+ LOAD_CONN_PARAM = 0x0035,
+ READ_UNCONF_INDEX_LIST = 0x0036,
+ READ_CONFIG_INFO = 0x0037,
+ SET_EXTERNAL_CONFIG = 0x0038,
+ SET_PUBLIC_ADDRESS = 0x0039,
+ START_SERVICE_DISCOVERY = 0x003A,
+ READ_LOCAL_OOB_EXT_DATA = 0x003B,
+ READ_EXT_INDEX_LIST = 0x003C,
+ READ_ADV_FEATURES = 0x003D,
+ ADD_ADVERTISING = 0x003E,
+ REMOVE_ADVERTISING = 0x003F,
+ GET_ADV_SIZE_INFO = 0x0040,
+ START_LIMITED_DISCOVERY = 0x0041,
+ READ_EXT_INFO = 0x0042,
+ SET_APPEARANCE = 0x0043,
+ GET_PHY_CONFIGURATION = 0x0044, // linux >= 4.19
+ SET_PHY_CONFIGURATION = 0x0045, // linux >= 4.19
+ SET_BLOCKED_KEYS = 0x0046, // linux >= 5.6
+ SET_WIDEBAND_SPEECH = 0x0047, // linux >= 5.7
+ READ_SECURITY_INFO = 0x0048, // linux >= 5.8
+ READ_EXP_FEATURES_INFO = 0x0049, // linux >= 5.8
+ SET_EXP_FEATURE = 0x004a, // linux >= 5.8
+ READ_DEF_SYSTEM_CONFIG = 0x004b, // linux >= 5.9
+ SET_DEF_SYSTEM_CONFIG = 0x004c,
+ READ_DEF_RUNTIME_CONFIG = 0x004d,
+ SET_DEF_RUNTIME_CONFIG = 0x004e,
+ GET_DEVICE_FLAGS = 0x004f,
+ SET_DEVICE_FLAGS = 0x0050,
+ READ_ADV_MONITOR_FEATURES = 0x0051,
+ ADD_ADV_PATTERNS_MONITOR = 0x0052,
+ REMOVE_ADV_MONITOR = 0x0053 // linux >= 5.9
+ };
+ static constexpr uint16_t number(const Opcode rhs) noexcept {
+ return static_cast<uint16_t>(rhs);
+ }
+ static std::string getOpcodeString(const Opcode op) noexcept;
- inline static void checkOpcode(const MgmtOpcode has, const MgmtOpcode min, const MgmtOpcode max)
+ protected:
+ inline static void checkOpcode(const Opcode has, const Opcode min, const Opcode max)
{
if( has < min || has > max ) {
throw MgmtOpcodeException("Has opcode "+jau::uint16HexString(static_cast<uint16_t>(has))+
@@ -191,11 +244,19 @@ namespace direct_bt {
".."+jau::uint16HexString(static_cast<uint16_t>(max))+"]", E_FILE_LINE);
}
}
+ static void checkOpcode(const Opcode has, const Opcode exp)
+ {
+ if( has != exp ) {
+ throw MgmtOpcodeException("Has evcode "+jau::uint16HexString(static_cast<uint16_t>(has))+
+ ", not matching "+jau::uint16HexString(static_cast<uint16_t>(exp)), E_FILE_LINE);
+ }
+ }
- virtual std::string baseString() const noexcept {
- return "opcode="+jau::uint16HexString(static_cast<uint16_t>(getOpcode()))+" "+getOpcodeString()+", devID "+jau::uint16HexString(getDevID());
+ virtual std::string baseString() const noexcept override {
+ return "opcode "+getOpcodeString()+", devID "+jau::uint16HexString(getDevID());
}
- virtual std::string valueString() const noexcept {
+
+ virtual std::string valueString() const noexcept override {
const jau::nsize_t psz = getParamSize();
const std::string ps = psz > 0 ? jau::bytesHexString(getParam(), 0, psz, true /* lsbFirst */, true /* leading0X */) : "";
return "param[size "+std::to_string(getParamSize())+", data "+ps+"], tsz "+std::to_string(getTotalSize());
@@ -203,50 +264,90 @@ namespace direct_bt {
public:
- MgmtCommand(const MgmtOpcode opc, const uint16_t dev_id, const uint16_t param_size=0)
- : pdu(MGMT_HEADER_SIZE+param_size)
+ MgmtCommand(const Opcode opc, const uint16_t dev_id, const uint16_t param_size=0)
+ : MgmtMsg(number(opc), dev_id, param_size)
{
- checkOpcode(opc, MgmtOpcode::READ_VERSION, MgmtOpcode::SET_BLOCKED_KEYS);
-
- pdu.put_uint16_nc(0, static_cast<uint16_t>(opc));
- pdu.put_uint16_nc(2, dev_id);
- pdu.put_uint16_nc(4, param_size);
+ checkOpcode(opc, Opcode::READ_VERSION, Opcode::SET_BLOCKED_KEYS);
}
- MgmtCommand(const MgmtOpcode opc, const uint16_t dev_id, const uint16_t param_size, const uint8_t* param)
+
+ MgmtCommand(const Opcode opc, const uint16_t dev_id, const uint16_t param_size, const uint8_t* param)
: MgmtCommand(opc, dev_id, param_size)
{
if( param_size > 0 ) {
memcpy(pdu.get_wptr_nc(MGMT_HEADER_SIZE), param, param_size);
}
}
- virtual ~MgmtCommand() noexcept {}
+ virtual ~MgmtCommand() noexcept override {}
- jau::nsize_t getTotalSize() const noexcept { return pdu.getSize(); }
-
- /** Return the underlying octets read only */
- TROOctets & getPDU() noexcept { return pdu; }
+ Opcode getOpcode() const noexcept { return static_cast<Opcode>( pdu.get_uint16_nc(0) ); }
+ std::string getOpcodeString() const noexcept { return getOpcodeString(getOpcode()); }
- MgmtOpcode getOpcode() const noexcept { return static_cast<MgmtOpcode>( pdu.get_uint16_nc(0) ); }
- std::string getOpcodeString() const noexcept { return getMgmtOpcodeString(getOpcode()); }
- uint16_t getDevID() const noexcept { return pdu.get_uint16_nc(2); }
uint16_t getParamSize() const noexcept { return pdu.get_uint16_nc(4); }
const uint8_t* getParam() const noexcept { return pdu.get_ptr_nc(MGMT_HEADER_SIZE); }
- std::string toString() const noexcept {
- return "MgmtReq["+baseString()+", "+valueString()+"]";
+ std::string toString() const noexcept override {
+ return "MgmtCmd["+baseString()+", "+valueString()+"]";
}
};
class MgmtUint8Cmd : public MgmtCommand
{
public:
- MgmtUint8Cmd(const MgmtOpcode opc, const uint16_t dev_id, const uint8_t data)
+ MgmtUint8Cmd(const Opcode opc, const uint16_t dev_id, const uint8_t data)
: MgmtCommand(opc, dev_id, 1)
{
pdu.put_uint8_nc(MGMT_HEADER_SIZE, data);
}
};
+ /**
+ * uint8_t discoverable
+ * uint16_t timeout
+ */
+ class MgmtSetDiscoverableCmd : public MgmtCommand
+ {
+ protected:
+ std::string valueString() const noexcept override {
+ const std::string ps = "state '"+jau::uint8HexString(getDiscoverable())+"', timeout "+std::to_string(getTimeout())+"s";
+ return "param[size "+std::to_string(getParamSize())+", data["+ps+"]], tsz "+std::to_string(getTotalSize());
+ }
+
+ public:
+ MgmtSetDiscoverableCmd(const uint16_t dev_id, const uint8_t discoverable, uint16_t timeout_sec)
+ : MgmtCommand(Opcode::SET_DISCOVERABLE, dev_id, 1+2)
+ {
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE, discoverable);
+ pdu.put_uint16_nc(MGMT_HEADER_SIZE+1, timeout_sec);
+ }
+ uint8_t getDiscoverable() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE); }
+ uint16_t getTimeout() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+1); }
+ };
+
+ /**
+ * uint8_t name[MGMT_MAX_NAME_LENGTH];
+ * uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+ */
+ class MgmtSetLocalNameCmd : public MgmtCommand
+ {
+ protected:
+ std::string valueString() const noexcept override {
+ const std::string ps = "name '"+getName()+"', shortName '"+getShortName()+"'";
+ return "param[size "+std::to_string(getParamSize())+", data["+ps+"]], tsz "+std::to_string(getTotalSize());
+ }
+
+ public:
+ MgmtSetLocalNameCmd(const uint16_t dev_id, const std::string & name, const std::string & short_name)
+ : MgmtCommand(Opcode::SET_LOCAL_NAME, dev_id, MgmtConstU16::MGMT_MAX_NAME_LENGTH + MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH)
+ {
+ pdu.put_string_nc(MGMT_HEADER_SIZE, name, MgmtConstU16::MGMT_MAX_NAME_LENGTH, true);
+ pdu.put_string_nc(MGMT_HEADER_SIZE+MgmtConstU16::MGMT_MAX_NAME_LENGTH, short_name, MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH, true);
+ }
+ const std::string getName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE); }
+ const std::string getShortName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE + MgmtConstU16::MGMT_MAX_NAME_LENGTH); }
+ };
+
+ // FIXME LOAD_LINK_KEYS = 0x0012,
+ // FIXME LOAD_LONG_TERM_KEYS = 0x0013,
/**
* mgmt_addr_info { EUI48, uint8_t type },
@@ -261,15 +362,17 @@ namespace direct_bt {
public:
MgmtDisconnectCmd(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType)
- : MgmtCommand(MgmtOpcode::DISCONNECT, dev_id, 6+1)
+ : MgmtCommand(Opcode::DISCONNECT, dev_id, 6+1)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
};
+ // FIXME LOAD_IRKS = 0x0030,
+
/**
* mgmt_addr_info { EUI48, uint8_t type },
*/
@@ -283,10 +386,10 @@ namespace direct_bt {
public:
MgmtGetConnectionInfoCmd(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType)
- : MgmtCommand(MgmtOpcode::GET_CONN_INFO, dev_id, 6+1)
+ : MgmtCommand(Opcode::GET_CONN_INFO, dev_id, 6+1)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
@@ -309,10 +412,10 @@ namespace direct_bt {
public:
MgmtPinCodeReplyCmd(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType,
const uint8_t pin_len, const TROOctets &pin_code)
- : MgmtCommand(MgmtOpcode::PIN_CODE_REPLY, dev_id, 6+1+1+16)
+ : MgmtCommand(Opcode::PIN_CODE_REPLY, dev_id, 6+1+1+16)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
pdu.put_uint8_nc(MGMT_HEADER_SIZE+7, pin_len);
pdu.put_octets_nc(MGMT_HEADER_SIZE+8, pin_code);
}
@@ -335,15 +438,27 @@ namespace direct_bt {
public:
MgmtPinCodeNegativeReplyCmd(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType)
- : MgmtCommand(MgmtOpcode::PIN_CODE_NEG_REPLY, dev_id, 6+1)
+ : MgmtCommand(Opcode::PIN_CODE_NEG_REPLY, dev_id, 6+1)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
};
+ // FIXME SET_IO_CAPABILITY = 0x0018,
+ // FIXME PAIR_DEVICE = 0x0019,
+ // FIXME CANCEL_PAIR_DEVICE = 0x001A,
+ // FIXME UNPAIR_DEVICE = 0x001B,
+ // FIXME USER_CONFIRM_REPLY = 0x001C,
+ // FIXME USER_CONFIRM_NEG_REPLY = 0x001D,
+ // FIXME USER_PASSKEY_REPLY = 0x001E,
+ // FIXME USER_PASSKEY_NEG_REPLY = 0x001F,
+ // TODO READ_LOCAL_OOB_DATA = 0x0020,
+ // TODO ADD_REMOTE_OOB_DATA = 0x0021,
+ // TODO REMOVE_REMOTE_OOB_DATA = 0x0022,
+
/**
* mgmt_addr_info { EUI48, uint8_t type },
* uint8_t action
@@ -359,11 +474,11 @@ namespace direct_bt {
public:
MgmtAddDeviceToWhitelistCmd(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType, const HCIWhitelistConnectType ctype)
- : MgmtCommand(MgmtOpcode::ADD_DEVICE_WHITELIST, dev_id, 6+1+1)
+ : MgmtCommand(Opcode::ADD_DEVICE_WHITELIST, dev_id, 6+1+1)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6+1, number(ctype));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6+1, direct_bt::number(ctype));
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
@@ -383,38 +498,15 @@ namespace direct_bt {
public:
MgmtRemoveDeviceFromWhitelistCmd(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType)
- : MgmtCommand(MgmtOpcode::REMOVE_DEVICE_WHITELIST, dev_id, 6+1)
+ : MgmtCommand(Opcode::REMOVE_DEVICE_WHITELIST, dev_id, 6+1)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
};
- /**
- * uint8_t name[MGMT_MAX_NAME_LENGTH];
- * uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
- */
- class MgmtSetLocalNameCmd : public MgmtCommand
- {
- protected:
- std::string valueString() const noexcept override {
- const std::string ps = "name '"+getName()+"', shortName '"+getShortName()+"'";
- return "param[size "+std::to_string(getParamSize())+", data["+ps+"]], tsz "+std::to_string(getTotalSize());
- }
-
- public:
- MgmtSetLocalNameCmd(const uint16_t dev_id, const std::string & name, const std::string & short_name)
- : MgmtCommand(MgmtOpcode::SET_LOCAL_NAME, dev_id, MgmtConstU16::MGMT_MAX_NAME_LENGTH + MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH)
- {
- pdu.put_string_nc(MGMT_HEADER_SIZE, name, MgmtConstU16::MGMT_MAX_NAME_LENGTH, true);
- pdu.put_string_nc(MGMT_HEADER_SIZE+MgmtConstU16::MGMT_MAX_NAME_LENGTH, short_name, MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH, true);
- }
- const std::string getName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE); }
- const std::string getShortName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE + MgmtConstU16::MGMT_MAX_NAME_LENGTH); }
- };
-
struct MgmtConnParam {
EUI48 address;
uint8_t address_type;
@@ -465,7 +557,7 @@ namespace direct_bt {
public:
MgmtLoadConnParamCmd(const uint16_t dev_id, const MgmtConnParam & connParam)
- : MgmtCommand(MgmtOpcode::LOAD_CONN_PARAM, dev_id, 2 + 15)
+ : MgmtCommand(Opcode::LOAD_CONN_PARAM, dev_id, 2 + 15)
{
jau::nsize_t offset = MGMT_HEADER_SIZE;
pdu.put_uint16_nc(offset, 1); offset+= 2;
@@ -479,7 +571,7 @@ namespace direct_bt {
}
MgmtLoadConnParamCmd(const uint16_t dev_id, std::vector<std::shared_ptr<MgmtConnParam>> connParams)
- : MgmtCommand(MgmtOpcode::LOAD_CONN_PARAM, dev_id, 2 + connParams.size() * 15)
+ : MgmtCommand(Opcode::LOAD_CONN_PARAM, dev_id, 2 + connParams.size() * 15)
{
jau::nsize_t offset = MGMT_HEADER_SIZE;
pdu.put_uint16_nc(offset, connParams.size()); offset+= 2;
@@ -510,7 +602,7 @@ namespace direct_bt {
* uint16_t dev-id,
* uint16_t param_size
*/
- class MgmtEvent
+ class MgmtEvent : public MgmtMsg
{
public:
enum class Opcode : uint16_t {
@@ -552,21 +644,23 @@ namespace direct_bt {
ADVERTISING_ADDED = 0x0023,
ADVERTISING_REMOVED = 0x0024,
EXT_INFO_CHANGED = 0x0025,
- PHY_CONFIGURATION_CHANGED = 0x0026,
- MGMT_EVENT_TYPE_COUNT = 0x0026
+ PHY_CONFIGURATION_CHANGED = 0x0026, // linux >= 4.19
+ EXP_FEATURE_CHANGED = 0x0027, // linux >= 5.8
+ DEVICE_FLAGS_CHANGED = 0x002a,
+ ADV_MONITOR_ADDED = 0x002b,
+ ADV_MONITOR_REMOVED = 0x002c,
+ MGMT_EVENT_TYPE_COUNT = 0x002c
};
-
+ static constexpr uint16_t number(const Opcode rhs) noexcept {
+ return static_cast<uint16_t>(rhs);
+ }
static std::string getOpcodeString(const Opcode opc) noexcept;
protected:
- /** actual received mgmt event */
- POctets pdu;
- uint64_t ts_creation;
-
- static void checkOpcode(const Opcode has, const Opcode min, const Opcode max)
+ inline static void checkOpcode(const Opcode has, const Opcode min, const Opcode max)
{
if( has < min || has > max ) {
- throw MgmtOpcodeException("Has evcode "+jau::uint16HexString(static_cast<uint16_t>(has))+
+ throw MgmtOpcodeException("Has opcode "+jau::uint16HexString(static_cast<uint16_t>(has))+
", not within range ["+jau::uint16HexString(static_cast<uint16_t>(min))+
".."+jau::uint16HexString(static_cast<uint16_t>(max))+"]", E_FILE_LINE);
}
@@ -574,16 +668,15 @@ namespace direct_bt {
static void checkOpcode(const Opcode has, const Opcode exp)
{
if( has != exp ) {
- throw MgmtOpcodeException("Has evcode "+jau::uint16HexString(static_cast<uint16_t>(has))+
+ throw MgmtOpcodeException("Has opcode "+jau::uint16HexString(static_cast<uint16_t>(has))+
", not matching "+jau::uint16HexString(static_cast<uint16_t>(exp)), E_FILE_LINE);
}
}
- virtual std::string baseString() const {
- return "opcode="+jau::uint16HexString(static_cast<uint16_t>(getOpcode()))+
- " "+getOpcodeString()+", devID "+jau::uint16HexString(getDevID(), true);
+ virtual std::string baseString() const noexcept override {
+ return "opcode "+getOpcodeString()+", devID "+jau::uint16HexString(getDevID(), true);
}
- virtual std::string valueString() const {
+ virtual std::string valueString() const noexcept override {
const jau::nsize_t d_sz = getDataSize();
const std::string d_str = d_sz > 0 ? jau::bytesHexString(getData(), 0, d_sz, true /* lsbFirst */, true /* leading0X */) : "";
return "data[size "+std::to_string(d_sz)+", data "+d_str+"], tsz "+std::to_string(getTotalSize());
@@ -601,7 +694,7 @@ namespace direct_bt {
/** Persistent memory, w/ ownership ..*/
MgmtEvent(const uint8_t* buffer, const jau::nsize_t buffer_len, const jau::nsize_t exp_param_size)
- : pdu(buffer, buffer_len), ts_creation(jau::getCurrentMilliseconds())
+ : MgmtMsg(buffer, buffer_len)
{
const jau::nsize_t paramSize = getParamSize();
pdu.check_range(0, MGMT_HEADER_SIZE+paramSize);
@@ -612,7 +705,7 @@ namespace direct_bt {
}
MgmtEvent(const Opcode opc, const uint16_t dev_id, const uint16_t param_size=0)
- : pdu(MGMT_HEADER_SIZE+param_size), ts_creation(jau::getCurrentMilliseconds())
+ : MgmtMsg(number(opc), dev_id, param_size)
{
// checkOpcode(opc, READ_VERSION, SET_BLOCKED_KEYS);
@@ -627,11 +720,10 @@ namespace direct_bt {
memcpy(pdu.get_wptr_nc(MGMT_HEADER_SIZE), param, param_size);
}
}
- virtual ~MgmtEvent() noexcept {}
+ virtual ~MgmtEvent() noexcept override {}
jau::nsize_t getTotalSize() const noexcept { return pdu.getSize(); }
- uint64_t getTimestamp() const noexcept { return ts_creation; }
Opcode getOpcode() const noexcept { return static_cast<Opcode>( pdu.get_uint16_nc(0) ); }
std::string getOpcodeString() const noexcept { return getOpcodeString(getOpcode()); }
uint16_t getDevID() const noexcept { return pdu.get_uint16_nc(2); }
@@ -645,17 +737,44 @@ namespace direct_bt {
return req.getDevID() == getDevID();
}
- std::string toString() const {
+ std::string toString() const noexcept override {
return "MgmtEvt["+baseString()+", "+valueString()+"]";
}
};
+ /**
+ * mgmt_addr_info { EUI48, uint8_t type },
+ */
+ class MgmtEvtAdressInfoMeta : public MgmtEvent
+ {
+ protected:
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", address="+getAddress().toString()+
+ ", addressType "+getBDAddressTypeString(getAddressType());
+ }
+
+ public:
+ MgmtEvtAdressInfoMeta(const Opcode opc, const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 7)
+ {
+ checkOpcode(getOpcode(), opc);
+ }
+
+ virtual ~MgmtEvtAdressInfoMeta() noexcept override {}
+
+ const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
+ BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
+
+ jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+7; }
+ jau::nsize_t getDataSize() const noexcept override { return getParamSize()-7; }
+ const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
+ };
+
class MgmtEvtCmdComplete : public MgmtEvent
{
protected:
- std::string baseString() const override {
- return MgmtEvent::baseString()+", req-opcode="+jau::uint16HexString(static_cast<uint16_t>(getReqOpcode()))+
- " "+getMgmtOpcodeString(getReqOpcode())+
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", cmd "+MgmtCommand::getOpcodeString(getCmdOpcode())+
", status "+jau::uint8HexString(static_cast<uint8_t>(getStatus()), true)+" "+getMgmtStatusString(getStatus());
}
@@ -667,8 +786,8 @@ namespace direct_bt {
public:
- static MgmtOpcode getReqOpcode(const uint8_t *data) {
- return static_cast<MgmtOpcode>( jau::get_uint16(data, MGMT_HEADER_SIZE, true /* littleEndian */) );
+ static MgmtCommand::Opcode getCmdOpcode(const uint8_t *data) {
+ return static_cast<MgmtCommand::Opcode>( jau::get_uint16(data, MGMT_HEADER_SIZE, true /* littleEndian */) );
}
MgmtEvtCmdComplete(const uint8_t* buffer, const jau::nsize_t buffer_len)
@@ -679,7 +798,7 @@ namespace direct_bt {
virtual ~MgmtEvtCmdComplete() noexcept override {}
- MgmtOpcode getReqOpcode() const noexcept { return static_cast<MgmtOpcode>( pdu.get_uint16_nc(MGMT_HEADER_SIZE) ); }
+ MgmtCommand::Opcode getCmdOpcode() const noexcept { return static_cast<MgmtCommand::Opcode>( pdu.get_uint16_nc(MGMT_HEADER_SIZE) ); }
MgmtStatus getStatus() const noexcept { return static_cast<MgmtStatus>( pdu.get_uint8_nc(MGMT_HEADER_SIZE+2) ); }
jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+3; }
@@ -687,19 +806,24 @@ namespace direct_bt {
const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
bool validate(const MgmtCommand &req) const noexcept override {
- return MgmtEvent::validate(req) && req.getOpcode() == getReqOpcode();
+ return MgmtEvent::validate(req) && req.getOpcode() == getCmdOpcode();
}
/**
+ * Returns AdapterSetting if getCmdOpcode() expects a single 4-octet AdapterSetting and hence getDataSize() == 4.
+ */
+ AdapterSetting getCurrentSettings() const noexcept;
+
+ /**
* Convert this instance into ConnectionInfo
- * if getReqOpcode() == GET_CONN_INFO, getStatus() == SUCCESS and size allows,
+ * if getCmdOpcode() == GET_CONN_INFO, getStatus() == SUCCESS and size allows,
* otherwise returns nullptr.
*/
std::shared_ptr<ConnectionInfo> toConnectionInfo() const noexcept;
/**
* Convert this instance into ConnectionInfo
- * if getReqOpcode() == SET_LOCAL_NAME, getStatus() == SUCCESS and size allows,
+ * if getCmdOpcode() == SET_LOCAL_NAME, getStatus() == SUCCESS and size allows,
* otherwise returns nullptr.
*/
std::shared_ptr<NameAndShortName> toNameAndShortName() const noexcept;
@@ -710,9 +834,8 @@ namespace direct_bt {
public:
protected:
- std::string baseString() const override {
- return MgmtEvent::baseString()+", req-opcode="+jau::uint16HexString(static_cast<uint16_t>(getReqOpcode()))+
- " "+getMgmtOpcodeString(getReqOpcode())+
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", cmd "+MgmtCommand::getOpcodeString(getCmdOpcode())+
", status "+jau::uint8HexString(static_cast<uint8_t>(getStatus()))+" "+getMgmtStatusString(getStatus());
}
@@ -722,7 +845,7 @@ namespace direct_bt {
{
checkOpcode(getOpcode(), Opcode::CMD_STATUS);
}
- MgmtOpcode getReqOpcode() const noexcept { return static_cast<MgmtOpcode>( pdu.get_uint16_nc(MGMT_HEADER_SIZE) ); }
+ MgmtCommand::Opcode getCmdOpcode() const noexcept { return static_cast<MgmtCommand::Opcode>( pdu.get_uint16_nc(MGMT_HEADER_SIZE) ); }
MgmtStatus getStatus() const noexcept { return static_cast<MgmtStatus>( pdu.get_uint8_nc(MGMT_HEADER_SIZE+2) ); }
jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+3; }
@@ -730,38 +853,28 @@ namespace direct_bt {
const uint8_t* getData() const noexcept override { return nullptr; }
bool validate(const MgmtCommand &req) const noexcept override {
- return MgmtEvent::validate(req) && req.getOpcode() == getReqOpcode();
+ return MgmtEvent::validate(req) && req.getOpcode() == getCmdOpcode();
}
};
- class MgmtEvtDiscovering : public MgmtEvent
+ class MgmtEvtControllerError : public MgmtEvent
{
public:
protected:
- std::string baseString() const override {
- return MgmtEvent::baseString()+", scan-type "+getScanTypeString(getScanType())+
- ", enabled "+std::to_string(getEnabled());
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", error-code "+jau::uint8HexString(static_cast<uint8_t>(getErrorCode()));
}
public:
- MgmtEvtDiscovering(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, 2)
- {
- checkOpcode(getOpcode(), Opcode::DISCOVERING);
- }
-
- MgmtEvtDiscovering(const uint16_t dev_id, const ScanType scanType, const bool enabled)
- : MgmtEvent(Opcode::DISCOVERING, dev_id, 1+1)
+ MgmtEvtControllerError(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 1)
{
- pdu.put_uint8_nc(MGMT_HEADER_SIZE, number(scanType));
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+1, enabled);
+ checkOpcode(getOpcode(), Opcode::CONTROLLER_ERROR);
}
+ uint8_t getErrorCode() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE); }
- ScanType getScanType() const noexcept { return static_cast<ScanType>( pdu.get_uint8_nc(MGMT_HEADER_SIZE) ); }
- bool getEnabled() const noexcept { return 0 != pdu.get_uint8_nc(MGMT_HEADER_SIZE+1); }
-
- jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+2; }
+ jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+1; }
jau::nsize_t getDataSize() const noexcept override { return 0; }
const uint8_t* getData() const noexcept override { return nullptr; }
};
@@ -774,7 +887,7 @@ namespace direct_bt {
public:
protected:
- std::string baseString() const override {
+ std::string baseString() const noexcept override {
return MgmtEvent::baseString()+", settings="+getAdapterSettingMaskString(getSettings());
}
@@ -792,103 +905,41 @@ namespace direct_bt {
};
/**
- * mgmt_addr_info { EUI48, uint8_t type },
- * int8_t store_hint,
- * uint16_t min_interval;
- * uint16_t max_interval;
- * uint16_t latency,
- * uint16_t timeout,
+ * uint8_t name[MGMT_MAX_NAME_LENGTH];
+ * uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
*/
- class MgmtEvtNewConnectionParam : public MgmtEvent
+ class MgmtEvtLocalNameChanged : public MgmtEvent
{
- public:
-
protected:
- std::string baseString() const override {
- return MgmtEvent::baseString()+", address="+getAddress().toString()+
- ", addressType "+getBDAddressTypeString(getAddressType())+
- ", store-hint "+std::to_string(getStoreHint())+
- ", interval["+std::to_string(getMinInterval())+".."+std::to_string(getMaxInterval())+
- "], latency "+std::to_string(getLatency())+", timeout "+std::to_string(getTimeout());
+ std::string valueString() const noexcept override {
+ return "name '"+getName()+"', shortName '"+getShortName()+"'";
}
public:
- MgmtEvtNewConnectionParam(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, 16)
- {
- checkOpcode(getOpcode(), Opcode::NEW_CONN_PARAM);
- }
- const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
- BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
-
- int8_t getStoreHint() const noexcept { return pdu.get_int8_nc(MGMT_HEADER_SIZE+7); }
- uint16_t getMinInterval() const noexcept { return pdu.get_uint32_nc(MGMT_HEADER_SIZE+8); }
- uint16_t getMaxInterval() const noexcept { return pdu.get_uint32_nc(MGMT_HEADER_SIZE+10); }
- uint16_t getLatency() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+12); }
- uint16_t getTimeout() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+14); }
-
- jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+16; }
- jau::nsize_t getDataSize() const noexcept override { return getParamSize()-16; }
- const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
- };
-
- /**
- * mgmt_addr_info { EUI48, uint8_t type },
- * int8_t rssi,
- * uint32_t flags,
- * uint16_t eir_len;
- * uint8_t *eir
- */
- class MgmtEvtDeviceFound : public MgmtEvent
- {
- private:
- std::shared_ptr<EInfoReport> eireport;
-
- protected:
- std::string baseString() const override {
- if( nullptr != eireport ) {
- return MgmtEvent::baseString()+", "+eireport->toString(false /* includeServices */);
- } else {
- return MgmtEvent::baseString()+", address="+getAddress().toString()+
- ", addressType "+getBDAddressTypeString(getAddressType())+
- ", rssi "+std::to_string(getRSSI())+", flags="+jau::uint32HexString(getFlags(), true)+
- ", eir-size "+std::to_string(getEIRSize());
- }
- }
+ static jau::nsize_t namesDataSize() noexcept { return MgmtConstU16::MGMT_MAX_NAME_LENGTH + MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH; }
+ static jau::nsize_t getRequiredTotalSize() noexcept { return MGMT_HEADER_SIZE + namesDataSize(); }
- public:
- MgmtEvtDeviceFound(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, 14)
+ MgmtEvtLocalNameChanged(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, namesDataSize())
{
- checkOpcode(getOpcode(), Opcode::DEVICE_FOUND);
- eireport = nullptr;
+ checkOpcode(getOpcode(), Opcode::LOCAL_NAME_CHANGED);
}
- MgmtEvtDeviceFound(const uint16_t dev_id, std::shared_ptr<EInfoReport> eir)
- : MgmtEvent(Opcode::DEVICE_FOUND, dev_id, 6+1+1+4+2+0)
+ MgmtEvtLocalNameChanged(const uint16_t dev_id, const std::string & name, const std::string & short_name)
+ : MgmtEvent(Opcode::LOCAL_NAME_CHANGED, dev_id, MgmtConstU16::MGMT_MAX_NAME_LENGTH + MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH)
{
- pdu.put_eui48_nc(MGMT_HEADER_SIZE, eir->getAddress());
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(eir->getAddressType()));
- pdu.put_int8_nc(MGMT_HEADER_SIZE+6+1, eir->getRSSI());
- pdu.put_uint32_nc(MGMT_HEADER_SIZE+6+1+1, eir->getFlags()); // EIR flags only 8bit, Mgmt uses 32bit?
- pdu.put_uint16_nc(MGMT_HEADER_SIZE+6+1+1+4, 0); // eir_len
- eireport = eir;
+ pdu.put_string_nc(MGMT_HEADER_SIZE, name, MgmtConstU16::MGMT_MAX_NAME_LENGTH, true);
+ pdu.put_string_nc(MGMT_HEADER_SIZE+MgmtConstU16::MGMT_MAX_NAME_LENGTH, short_name, MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH, true);
}
- /** Returns the EInfoReport, assuming creation occurred via HCIHandler. Otherwise nullptr. */
- std::shared_ptr<EInfoReport> getEIR() const noexcept { return eireport; }
-
- const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
- BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
-
- int8_t getRSSI() const noexcept { return pdu.get_int8_nc(MGMT_HEADER_SIZE+7); }
- uint32_t getFlags() const noexcept { return pdu.get_uint32_nc(MGMT_HEADER_SIZE+8); }
- uint16_t getEIRSize() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+12); }
+ const std::string getName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE); }
+ const std::string getShortName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE + MgmtConstU16::MGMT_MAX_NAME_LENGTH); }
- jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+14; }
- jau::nsize_t getDataSize() const noexcept override { return getParamSize()-14; }
- const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
+ std::shared_ptr<NameAndShortName> toNameAndShortName() const noexcept;
};
+ // FIXME NEW_LINK_KEY
+ // FIXME NEW_LONG_TERM_KEY
+
/**
* mgmt_addr_info { EUI48, uint8_t type },
* uint32_t flags,
@@ -901,7 +952,7 @@ namespace direct_bt {
uint16_t hci_conn_handle;
protected:
- std::string baseString() const override {
+ std::string baseString() const noexcept override {
return MgmtEvent::baseString()+", address="+getAddress().toString()+
", addressType "+getBDAddressTypeString(getAddressType())+
", flags="+jau::uint32HexString(getFlags(), true)+
@@ -919,7 +970,7 @@ namespace direct_bt {
: MgmtEvent(Opcode::DEVICE_CONNECTED, dev_id, 6+1+4+2), hci_conn_handle(hci_conn_handle_)
{
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
pdu.put_uint32_nc(MGMT_HEADER_SIZE+6+1, 0); // flags
pdu.put_uint16_nc(MGMT_HEADER_SIZE+6+1+4, 0); // eir-len
}
@@ -940,49 +991,6 @@ namespace direct_bt {
/**
* mgmt_addr_info { EUI48, uint8_t type },
- * uint8_t status
- */
- class MgmtEvtDeviceConnectFailed : public MgmtEvent
- {
- private:
- const HCIStatusCode hciStatus;
-
- protected:
- std::string baseString() const override {
- return MgmtEvent::baseString()+", address="+getAddress().toString()+
- ", addressType "+getBDAddressTypeString(getAddressType())+
- ", status[mgmt["+jau::uint8HexString(static_cast<uint8_t>(getStatus()))+" ("+getMgmtStatusString(getStatus())+")]"+
- ", hci["+jau::uint8HexString(static_cast<uint8_t>(hciStatus))+" ("+getHCIStatusCodeString(hciStatus)+")]]";
- }
-
- public:
- MgmtEvtDeviceConnectFailed(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, 8), hciStatus(HCIStatusCode::UNKNOWN)
- {
- checkOpcode(getOpcode(), Opcode::CONNECT_FAILED);
- }
- MgmtEvtDeviceConnectFailed(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType, const HCIStatusCode status)
- : MgmtEvent(Opcode::CONNECT_FAILED, dev_id, 6+1+1), hciStatus(status)
- {
- pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6+1, static_cast<uint8_t>(MgmtStatus::CONNECT_FAILED));
- }
- const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
- BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
-
- MgmtStatus getStatus() const noexcept { return static_cast<MgmtStatus>( pdu.get_uint8_nc(MGMT_HEADER_SIZE+7) ); }
-
- /** Return the root reason in non reduced HCIStatusCode space, if available. Otherwise this value will be HCIStatusCode::UNKNOWN. */
- HCIStatusCode getHCIStatus() const noexcept { return hciStatus; }
-
- jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+8; }
- jau::nsize_t getDataSize() const noexcept override { return getParamSize()-8; }
- const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
- };
-
- /**
- * mgmt_addr_info { EUI48, uint8_t type },
* uint8_t reason
*/
class MgmtEvtDeviceDisconnected : public MgmtEvent
@@ -1016,7 +1024,7 @@ namespace direct_bt {
const uint16_t hci_conn_handle;
protected:
- std::string baseString() const override {
+ std::string baseString() const noexcept override {
const DisconnectReason reason1 = getReason();
const HCIStatusCode reason2 = getHCIReason();
return MgmtEvent::baseString()+", address="+getAddress().toString()+
@@ -1038,7 +1046,7 @@ namespace direct_bt {
{
DisconnectReason disconnectReason = getDisconnectReason(hciReason_);
pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
- pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
pdu.put_uint8_nc(MGMT_HEADER_SIZE+6+1, static_cast<uint8_t>(disconnectReason));
}
@@ -1065,29 +1073,41 @@ namespace direct_bt {
/**
* mgmt_addr_info { EUI48, uint8_t type },
- * uint8_t secure
+ * uint8_t status
*/
- class MgmtEvtPinCodeRequest : public MgmtEvent
+ class MgmtEvtDeviceConnectFailed : public MgmtEvent
{
- public:
+ private:
+ const HCIStatusCode hciStatus;
protected:
- std::string baseString() const override {
+ std::string baseString() const noexcept override {
return MgmtEvent::baseString()+", address="+getAddress().toString()+
", addressType "+getBDAddressTypeString(getAddressType())+
- ", secure "+std::to_string(getSecure());
+ ", status[mgmt["+jau::uint8HexString(static_cast<uint8_t>(getStatus()))+" ("+getMgmtStatusString(getStatus())+")]"+
+ ", hci["+jau::uint8HexString(static_cast<uint8_t>(hciStatus))+" ("+getHCIStatusCodeString(hciStatus)+")]]";
}
public:
- MgmtEvtPinCodeRequest(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, 8)
+ MgmtEvtDeviceConnectFailed(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 8), hciStatus(HCIStatusCode::UNKNOWN)
{
- checkOpcode(getOpcode(), Opcode::PIN_CODE_REQUEST);
+ checkOpcode(getOpcode(), Opcode::CONNECT_FAILED);
+ }
+ MgmtEvtDeviceConnectFailed(const uint16_t dev_id, const EUI48 &address, const BDAddressType addressType, const HCIStatusCode status)
+ : MgmtEvent(Opcode::CONNECT_FAILED, dev_id, 6+1+1), hciStatus(status)
+ {
+ pdu.put_eui48_nc(MGMT_HEADER_SIZE, address);
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(addressType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6+1, static_cast<uint8_t>(MgmtStatus::CONNECT_FAILED));
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
- uint8_t getSecure() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE+7); }
+ MgmtStatus getStatus() const noexcept { return static_cast<MgmtStatus>( pdu.get_uint8_nc(MGMT_HEADER_SIZE+7) ); }
+
+ /** Return the root reason in non reduced HCIStatusCode space, if available. Otherwise this value will be HCIStatusCode::UNKNOWN. */
+ HCIStatusCode getHCIStatus() const noexcept { return hciStatus; }
jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+8; }
jau::nsize_t getDataSize() const noexcept override { return getParamSize()-8; }
@@ -1096,155 +1116,275 @@ namespace direct_bt {
/**
* mgmt_addr_info { EUI48, uint8_t type },
- * uint8_t action
+ * uint8_t secure
*/
- class MgmtEvtDeviceWhitelistAdded : public MgmtEvent
+ class MgmtEvtPinCodeRequest : public MgmtEvent
{
public:
protected:
- std::string baseString() const override {
+ std::string baseString() const noexcept override {
return MgmtEvent::baseString()+", address="+getAddress().toString()+
", addressType "+getBDAddressTypeString(getAddressType())+
- ", action "+std::to_string(getAction());
+ ", secure "+std::to_string(getSecure());
}
public:
- MgmtEvtDeviceWhitelistAdded(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ MgmtEvtPinCodeRequest(const uint8_t* buffer, const jau::nsize_t buffer_len)
: MgmtEvent(buffer, buffer_len, 8)
{
- checkOpcode(getOpcode(), Opcode::DEVICE_WHITELIST_ADDED);
+ checkOpcode(getOpcode(), Opcode::PIN_CODE_REQUEST);
}
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
- uint8_t getAction() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE+7); }
+ uint8_t getSecure() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE+7); }
jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+8; }
jau::nsize_t getDataSize() const noexcept override { return getParamSize()-8; }
const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
};
+ // FIXME USER_CONFIRM_REQUEST = 0x000F,
+
/**
* mgmt_addr_info { EUI48, uint8_t type },
*/
- class MgmtEvtAdressInfoMeta : public MgmtEvent
+ class MgmtEvtUserPasskeyRequest: public MgmtEvtAdressInfoMeta
{
+ public:
+ MgmtEvtUserPasskeyRequest(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvtAdressInfoMeta(Opcode::USER_PASSKEY_REQUEST, buffer, buffer_len)
+ { }
+ };
+
+ // FIXME AUTH_FAILED = 0x0011,
+
+ /**
+ * mgmt_addr_info { EUI48, uint8_t type },
+ * int8_t rssi,
+ * uint32_t flags,
+ * uint16_t eir_len;
+ * uint8_t *eir
+ */
+ class MgmtEvtDeviceFound : public MgmtEvent
+ {
+ private:
+ std::shared_ptr<EInfoReport> eireport;
+
protected:
- std::string baseString() const override {
- return MgmtEvent::baseString()+", address="+getAddress().toString()+
- ", addressType "+getBDAddressTypeString(getAddressType());
+ std::string baseString() const noexcept override {
+ if( nullptr != eireport ) {
+ return MgmtEvent::baseString()+", "+eireport->toString(false /* includeServices */);
+ } else {
+ return MgmtEvent::baseString()+", address="+getAddress().toString()+
+ ", addressType "+getBDAddressTypeString(getAddressType())+
+ ", rssi "+std::to_string(getRSSI())+", flags="+jau::uint32HexString(getFlags(), true)+
+ ", eir-size "+std::to_string(getEIRSize());
+ }
}
public:
- MgmtEvtAdressInfoMeta(const Opcode opc, const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, 7)
+ MgmtEvtDeviceFound(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 14)
{
- checkOpcode(getOpcode(), opc);
+ checkOpcode(getOpcode(), Opcode::DEVICE_FOUND);
+ eireport = nullptr;
+ }
+ MgmtEvtDeviceFound(const uint16_t dev_id, std::shared_ptr<EInfoReport> eir)
+ : MgmtEvent(Opcode::DEVICE_FOUND, dev_id, 6+1+1+4+2+0)
+ {
+ pdu.put_eui48_nc(MGMT_HEADER_SIZE, eir->getAddress());
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+6, direct_bt::number(eir->getAddressType()));
+ pdu.put_int8_nc(MGMT_HEADER_SIZE+6+1, eir->getRSSI());
+ pdu.put_uint32_nc(MGMT_HEADER_SIZE+6+1+1, eir->getFlags()); // EIR flags only 8bit, Mgmt uses 32bit?
+ pdu.put_uint16_nc(MGMT_HEADER_SIZE+6+1+1+4, 0); // eir_len
+ eireport = eir;
}
- virtual ~MgmtEvtAdressInfoMeta() noexcept override {}
+ /** Returns the EInfoReport, assuming creation occurred via HCIHandler. Otherwise nullptr. */
+ std::shared_ptr<EInfoReport> getEIR() const noexcept { return eireport; }
const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
- jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+7; }
- jau::nsize_t getDataSize() const noexcept override { return getParamSize()-7; }
+ int8_t getRSSI() const noexcept { return pdu.get_int8_nc(MGMT_HEADER_SIZE+7); }
+ uint32_t getFlags() const noexcept { return pdu.get_uint32_nc(MGMT_HEADER_SIZE+8); }
+ uint16_t getEIRSize() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+12); }
+
+ jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+14; }
+ jau::nsize_t getDataSize() const noexcept override { return getParamSize()-14; }
const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
};
+ class MgmtEvtDiscovering : public MgmtEvent
+ {
+ public:
+
+ protected:
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", scan-type "+getScanTypeString(getScanType())+
+ ", enabled "+std::to_string(getEnabled());
+ }
+
+ public:
+ MgmtEvtDiscovering(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 2)
+ {
+ checkOpcode(getOpcode(), Opcode::DISCOVERING);
+ }
+
+ MgmtEvtDiscovering(const uint16_t dev_id, const ScanType scanType, const bool enabled)
+ : MgmtEvent(Opcode::DISCOVERING, dev_id, 1+1)
+ {
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE, direct_bt::number(scanType));
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE+1, enabled);
+ }
+
+ ScanType getScanType() const noexcept { return static_cast<ScanType>( pdu.get_uint8_nc(MGMT_HEADER_SIZE) ); }
+ bool getEnabled() const noexcept { return 0 != pdu.get_uint8_nc(MGMT_HEADER_SIZE+1); }
+
+ jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+2; }
+ jau::nsize_t getDataSize() const noexcept override { return 0; }
+ const uint8_t* getData() const noexcept override { return nullptr; }
+ };
+
/**
* mgmt_addr_info { EUI48, uint8_t type },
*/
- class MgmtEvtDeviceWhitelistRemoved : public MgmtEvtAdressInfoMeta
+ class MgmtEvtDeviceBlocked : public MgmtEvtAdressInfoMeta
{
public:
- MgmtEvtDeviceWhitelistRemoved(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvtAdressInfoMeta(Opcode::DEVICE_WHITELIST_REMOVED, buffer, buffer_len)
+ MgmtEvtDeviceBlocked(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvtAdressInfoMeta(Opcode::DEVICE_BLOCKED, buffer, buffer_len)
{ }
};
/**
* mgmt_addr_info { EUI48, uint8_t type },
*/
- class MgmtEvtDeviceUnpaired : public MgmtEvtAdressInfoMeta
+ class MgmtEvtDeviceUnblocked : public MgmtEvtAdressInfoMeta
{
public:
- MgmtEvtDeviceUnpaired(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvtAdressInfoMeta(Opcode::DEVICE_UNPAIRED, buffer, buffer_len)
+ MgmtEvtDeviceUnblocked(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvtAdressInfoMeta(Opcode::DEVICE_UNBLOCKED, buffer, buffer_len)
{ }
};
/**
* mgmt_addr_info { EUI48, uint8_t type },
*/
- class MgmtEvtDeviceBlocked : public MgmtEvtAdressInfoMeta
+ class MgmtEvtDeviceUnpaired : public MgmtEvtAdressInfoMeta
{
public:
- MgmtEvtDeviceBlocked(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvtAdressInfoMeta(Opcode::DEVICE_BLOCKED, buffer, buffer_len)
+ MgmtEvtDeviceUnpaired(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvtAdressInfoMeta(Opcode::DEVICE_UNPAIRED, buffer, buffer_len)
{ }
};
+ // FIXME PASSKEY_NOTIFY = 0x0017,
+ // FIXME NEW_IRK = 0x0018,
+ // FIXME NEW_CSRK = 0x0019,
+
/**
* mgmt_addr_info { EUI48, uint8_t type },
+ * uint8_t action
*/
- class MgmtEvtDeviceUnblocked : public MgmtEvtAdressInfoMeta
+ class MgmtEvtDeviceWhitelistAdded : public MgmtEvent
{
public:
- MgmtEvtDeviceUnblocked(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvtAdressInfoMeta(Opcode::DEVICE_UNBLOCKED, buffer, buffer_len)
- { }
+
+ protected:
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", address="+getAddress().toString()+
+ ", addressType "+getBDAddressTypeString(getAddressType())+
+ ", action "+std::to_string(getAction());
+ }
+
+ public:
+ MgmtEvtDeviceWhitelistAdded(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 8)
+ {
+ checkOpcode(getOpcode(), Opcode::DEVICE_WHITELIST_ADDED);
+ }
+ const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
+ BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
+
+ uint8_t getAction() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE+7); }
+
+ jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+8; }
+ jau::nsize_t getDataSize() const noexcept override { return getParamSize()-8; }
+ const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
};
/**
* mgmt_addr_info { EUI48, uint8_t type },
*/
- class MgmtEvtUserPasskeyRequest: public MgmtEvtAdressInfoMeta
+ class MgmtEvtDeviceWhitelistRemoved : public MgmtEvtAdressInfoMeta
{
public:
- MgmtEvtUserPasskeyRequest(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvtAdressInfoMeta(Opcode::USER_PASSKEY_REQUEST, buffer, buffer_len)
+ MgmtEvtDeviceWhitelistRemoved(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvtAdressInfoMeta(Opcode::DEVICE_WHITELIST_REMOVED, buffer, buffer_len)
{ }
};
/**
- * uint8_t name[MGMT_MAX_NAME_LENGTH];
- * uint8_t short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+ * mgmt_addr_info { EUI48, uint8_t type },
+ * int8_t store_hint,
+ * uint16_t min_interval;
+ * uint16_t max_interval;
+ * uint16_t latency,
+ * uint16_t timeout,
*/
- class MgmtEvtLocalNameChanged : public MgmtEvent
+ class MgmtEvtNewConnectionParam : public MgmtEvent
{
+ public:
+
protected:
- std::string valueString() const override {
- return "name '"+getName()+"', shortName '"+getShortName()+"'";
+ std::string baseString() const noexcept override {
+ return MgmtEvent::baseString()+", address="+getAddress().toString()+
+ ", addressType "+getBDAddressTypeString(getAddressType())+
+ ", store-hint "+std::to_string(getStoreHint())+
+ ", interval["+std::to_string(getMinInterval())+".."+std::to_string(getMaxInterval())+
+ "], latency "+std::to_string(getLatency())+", timeout "+std::to_string(getTimeout());
}
public:
- static jau::nsize_t namesDataSize() noexcept { return MgmtConstU16::MGMT_MAX_NAME_LENGTH + MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH; }
- static jau::nsize_t getRequiredTotalSize() noexcept { return MGMT_HEADER_SIZE + namesDataSize(); }
-
- MgmtEvtLocalNameChanged(const uint8_t* buffer, const jau::nsize_t buffer_len)
- : MgmtEvent(buffer, buffer_len, namesDataSize())
- {
- checkOpcode(getOpcode(), Opcode::LOCAL_NAME_CHANGED);
- }
- MgmtEvtLocalNameChanged(const uint16_t dev_id, const std::string & name, const std::string & short_name)
- : MgmtEvent(Opcode::LOCAL_NAME_CHANGED, dev_id, MgmtConstU16::MGMT_MAX_NAME_LENGTH + MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH)
+ MgmtEvtNewConnectionParam(const uint8_t* buffer, const jau::nsize_t buffer_len)
+ : MgmtEvent(buffer, buffer_len, 16)
{
- pdu.put_string_nc(MGMT_HEADER_SIZE, name, MgmtConstU16::MGMT_MAX_NAME_LENGTH, true);
- pdu.put_string_nc(MGMT_HEADER_SIZE+MgmtConstU16::MGMT_MAX_NAME_LENGTH, short_name, MgmtConstU16::MGMT_MAX_SHORT_NAME_LENGTH, true);
+ checkOpcode(getOpcode(), Opcode::NEW_CONN_PARAM);
}
+ const EUI48 getAddress() const noexcept { return EUI48(pdu.get_ptr_nc(MGMT_HEADER_SIZE)); } // mgmt_addr_info
+ BDAddressType getAddressType() const noexcept { return static_cast<BDAddressType>(pdu.get_uint8_nc(MGMT_HEADER_SIZE+6)); } // mgmt_addr_info
- const std::string getName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE); }
- const std::string getShortName() const noexcept { return pdu.get_string_nc(MGMT_HEADER_SIZE + MgmtConstU16::MGMT_MAX_NAME_LENGTH); }
+ int8_t getStoreHint() const noexcept { return pdu.get_int8_nc(MGMT_HEADER_SIZE+7); }
+ uint16_t getMinInterval() const noexcept { return pdu.get_uint32_nc(MGMT_HEADER_SIZE+8); }
+ uint16_t getMaxInterval() const noexcept { return pdu.get_uint32_nc(MGMT_HEADER_SIZE+10); }
+ uint16_t getLatency() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+12); }
+ uint16_t getTimeout() const noexcept { return pdu.get_uint16_nc(MGMT_HEADER_SIZE+14); }
- std::shared_ptr<NameAndShortName> toNameAndShortName() const noexcept;
+ jau::nsize_t getDataOffset() const noexcept override { return MGMT_HEADER_SIZE+16; }
+ jau::nsize_t getDataSize() const noexcept override { return getParamSize()-16; }
+ const uint8_t* getData() const noexcept override { return getDataSize()>0 ? pdu.get_ptr_nc(getDataOffset()) : nullptr; }
};
+ // TODO UNCONF_INDEX_ADDED = 0x001D,
+ // TODO UNCONF_INDEX_REMOVED = 0x001E,
+ // TODO NEW_CONFIG_OPTIONS = 0x001F,
+ // TODO EXT_INDEX_ADDED = 0x0020,
+ // TODO EXT_INDEX_REMOVED = 0x0021,
+ // TODO LOCAL_OOB_DATA_UPDATED = 0x0022,
+ // TODO ADVERTISING_ADDED = 0x0023,
+ // TODO ADVERTISING_REMOVED = 0x0024,
+ // TODO EXT_INFO_CHANGED = 0x0025,
+ // TODO PHY_CONFIGURATION_CHANGED = 0x0026,
+ // TODO MGMT_EVENT_TYPE_COUNT = 0x0026
+
class MgmtEvtAdapterInfo : public MgmtEvtCmdComplete
{
protected:
- std::string valueString() const override {
+ std::string valueString() const noexcept override {
return getAddress().toString()+", version "+std::to_string(getVersion())+
", manuf "+std::to_string(getManufacturer())+
", settings[sup "+getAdapterSettingMaskString(getSupportedSetting())+", cur "+getAdapterSettingMaskString(getCurrentSetting())+
diff --git a/api/direct_bt/SMPHandler.hpp b/api/direct_bt/SMPHandler.hpp
index 814b2cd6..49c149e5 100644
--- a/api/direct_bt/SMPHandler.hpp
+++ b/api/direct_bt/SMPHandler.hpp
@@ -50,8 +50,10 @@
*/
#ifdef __linux__
#define SMP_SUPPORTED_BY_OS 0
+ #define USE_LINUX_BT_SECURITY 1
#else
#define SMP_SUPPORTED_BY_OS 1
+ #define USE_LINUX_BT_SECURITY 0
#endif
/**
diff --git a/src/direct_bt/DBTAdapter.cpp b/src/direct_bt/DBTAdapter.cpp
index f72bd733..dc609653 100644
--- a/src/direct_bt/DBTAdapter.cpp
+++ b/src/direct_bt/DBTAdapter.cpp
@@ -322,15 +322,18 @@ std::shared_ptr<NameAndShortName> DBTAdapter::setLocalName(const std::string &na
}
bool DBTAdapter::setDiscoverable(bool value) noexcept {
- return mgmt.setMode(dev_id, MgmtOpcode::SET_DISCOVERABLE, value ? 1 : 0);
+ AdapterSetting current_settings;
+ return MgmtStatus::SUCCESS == mgmt.setDiscoverable(dev_id, value ? 0x01 : 0x00, 10 /* timeout seconds */, current_settings);
}
bool DBTAdapter::setBondable(bool value) noexcept {
- return mgmt.setMode(dev_id, MgmtOpcode::SET_BONDABLE, value ? 1 : 0);
+ AdapterSetting current_settings;
+ return mgmt.setMode(dev_id, MgmtCommand::Opcode::SET_BONDABLE, value ? 1 : 0, current_settings);
}
bool DBTAdapter::setPowered(bool value) noexcept {
- return mgmt.setMode(dev_id, MgmtOpcode::SET_POWERED, value ? 1 : 0);
+ AdapterSetting current_settings;
+ return mgmt.setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, value ? 1 : 0, current_settings);
}
HCIStatusCode DBTAdapter::reset() noexcept {
diff --git a/src/direct_bt/DBTManager.cpp b/src/direct_bt/DBTManager.cpp
index 4b805b58..76c7aedb 100644
--- a/src/direct_bt/DBTManager.cpp
+++ b/src/direct_bt/DBTManager.cpp
@@ -46,6 +46,8 @@
#include "HCIComm.hpp"
#include "DBTTypes.hpp"
+#include "SMPHandler.hpp"
+
extern "C" {
#include <inttypes.h>
#include <unistd.h>
@@ -232,22 +234,10 @@ std::shared_ptr<MgmtEvent> DBTManager::sendWithReply(MgmtCommand &req) noexcept
return nullptr;
}
-void DBTManager::setAdapterMode(const uint16_t dev_id, const uint8_t ssp, const uint8_t bredr, const uint8_t le) noexcept {
- bool res;
- res = setMode(dev_id, MgmtOpcode::SET_SSP, ssp);
- DBG_PRINT("setAdapterMode[%d]: SET_SSP(%d): result %d", dev_id, ssp, res);
-
- res = setMode(dev_id, MgmtOpcode::SET_BREDR, bredr);
- DBG_PRINT("setAdapterMode[%d]: SET_BREDR(%d): result %d", dev_id, bredr, res);
-
- res = setMode(dev_id, MgmtOpcode::SET_LE, le);
- DBG_PRINT("setAdapterMode[%d]: SET_LE(%d): result %d", dev_id, le, res);
-}
-
std::shared_ptr<AdapterInfo> DBTManager::initAdapter(const uint16_t dev_id, const BTMode btMode) noexcept {
std::shared_ptr<AdapterInfo> adapterInfo = nullptr;
- bool powered;
- MgmtCommand req0(MgmtOpcode::READ_INFO, dev_id);
+ AdapterSetting current_settings;
+ MgmtCommand req0(MgmtCommand::Opcode::READ_INFO, dev_id);
{
std::shared_ptr<MgmtEvent> res = sendWithReply(req0);
if( nullptr == res ) {
@@ -264,35 +254,50 @@ std::shared_ptr<AdapterInfo> DBTManager::initAdapter(const uint16_t dev_id, cons
}
}
DBG_PRINT("initAdapter[%d, BTMode %s]: Start: %s", dev_id, getBTModeString(btMode).c_str(), adapterInfo->toString().c_str());
+ current_settings = adapterInfo->getCurrentSettingMask();
switch ( btMode ) {
case BTMode::DUAL:
- setAdapterMode(dev_id, 1 /* ssp */, 1 /* bredr */, 1 /* le */);
+ setMode(dev_id, MgmtCommand::Opcode::SET_SSP, 1, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_BREDR, 1, current_settings);
+ setDiscoverable(dev_id, 0, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_LE, 1, current_settings);
+#if USE_LINUX_BT_SECURITY
+ setMode(dev_id, MgmtCommand::Opcode::SET_SECURE_CONN, 1, current_settings);
+#endif
break;
case BTMode::BREDR:
- setAdapterMode(dev_id, 1 /* ssp */, 1 /* bredr */, 0 /* le */);
+ setMode(dev_id, MgmtCommand::Opcode::SET_SSP, 1, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_BREDR, 1, current_settings);
+ setDiscoverable(dev_id, 0, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_LE, 0, current_settings);
break;
case BTMode::NONE:
[[fallthrough]]; // map NONE -> LE
case BTMode::LE:
- setAdapterMode(dev_id, 0 /* ssp */, 0 /* bredr */, 1 /* le */);
+ setMode(dev_id, MgmtCommand::Opcode::SET_SSP, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_BREDR, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_LE, 1, current_settings);
+#if USE_LINUX_BT_SECURITY
+ setMode(dev_id, MgmtCommand::Opcode::SET_SECURE_CONN, 1, current_settings);
+#endif
break;
}
- setMode(dev_id, MgmtOpcode::SET_CONNECTABLE, 0);
- setMode(dev_id, MgmtOpcode::SET_FAST_CONNECTABLE, 0);
+ setMode(dev_id, MgmtCommand::Opcode::SET_CONNECTABLE, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_FAST_CONNECTABLE, 0, current_settings);
removeDeviceFromWhitelist(dev_id, EUI48_ANY_DEVICE, BDAddressType::BDADDR_BREDR); // flush whitelist!
- powered = setMode(dev_id, MgmtOpcode::SET_POWERED, 1);
- DBG_PRINT("setAdapterMode[%d]: SET_POWERED(1): result %d", dev_id, powered);
+ setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, 1, current_settings);
/**
* Update AdapterSettings post settings
*/
- {
+ if( AdapterSetting::NONE != current_settings ) {
+ adapterInfo->setCurrentSettingMask(current_settings);
+ } else {
adapterInfo = nullptr; // flush
-
std::shared_ptr<MgmtEvent> res = sendWithReply(req0);
if( nullptr == res ) {
goto fail;
@@ -314,10 +319,12 @@ fail:
}
void DBTManager::shutdownAdapter(const uint16_t dev_id) noexcept {
- setMode(dev_id, MgmtOpcode::SET_CONNECTABLE, 0);
- setMode(dev_id, MgmtOpcode::SET_FAST_CONNECTABLE, 0);
- setMode(dev_id, MgmtOpcode::SET_DISCOVERABLE, 0);
- setMode(dev_id, MgmtOpcode::SET_POWERED, 0);
+ AdapterSetting current_settings;
+ setMode(dev_id, MgmtCommand::Opcode::SET_SECURE_CONN, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_BONDABLE, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_CONNECTABLE, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_FAST_CONNECTABLE, 0, current_settings);
+ setMode(dev_id, MgmtCommand::Opcode::SET_POWERED, 0, current_settings);
}
DBTManager::DBTManager(const BTMode _defaultBTMode) noexcept
@@ -362,7 +369,7 @@ DBTManager::DBTManager(const BTMode _defaultBTMode) noexcept
// Mandatory
{
- MgmtCommand req0(MgmtOpcode::READ_VERSION, MgmtConstU16::MGMT_INDEX_NONE);
+ MgmtCommand req0(MgmtCommand::Opcode::READ_VERSION, MgmtConstU16::MGMT_INDEX_NONE);
std::shared_ptr<MgmtEvent> res = sendWithReply(req0);
if( nullptr == res ) {
goto fail;
@@ -382,7 +389,7 @@ DBTManager::DBTManager(const BTMode _defaultBTMode) noexcept
}
// Optional
{
- MgmtCommand req0(MgmtOpcode::READ_COMMANDS, MgmtConstU16::MGMT_INDEX_NONE);
+ MgmtCommand req0(MgmtCommand::Opcode::READ_COMMANDS, MgmtConstU16::MGMT_INDEX_NONE);
std::shared_ptr<MgmtEvent> res = sendWithReply(req0);
if( nullptr == res ) {
goto next1;
@@ -396,7 +403,7 @@ DBTManager::DBTManager(const BTMode _defaultBTMode) noexcept
const int expDataSize = 4 + num_commands * 2 + num_events * 2;
if( res->getDataSize() >= expDataSize ) {
for(int i=0; i< num_commands; i++) {
- const MgmtOpcode op = static_cast<MgmtOpcode>( get_uint16(data, 4+i*2, true /* littleEndian */) );
+ const MgmtCommand::Opcode op = static_cast<MgmtCommand::Opcode>( get_uint16(data, 4+i*2, true /* littleEndian */) );
DBG_PRINT("kernel op %d: %s", i, getMgmtOpcodeString(op).c_str());
}
}
@@ -407,7 +414,7 @@ DBTManager::DBTManager(const BTMode _defaultBTMode) noexcept
next1:
// Mandatory
{
- MgmtCommand req0(MgmtOpcode::READ_INDEX_LIST, MgmtConstU16::MGMT_INDEX_NONE);
+ MgmtCommand req0(MgmtCommand::Opcode::READ_INDEX_LIST, MgmtConstU16::MGMT_INDEX_NONE);
std::shared_ptr<MgmtEvent> res = sendWithReply(req0);
if( nullptr == res ) {
goto fail;
@@ -444,6 +451,7 @@ next1:
}
addMgmtEventCallback(-1, MgmtEvent::Opcode::NEW_SETTINGS, jau::bindMemberFunc(this, &DBTManager::mgmtEvNewSettingsCB));
+ addMgmtEventCallback(-1, MgmtEvent::Opcode::CONTROLLER_ERROR, jau::bindMemberFunc(this, &DBTManager::mgmtEvControllerErrorCB));
if( env.DEBUG_EVENT ) {
addMgmtEventCallback(-1, MgmtEvent::Opcode::CLASS_OF_DEV_CHANGED, jau::bindMemberFunc(this, &DBTManager::mgmtEvClassOfDeviceChangedCB));
@@ -640,19 +648,55 @@ int DBTManager::getDefaultAdapterDevID() const noexcept {
return ai->dev_id;
}
-bool DBTManager::setMode(const uint16_t dev_id, const MgmtOpcode opc, const uint8_t mode) noexcept {
+bool DBTManager::setMode(const uint16_t dev_id, const MgmtCommand::Opcode opc, const uint8_t mode, AdapterSetting& current_settings) noexcept {
MgmtUint8Cmd req(opc, dev_id, mode);
- std::shared_ptr<MgmtEvent> res = sendWithReply(req);
- if( nullptr != res ) {
- if( res->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) {
- const MgmtEvtCmdComplete &res1 = *static_cast<const MgmtEvtCmdComplete *>(res.get());
- return MgmtStatus::SUCCESS == res1.getStatus();
- } else if( res->getOpcode() == MgmtEvent::Opcode::CMD_STATUS ) {
- const MgmtEvtCmdStatus &res1 = *static_cast<const MgmtEvtCmdStatus *>(res.get());
- return MgmtStatus::SUCCESS == res1.getStatus();
+ std::shared_ptr<MgmtEvent> reply = sendWithReply(req);
+ MgmtStatus res;
+ if( nullptr != reply ) {
+ if( reply->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) {
+ const MgmtEvtCmdComplete &reply1 = *static_cast<const MgmtEvtCmdComplete *>(reply.get());
+ res = reply1.getStatus();
+ if( MgmtStatus::SUCCESS == res ) {
+ current_settings = reply1.getCurrentSettings();
+ }
+ } else if( reply->getOpcode() == MgmtEvent::Opcode::CMD_STATUS ) {
+ const MgmtEvtCmdStatus &reply1 = *static_cast<const MgmtEvtCmdStatus *>(reply.get());
+ res = reply1.getStatus();
+ } else {
+ res = MgmtStatus::UNKNOWN_COMMAND;
}
+ } else {
+ res = MgmtStatus::TIMEOUT;
}
- return false;
+ DBG_PRINT("DBTManager::setMode[%d, %s]: %s, result %s %s", dev_id,
+ MgmtCommand::getOpcodeString(opc).c_str(), jau::uint8HexString(mode).c_str(),
+ getMgmtStatusString(res).c_str(), getAdapterSettingMaskString(current_settings).c_str());
+ return MgmtStatus::SUCCESS == res;
+}
+
+MgmtStatus DBTManager::setDiscoverable(const uint16_t dev_id, const uint8_t state, const uint16_t timeout_sec, AdapterSetting& current_settings) noexcept {
+ MgmtSetDiscoverableCmd req(dev_id, state, timeout_sec);
+ std::shared_ptr<MgmtEvent> reply = sendWithReply(req);
+ MgmtStatus res;
+ if( nullptr != reply ) {
+ if( reply->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) {
+ const MgmtEvtCmdComplete &reply1 = *static_cast<const MgmtEvtCmdComplete *>(reply.get());
+ res = reply1.getStatus();
+ if( MgmtStatus::SUCCESS == res ) {
+ current_settings = reply1.getCurrentSettings();
+ }
+ } else if( reply->getOpcode() == MgmtEvent::Opcode::CMD_STATUS ) {
+ const MgmtEvtCmdStatus &reply1 = *static_cast<const MgmtEvtCmdStatus *>(reply.get());
+ res = reply1.getStatus();
+ } else {
+ res = MgmtStatus::UNKNOWN_COMMAND;
+ }
+ } else {
+ res = MgmtStatus::TIMEOUT;
+ }
+ DBG_PRINT("DBTManager::setDiscoverable[%d]: %s, result %s %s", dev_id,
+ req.toString().c_str(), getMgmtStatusString(res).c_str(), getAdapterSettingMaskString(current_settings).c_str());
+ return res;
}
ScanType DBTManager::startDiscovery(const uint16_t dev_id, const BTMode btMode) noexcept {
@@ -660,7 +704,7 @@ ScanType DBTManager::startDiscovery(const uint16_t dev_id, const BTMode btMode)
}
ScanType DBTManager::startDiscovery(const uint16_t dev_id, const ScanType scanType) noexcept {
- MgmtUint8Cmd req(MgmtOpcode::START_DISCOVERY, dev_id, number(scanType));
+ MgmtUint8Cmd req(MgmtCommand::Opcode::START_DISCOVERY, dev_id, number(scanType));
std::shared_ptr<MgmtEvent> res = sendWithReply(req);
ScanType type = ScanType::NONE;
if( nullptr != res && res->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) {
@@ -677,7 +721,7 @@ ScanType DBTManager::startDiscovery(const uint16_t dev_id, const ScanType scanTy
return type;
}
bool DBTManager::stopDiscovery(const uint16_t dev_id, const ScanType type) noexcept {
- MgmtUint8Cmd req(MgmtOpcode::STOP_DISCOVERY, dev_id, number(type));
+ MgmtUint8Cmd req(MgmtCommand::Opcode::STOP_DISCOVERY, dev_id, number(type));
std::shared_ptr<MgmtEvent> res = sendWithReply(req);
if( nullptr != res && res->getOpcode() == MgmtEvent::Opcode::CMD_COMPLETE ) {
const MgmtEvtCmdComplete &res1 = *static_cast<const MgmtEvtCmdComplete *>(res.get());
@@ -949,6 +993,12 @@ bool DBTManager::mgmtEvNewSettingsCB(std::shared_ptr<MgmtEvent> e) noexcept {
return true;
}
+bool DBTManager::mgmtEvControllerErrorCB(std::shared_ptr<MgmtEvent> e) noexcept {
+ DBG_PRINT("DBTManager:mgmt:ControllerError: %s", e->toString().c_str());
+ (void)e;
+ return true;
+}
+
bool DBTManager::mgmtEvClassOfDeviceChangedCB(std::shared_ptr<MgmtEvent> e) noexcept {
DBG_PRINT("DBTManager:mgmt:ClassOfDeviceChanged: %s", e->toString().c_str());
(void)e;
diff --git a/src/direct_bt/MgmtTypes.cpp b/src/direct_bt/MgmtTypes.cpp
index 52bdf3b0..de6b1c08 100644
--- a/src/direct_bt/MgmtTypes.cpp
+++ b/src/direct_bt/MgmtTypes.cpp
@@ -163,11 +163,24 @@ std::string direct_bt::getMgmtStatusString(const MgmtStatus opc) noexcept {
X(SET_APPEARANCE) \
X(GET_PHY_CONFIGURATION) \
X(SET_PHY_CONFIGURATION) \
- X(SET_BLOCKED_KEYS)
-
-#define MGMT_OPCODE_CASE_TO_STRING(V) case MgmtOpcode::V: return #V;
-
-std::string direct_bt::getMgmtOpcodeString(const MgmtOpcode op) noexcept {
+ X(SET_BLOCKED_KEYS) \
+ X(SET_WIDEBAND_SPEECH) \
+ X(READ_SECURITY_INFO) \
+ X(READ_EXP_FEATURES_INFO) \
+ X(SET_EXP_FEATURE) \
+ X(READ_DEF_SYSTEM_CONFIG) \
+ X(SET_DEF_SYSTEM_CONFIG) \
+ X(READ_DEF_RUNTIME_CONFIG) \
+ X(SET_DEF_RUNTIME_CONFIG) \
+ X(GET_DEVICE_FLAGS) \
+ X(SET_DEVICE_FLAGS) \
+ X(READ_ADV_MONITOR_FEATURES) \
+ X(ADD_ADV_PATTERNS_MONITOR) \
+ X(REMOVE_ADV_MONITOR)
+
+#define MGMT_OPCODE_CASE_TO_STRING(V) case MgmtCommand::Opcode::V: return #V;
+
+std::string MgmtCommand::getOpcodeString(const Opcode op) noexcept {
switch(op) {
MGMT_OPCODE_ENUM(MGMT_OPCODE_CASE_TO_STRING)
default: ; // fall through intended
@@ -218,7 +231,11 @@ std::string direct_bt::getMgmtOpcodeString(const MgmtOpcode op) noexcept {
X(ADVERTISING_ADDED) \
X(ADVERTISING_REMOVED) \
X(EXT_INFO_CHANGED) \
- X(PHY_CONFIGURATION_CHANGED)
+ X(PHY_CONFIGURATION_CHANGED) \
+ X(EXP_FEATURE_CHANGED) \
+ X(DEVICE_FLAGS_CHANGED) \
+ X(ADV_MONITOR_ADDED) \
+ X(ADV_MONITOR_REMOVED)
#define MGMT_EV_OPCODE_CASE_TO_STRING(V) case MgmtEvent::Opcode::V: return #V;
@@ -236,7 +253,7 @@ std::shared_ptr<MgmtEvent> MgmtEvent::getSpecialized(const uint8_t * buffer, jau
switch( opc ) {
case MgmtEvent::Opcode::CMD_COMPLETE:
if( buffer_size >= MgmtEvtAdapterInfo::getRequiredTotalSize() &&
- MgmtOpcode::READ_INFO == MgmtEvtCmdComplete::getReqOpcode(buffer) ) {
+ MgmtCommand::Opcode::READ_INFO == MgmtEvtCmdComplete::getCmdOpcode(buffer) ) {
res = new MgmtEvtAdapterInfo(buffer, buffer_size);
} else {
res = new MgmtEvtCmdComplete(buffer, buffer_size);
@@ -244,35 +261,36 @@ std::shared_ptr<MgmtEvent> MgmtEvent::getSpecialized(const uint8_t * buffer, jau
break;
case MgmtEvent::Opcode::CMD_STATUS:
res = new MgmtEvtCmdStatus(buffer, buffer_size); break;
- case MgmtEvent::Opcode::DISCOVERING:
- res = new MgmtEvtDiscovering(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::CONTROLLER_ERROR:
+ res = new MgmtEvtControllerError(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::INDEX_ADDED:
+ res = new MgmtEvent(buffer, buffer_size, 0); break;
+ case MgmtEvent::Opcode::INDEX_REMOVED:
+ res = new MgmtEvent(buffer, buffer_size, 0); break;
case MgmtEvent::Opcode::NEW_SETTINGS:
res = new MgmtEvtNewSettings(buffer, buffer_size); break;
- case MgmtEvent::Opcode::NEW_CONN_PARAM:
- res = new MgmtEvtNewConnectionParam(buffer, buffer_size); break;
- case MgmtEvent::Opcode::DEVICE_FOUND:
- res = new MgmtEvtDeviceFound(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::LOCAL_NAME_CHANGED:
+ res = new MgmtEvtLocalNameChanged(buffer, buffer_size); break;
case MgmtEvent::Opcode::DEVICE_CONNECTED:
res = new MgmtEvtDeviceConnected(buffer, buffer_size); break;
- case MgmtEvent::Opcode::CONNECT_FAILED:
- res = new MgmtEvtDeviceConnectFailed(buffer, buffer_size); break;
case MgmtEvent::Opcode::DEVICE_DISCONNECTED:
res = new MgmtEvtDeviceDisconnected(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::CONNECT_FAILED:
+ res = new MgmtEvtDeviceConnectFailed(buffer, buffer_size); break;
case MgmtEvent::Opcode::PIN_CODE_REQUEST:
res = new MgmtEvtPinCodeRequest(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::DEVICE_FOUND:
+ res = new MgmtEvtDeviceFound(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::DISCOVERING:
+ res = new MgmtEvtDiscovering(buffer, buffer_size); break;
+ case MgmtEvent::Opcode::DEVICE_UNPAIRED:
+ res = new MgmtEvtDeviceUnpaired(buffer, buffer_size); break;
case MgmtEvent::Opcode::DEVICE_WHITELIST_ADDED:
res = new MgmtEvtDeviceWhitelistAdded(buffer, buffer_size); break;
case MgmtEvent::Opcode::DEVICE_WHITELIST_REMOVED:
res = new MgmtEvtDeviceWhitelistRemoved(buffer, buffer_size); break;
- case MgmtEvent::Opcode::DEVICE_UNPAIRED:
- res = new MgmtEvtDeviceUnpaired(buffer, buffer_size); break;
- case MgmtEvent::Opcode::LOCAL_NAME_CHANGED:
- res = new MgmtEvtLocalNameChanged(buffer, buffer_size);
- break;
- case MgmtEvent::Opcode::INDEX_ADDED:
- [[fallthrough]];
- case MgmtEvent::Opcode::INDEX_REMOVED:
- [[fallthrough]];
+ case MgmtEvent::Opcode::NEW_CONN_PARAM:
+ res = new MgmtEvtNewConnectionParam(buffer, buffer_size); break;
default:
res = new MgmtEvent(buffer, buffer_size, 0); break;
}
@@ -283,8 +301,49 @@ std::shared_ptr<MgmtEvent> MgmtEvent::getSpecialized(const uint8_t * buffer, jau
// *************************************************
// *************************************************
+AdapterSetting MgmtEvtCmdComplete::getCurrentSettings() const noexcept {
+ if( 4 != getDataSize() ) {
+ return AdapterSetting::NONE;
+ }
+ MgmtCommand::Opcode cmd = getCmdOpcode();
+ switch(cmd) {
+ case MgmtCommand::Opcode::SET_POWERED:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_DISCOVERABLE:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_CONNECTABLE:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_FAST_CONNECTABLE:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_BONDABLE:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_LINK_SECURITY:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_SSP:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_HS:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_LE:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_ADVERTISING:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_BREDR:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_STATIC_ADDRESS:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_SECURE_CONN:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_DEBUG_KEYS:
+ [[fallthrough]];
+ case MgmtCommand::Opcode::SET_PRIVACY:
+ return static_cast<AdapterSetting>( pdu.get_uint32_nc(getDataOffset()) );
+ default:
+ return AdapterSetting::NONE;
+ }
+}
+
std::shared_ptr<ConnectionInfo> MgmtEvtCmdComplete::toConnectionInfo() const noexcept {
- if( MgmtOpcode::GET_CONN_INFO != getReqOpcode() ) {
+ if( MgmtCommand::Opcode::GET_CONN_INFO != getCmdOpcode() ) {
ERR_PRINT("Not a GET_CONN_INFO reply: %s", toString().c_str());
return nullptr;
}
@@ -308,7 +367,7 @@ std::shared_ptr<ConnectionInfo> MgmtEvtCmdComplete::toConnectionInfo() const noe
}
std::shared_ptr<NameAndShortName> MgmtEvtCmdComplete::toNameAndShortName() const noexcept {
- if( MgmtOpcode::SET_LOCAL_NAME != getReqOpcode() ) {
+ if( MgmtCommand::Opcode::SET_LOCAL_NAME != getCmdOpcode() ) {
ERR_PRINT("Not a SET_LOCAL_NAME reply: %s", toString().c_str());
return nullptr;
}
diff --git a/src/direct_bt/SMPHandler.cpp b/src/direct_bt/SMPHandler.cpp
index 86dab20d..89158d5f 100644
--- a/src/direct_bt/SMPHandler.cpp
+++ b/src/direct_bt/SMPHandler.cpp
@@ -65,11 +65,10 @@ SMPEnv::SMPEnv() noexcept
{
}
-#ifdef __linux__
- // Linux/BlueZ prohibits access to the existing SMP implementation via L2CAP (socket).
- bool SMPHandler::IS_SUPPORTED_BY_OS = false;
-#else
+#if SMP_SUPPORTED_BY_OS
bool SMPHandler::IS_SUPPORTED_BY_OS = true;
+#else
+ bool SMPHandler::IS_SUPPORTED_BY_OS = false;
#endif
std::shared_ptr<DBTDevice> SMPHandler::getDeviceChecked() const {