M module-bluetooth/Bluetooth/Device.hpp => module-bluetooth/Bluetooth/Device.hpp +50 -0
@@ 24,12 24,62 @@ enum DEVICE_STATE
REMOTE_NAME_FETCHED
};
+namespace TYPE_OF_SERVICE
+{
+ inline constexpr uint32_t POSITIONING = 0x00010000;
+ inline constexpr uint32_t NETWORKING = 0x00020000;
+ inline constexpr uint32_t RENDERING = 0x00040000;
+ inline constexpr uint32_t CAPTURING = 0x00080000;
+ inline constexpr uint32_t OBJECT_TRANSFER = 0x00100000;
+ inline constexpr uint32_t AUDIO = 0x00200000;
+ inline constexpr uint32_t TELEPHONY = 0x00400000;
+ inline constexpr uint32_t INFORMATION = 0x00800000;
+
+ ///> At least one of this class has to be supported by remote device in order to establish connection
+ inline constexpr uint32_t REMOTE_SUPPORTED_SERVICES = (AUDIO | POSITIONING);
+
+} // namespace TYPE_OF_SERVICE
+
+static inline std::string getListOfSupportedServicesInString(uint32_t cod)
+{
+ std::string res = "|";
+ if (cod & TYPE_OF_SERVICE::POSITIONING) {
+ res += "POSITIONING|";
+ }
+ if (cod & TYPE_OF_SERVICE::NETWORKING) {
+ res += "NETWORKING|";
+ }
+ if (cod & TYPE_OF_SERVICE::RENDERING) {
+ res += "RENDERING|";
+ }
+ if (cod & TYPE_OF_SERVICE::CAPTURING) {
+ res += "CAPTURING|";
+ }
+ if (cod & TYPE_OF_SERVICE::OBJECT_TRANSFER) {
+ res += "OBJECT_TRANSFER|";
+ }
+ if (cod & TYPE_OF_SERVICE::AUDIO) {
+ res += "AUDIO|";
+ }
+ if (cod & TYPE_OF_SERVICE::TELEPHONY) {
+ res += "TELEPHONY|";
+ }
+ if (cod & TYPE_OF_SERVICE::INFORMATION) {
+ res += "INFORMATION|";
+ }
+ if (res == std::string("|")) {
+ res += "NONE|";
+ }
+ return res;
+}
+
struct Devicei : public Device
{
public:
bd_addr_t address;
uint8_t pageScanRepetitionMode;
uint16_t clockOffset;
+ uint32_t classOfDevice; ///> Class of Device/Service
DEVICE_STATE state;
Devicei(std::string name = "") : Device(std::move(name))
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp +19 -4
@@ 146,18 146,18 @@ namespace bluetooth
device.setAddress(&addr);
device.pageScanRepetitionMode = gap_event_inquiry_result_get_page_scan_repetition_mode(packet);
device.clockOffset = gap_event_inquiry_result_get_clock_offset(packet);
-
+ device.classOfDevice = gap_event_inquiry_result_get_class_of_device(packet);
LOG_INFO("Device found: %s ", bd_addr_to_str(addr));
- LOG_INFO("with COD: 0x%06x, ", static_cast<unsigned int>(gap_event_inquiry_result_get_class_of_device(packet)));
+ LOG_INFO("with COD: 0x%06x, ", static_cast<unsigned int>(device.classOfDevice));
LOG_INFO("pageScan %d, ", device.pageScanRepetitionMode);
LOG_INFO("clock offset 0x%04x", device.clockOffset);
+
if (gap_event_inquiry_result_get_rssi_available(packet) != 0u) {
LOG_INFO(", rssi %d dBm", static_cast<int8_t>(gap_event_inquiry_result_get_rssi(packet)));
}
if (gap_event_inquiry_result_get_name_available(packet) != 0u) {
auto name = gap_event_inquiry_result_get_name(packet);
device.name = std::string{reinterpret_cast<const char *>(name)};
-
LOG_INFO(", name '%s'", device.name.c_str());
device.state = REMOTE_NAME_FETCHED;
}
@@ 176,6 176,13 @@ namespace bluetooth
if (index >= 0) {
return; // already in our list
}
+ uint32_t classOfDevice = gap_event_inquiry_result_get_class_of_device(packet);
+ ///> Device has to support services: AUDIO for HFP and HSP profiles, and RENDERING for SNK of A2DP profile
+ if (!(classOfDevice & TYPE_OF_SERVICE::REMOTE_SUPPORTED_SERVICES)) {
+ LOG_INFO("Ignoring device with incompatible services: %s, ",
+ getListOfSupportedServicesInString(classOfDevice).c_str());
+ return;
+ }
addNewDevice(packet, addr);
sendDevices();
}
@@ 284,5 291,13 @@ namespace bluetooth
"ApplicationSettingsNew");
return true;
}
-
+ auto GAP::isServiceSupportedByRemote(bd_addr_t addr, uint32_t typeOfService) -> bool
+ {
+ for (const auto &device : devices) {
+ if (bd_addr_cmp(device.address, addr) == 0) {
+ return (device.classOfDevice & typeOfService);
+ }
+ }
+ return false;
+ }
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp +2 -0
@@ 52,6 52,8 @@ namespace bluetooth
auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool;
auto unpair(uint8_t *addr) -> bool;
static auto getDevicesList() -> const std::vector<Devicei> &;
+ static auto isServiceSupportedByRemote(bd_addr_t addr, uint32_t typeOfService) -> bool;
+
static std::string currentlyProcessedDeviceAddr;
explicit GAP(sys::Service *owner);
};
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +19 -4
@@ 1,5 1,9 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
#include <service-bluetooth/ServiceBluetooth.hpp>
#include "ProfileManager.hpp"
+#include <GAP/GAP.hpp>
namespace bluetooth
{
@@ 34,10 38,21 @@ namespace bluetooth
auto ProfileManager::connect(bd_addr_t address) -> Error::Code
{
bd_addr_copy(remoteAddr, address);
- for (auto &[profileName, ptr] : profilesList) {
- if (ptr != nullptr) {
- ptr->setDeviceAddress(remoteAddr);
- ptr->connect();
+ ///> connect to remote only if we are sure that remote side supports our profiles
+ if (GAP::isServiceSupportedByRemote(address, TYPE_OF_SERVICE::RENDERING)) {
+ auto profilePtr = profilesList[AudioProfile::A2DP].get();
+ if (profilePtr != nullptr) {
+ LOG_DEBUG("Connecting device %s to A2DP", bd_addr_to_str(address));
+ profilePtr->setDeviceAddress(remoteAddr);
+ profilePtr->connect();
+ }
+ }
+ if (GAP::isServiceSupportedByRemote(address, TYPE_OF_SERVICE::AUDIO)) {
+ auto profilePtr = profilesList[AudioProfile::HSP].get();
+ if (profilePtr != nullptr) {
+ LOG_DEBUG("Connecting device %s to HSP", bd_addr_to_str(address));
+ profilePtr->setDeviceAddress(remoteAddr);
+ profilePtr->connect();
}
}
return Error::Success;
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +3 -0
@@ 1,3 1,6 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
#pragma once
#include <Service/Service.hpp>
M module-bluetooth/README.md => module-bluetooth/README.md +8 -0
@@ 14,6 14,14 @@ It's meant to provide interface layer for service-bluetooth like that:
* `lib`
Libraries used with as little modifications as possible
+## Supported profiles
+* `A2DP`
+* `HSP`
+* `HFP` (Currently not supported)
+
+NOTE: Remote devices that do not support at least one of above profiles will not be added to list of devices during scan
+process.
+
## Events flowchart

<img src="./flowchart.svg">