diff options
author | Sven Gothel <[email protected]> | 2020-08-23 09:34:40 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2020-08-23 09:34:40 +0200 |
commit | a49ce8a8a72eb34cc6a4c8d23e4907684350d078 (patch) | |
tree | a5f3206d489afcd665ea419e91e824706199b383 /src | |
parent | 2bcbaa8bd744f2d255259ee999ccfd257f4af2b5 (diff) |
HCIHandler: Produce MgmtEvtDeviceFound events from LE_ADVERTISING_REPORT; EInfoReport: Fix address-type AD -> BDAddressType
Parse LE_ADVERTISING_REPORT and produce MgmtEvtDeviceFound, call its listener.
This removes dependency of Linux Mgmt's MgmtEvtDeviceFound events.
MgmtEvtDeviceFound optionally holds the parsed std::shared_ptr<EInfoReport> instance,
removing the need to process the raw EIR again in DBTAdapter later on.
Misc:
- Fix EInfoReport AD address-type -> BDAddressType conversion (missing)
- Expose LEADVEventType enum w/ string presentation.
Diffstat (limited to 'src')
-rw-r--r-- | src/direct_bt/BTTypes.cpp | 55 | ||||
-rw-r--r-- | src/direct_bt/HCIHandler.cpp | 69 |
2 files changed, 73 insertions, 51 deletions
diff --git a/src/direct_bt/BTTypes.cpp b/src/direct_bt/BTTypes.cpp index b08b2eb9..2ab8bcd9 100644 --- a/src/direct_bt/BTTypes.cpp +++ b/src/direct_bt/BTTypes.cpp @@ -232,6 +232,23 @@ std::string direct_bt::getScanTypeString(const ScanType v) { return "Unknown ScanType"; } +#define LEADVEventType_ENUM(X) \ + X(ADV_IND) \ + X(ADV_DIRECT_IND) \ + X(ADV_SCAN_IND) \ + X(ADV_NONCONN_IND) \ + X(SCAN_RSP) \ + +#define LEADVEventType_CASE_TO_STRING(V) case LEADVEventType::V: return #V; + +std::string direct_bt::getLEADVEventTypeString(const LEADVEventType v) { + switch(v) { + LEADVEventType_ENUM(LEADVEventType_CASE_TO_STRING) + default: ; // fall through intended + } + return "Unknown LEADVEventType"; +} + #define APPEARANCECAT_ENUM(X) \ X(UNKNOWN) \ X(GENERIC_PHONE) \ @@ -376,10 +393,34 @@ std::string EInfoReport::getSourceString() const { case Source::NA: return "N/A"; case Source::AD: return "AD"; case Source::EIR: return "EIR"; + case Source::EIR_MGMT: return "EIR_MGMT"; } return "N/A"; } +void EInfoReport::setADAddressType(uint8_t adAddressType) { + ad_address_type = adAddressType; + switch( ad_address_type ) { + case 0x00: addressType = BDAddressType::BDADDR_LE_PUBLIC; break; + case 0x01: addressType = BDAddressType::BDADDR_LE_RANDOM; break; + case 0x02: addressType = BDAddressType::BDADDR_LE_RANDOM; break; + case 0x03: addressType = BDAddressType::BDADDR_LE_RANDOM; break; + default: addressType = BDAddressType::BDADDR_UNDEFINED; break; + } + set(EIRDataType::BDADDR_TYPE); +} + +void EInfoReport::setAddressType(BDAddressType at) { + addressType = at; + switch( addressType ) { + case BDAddressType::BDADDR_BREDR: ad_address_type = 0; break; + case BDAddressType::BDADDR_LE_PUBLIC: ad_address_type = 0; break; + case BDAddressType::BDADDR_LE_RANDOM: ad_address_type = 1; break; + case BDAddressType::BDADDR_UNDEFINED: ad_address_type = 4; break; + } + set(EIRDataType::BDADDR_TYPE); +} + void EInfoReport::setName(const uint8_t *buffer, int buffer_len) { name = get_string(buffer, buffer_len, 30); set(EIRDataType::NAME); @@ -404,12 +445,12 @@ void EInfoReport::addService(std::shared_ptr<uuid_t> const &uuid) std::string EInfoReport::eirDataMaskToString() const { return std::string("DataSet"+ direct_bt::getEIRDataMaskString(eir_data_mask) ); } -std::string EInfoReport::toString() const { +std::string EInfoReport::toString(const bool includeServices) const { std::string msdstr = nullptr != msd ? msd->toString() : "MSD[null]"; std::string out("EInfoReport::"+getSourceString()+ - "[address["+getAddressString()+", "+getBDAddressTypeString(getAddressType())+"], name['"+name+"'/'"+name_short+ - "'], "+eirDataMaskToString()+ - ", evt-type "+std::to_string(evt_type)+", rssi "+std::to_string(rssi)+ + "[address["+getAddressString()+", "+getBDAddressTypeString(getAddressType())+"/"+std::to_string(ad_address_type)+ + "], name['"+name+"'/'"+name_short+"'], "+eirDataMaskToString()+ + ", evt-type "+getLEADVEventTypeString(evt_type)+", rssi "+std::to_string(rssi)+ ", tx-power "+std::to_string(tx_power)+ ", dev-class "+uint32HexString(device_class, true)+ ", appearance "+uint16HexString(static_cast<uint16_t>(appearance))+" ("+getAppearanceCatString(appearance)+ @@ -421,7 +462,7 @@ std::string EInfoReport::toString() const { ", version "+uint16HexString(did_version, true)+ "], "+msdstr+"]"); - if(services.size() > 0 ) { + if( includeServices && services.size() > 0 ) { out.append("\n"); for(auto it = services.begin(); it != services.end(); it++) { std::shared_ptr<uuid_t> p = *it; @@ -612,11 +653,11 @@ std::vector<std::shared_ptr<EInfoReport>> EInfoReport::read_ad_reports(uint8_t c ad_reports.push_back(std::shared_ptr<EInfoReport>(new EInfoReport())); ad_reports[i]->setSource(Source::AD); ad_reports[i]->setTimestamp(timestamp); - ad_reports[i]->setEvtType(*i_octets++); + ad_reports[i]->setEvtType(static_cast<LEADVEventType>(*i_octets++)); read_segments++; } for(i = 0; i < num_reports && i_octets < limes; i++) { - ad_reports[i]->setAddressType(static_cast<BDAddressType>(*i_octets++)); + ad_reports[i]->setADAddressType(*i_octets++); read_segments++; } for(i = 0; i < num_reports && i_octets + 5 < limes; i++) { diff --git a/src/direct_bt/HCIHandler.cpp b/src/direct_bt/HCIHandler.cpp index 77fd6e39..6ade9e67 100644 --- a/src/direct_bt/HCIHandler.cpp +++ b/src/direct_bt/HCIHandler.cpp @@ -32,8 +32,6 @@ #include <algorithm> -// #define SHOW_LE_ADVERTISING 1 - // #define PERF_PRINT_ON 1 // #define VERBOSE_ON 1 #include <dbt_debug.hpp> @@ -267,17 +265,7 @@ void HCIHandler::hciReaderThreadImpl() { DBG_PRINT("HCIHandler::reader: Drop (meta filter) %s", event->toString().c_str()); continue; // next packet } -#ifdef SHOW_LE_ADVERTISING - if( event->isMetaEvent(HCIMetaEventType::LE_ADVERTISING_REPORT) ) { - std::vector<std::shared_ptr<EInfoReport>> eirlist = EInfoReport::read_ad_reports(event->getParam(), event->getParamSize()); - int i=0; - for_each_idx(eirlist, [&](std::shared_ptr<EInfoReport> &eir) { - INFO_PRINT("LE_ADV[%d]: %s", i, eir->toString().c_str()); - i++; - }); - continue; // next packet - } -#endif /* SHOW_LE_ADVERTISING */ + if( event->isEvent(HCIEventType::CMD_STATUS) || event->isEvent(HCIEventType::CMD_COMPLETE) ) { if( hciEventRing.isFull() ) { @@ -287,28 +275,22 @@ void HCIHandler::hciReaderThreadImpl() { } DBG_PRINT("HCIHandler::reader: CmdResult %s", event->toString().c_str()); hciEventRing.putBlocking( event ); + } else if( event->isMetaEvent(HCIMetaEventType::LE_ADVERTISING_REPORT) ) { + // issue callbacks for the translated AD events + std::vector<std::shared_ptr<EInfoReport>> eirlist = EInfoReport::read_ad_reports(event->getParam(), event->getParamSize()); + int i=0; + for_each_idx(eirlist, [&](std::shared_ptr<EInfoReport> &eir) { + std::shared_ptr<MgmtEvent> mevent( new MgmtEvtDeviceFound(dev_id, eir) ); + DBG_PRINT("LE_ADV[%d]: %s", i, eir->toString().c_str()); + sendMgmtEvent( mevent ); + i++; + }); } else { - // issue a callback + // issue a callback for the translated event std::shared_ptr<MgmtEvent> mevent = translate(event); if( nullptr != mevent ) { - const std::lock_guard<std::recursive_mutex> lock(mtx_callbackLists); // RAII-style acquire and relinquish via destructor - MgmtEventCallbackList & mgmtEventCallbackList = mgmtEventCallbackLists[static_cast<uint16_t>(mevent->getOpcode())]; - int invokeCount = 0; - if( mgmtEventCallbackList.size() > 0 ) { - for (auto it = mgmtEventCallbackList.begin(); it != mgmtEventCallbackList.end(); ++it) { - try { - it->invoke(mevent); - } catch (std::exception &e) { - ERR_PRINT("HCIHandler::fwdPacketReceived-CBs %d/%zd: MgmtEventCallback %s : Caught exception %s", - invokeCount+1, mgmtEventCallbackList.size(), - it->toString().c_str(), e.what()); - } - invokeCount++; - } - } - DBG_PRINT("HCIHandler::reader: Event %s -> %d/%zd callbacks; source %s", - mevent->toString().c_str(), invokeCount, mgmtEventCallbackList.size(), event->toString().c_str()); - (void)invokeCount; + DBG_PRINT("HCIHandler::reader: Event source %s", event->toString().c_str()); + sendMgmtEvent( mevent ); } else { DBG_PRINT("HCIHandler::reader: Drop (no translation) %s", event->toString().c_str()); } @@ -324,18 +306,19 @@ void HCIHandler::hciReaderThreadImpl() { void HCIHandler::sendMgmtEvent(std::shared_ptr<MgmtEvent> event) { const std::lock_guard<std::recursive_mutex> lock(mtx_callbackLists); // RAII-style acquire and relinquish via destructor - const MgmtEvent::Opcode opc = event->getOpcode(); - MgmtEventCallbackList & mgmtEventCallbackList = mgmtEventCallbackLists[static_cast<uint16_t>(opc)]; + MgmtEventCallbackList & mgmtEventCallbackList = mgmtEventCallbackLists[static_cast<uint16_t>(event->getOpcode())]; int invokeCount = 0; - for (auto it = mgmtEventCallbackList.begin(); it != mgmtEventCallbackList.end(); ++it) { - try { - it->invoke(event); - } catch (std::exception &e) { - ERR_PRINT("HCIHandler::sendMgmtEvent-CBs %d/%zd: MgmtEventCallback %s : Caught exception %s", - invokeCount+1, mgmtEventCallbackList.size(), - it->toString().c_str(), e.what()); + if( mgmtEventCallbackList.size() > 0 ) { + for (auto it = mgmtEventCallbackList.begin(); it != mgmtEventCallbackList.end(); ++it) { + try { + it->invoke(event); + } catch (std::exception &e) { + ERR_PRINT("HCIHandler::sendMgmtEvent-CBs %d/%zd: MgmtEventCallback %s : Caught exception %s", + invokeCount+1, mgmtEventCallbackList.size(), + it->toString().c_str(), e.what()); + } + invokeCount++; } - invokeCount++; } DBG_PRINT("HCIHandler::sendMgmtEvent: Event %s -> %d/%zd callbacks", event->toString().c_str(), invokeCount, mgmtEventCallbackList.size()); @@ -483,9 +466,7 @@ HCIHandler::HCIHandler(const BTMode btMode, const uint16_t dev_id, const int rep uint32_t mask = 0; // filter_all_metaevs(mask); filter_set_metaev(HCIMetaEventType::LE_CONN_COMPLETE, mask); -#ifdef SHOW_LE_ADVERTISING filter_set_metaev(HCIMetaEventType::LE_ADVERTISING_REPORT, mask); -#endif filter_put_metaevs(mask); } #ifdef VERBOSE_ON |