M .gdbinit-1051 => .gdbinit-1051 +1 -1
@@ 13,4 13,4 @@ info threads
thread 2
tb main
b HardFault_Handler
-
+b _exit
M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +6 -4
@@ 226,6 226,8 @@ namespace app
});
connect(typeid(::message::bluetooth::RequestPasskey), [&](sys::Message *msg) {
+ auto m = dynamic_cast<::message::bluetooth::RequestPasskey *>(msg);
+ bluetoothSettingsModel->pinRequestor = m->getDevice();
switchWindow(gui::window::name::bluetooth_check_passkey);
return sys::MessageNone{};
});
@@ 396,10 398,10 @@ namespace app
windowsFactory.attach(gui::window::name::phone_name, [this](ApplicationCommon *app, const std::string &name) {
return std::make_unique<gui::PhoneNameWindow>(app, bluetoothSettingsModel);
});
- windowsFactory.attach(gui::window::name::bluetooth_check_passkey,
- [](ApplicationCommon *app, const std::string &name) {
- return std::make_unique<gui::BluetoothCheckPasskeyWindow>(app);
- });
+ windowsFactory.attach(
+ gui::window::name::bluetooth_check_passkey, [this](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique<gui::BluetoothCheckPasskeyWindow>(app, bluetoothSettingsModel);
+ });
// Network
windowsFactory.attach(gui::window::name::network, [](ApplicationCommon *app, const std::string &name) {
M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp => module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.cpp +2 -1
@@ 70,7 70,8 @@ void BluetoothSettingsModel::requestDeviceUnpair(const Devicei &device)
void BluetoothSettingsModel::responsePasskey(const std::string &passkey)
{
- service->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey), service::name::bluetooth);
+ service->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey, pinRequestor),
+ service::name::bluetooth);
}
void BluetoothSettingsModel::requestConnection(const Devicei &device)
M module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp => module-apps/application-settings/models/bluetooth/BluetoothSettingsModel.hpp +1 -0
@@ 40,6 40,7 @@ class BluetoothSettingsModel
auto isDeviceConnecting() -> bool;
auto getStatus() const -> const BluetoothStatus;
auto isDeviceListEmpty() const -> bool;
+ Devicei pinRequestor;
private:
std::vector<Devicei> devices{};
M module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.cpp => module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.cpp +5 -3
@@ 6,6 6,7 @@
#include <application-settings/widgets/SettingsStyle.hpp>
#include <application-settings/windows/WindowNames.hpp>
+#include <utility>
#include <widgets/text/Text.hpp>
namespace gui
@@ 17,10 18,11 @@ namespace gui
} // namespace
namespace passkey_style = style::settings::window::bluetooth::passkey;
- BluetoothCheckPasskeyWindow::BluetoothCheckPasskeyWindow(app::ApplicationCommon *app)
- : AppWindow(app, window::name::bluetooth_check_passkey)
+ BluetoothCheckPasskeyWindow::BluetoothCheckPasskeyWindow(
+ app::ApplicationCommon *app, std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel)
+ : AppWindow(app, window::name::bluetooth_check_passkey),
+ bluetoothSettingsModel(std::move(bluetoothSettingsModel))
{
- bluetoothSettingsModel = std::make_unique<BluetoothSettingsModel>(application);
buildInterface();
}
M module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.hpp => module-apps/application-settings/windows/bluetooth/BluetoothCheckPasskeyWindow.hpp +3 -2
@@ 13,7 13,8 @@ namespace gui
class BluetoothCheckPasskeyWindow : public AppWindow
{
public:
- explicit BluetoothCheckPasskeyWindow(app::ApplicationCommon *app);
+ BluetoothCheckPasskeyWindow(app::ApplicationCommon *app,
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel);
private:
void buildInterface() override;
@@ 22,6 23,6 @@ namespace gui
Image *image = nullptr;
Label *label = nullptr;
Text *text = nullptr;
- std::unique_ptr<BluetoothSettingsModel> bluetoothSettingsModel;
+ std::shared_ptr<BluetoothSettingsModel> bluetoothSettingsModel;
};
} // namespace gui
M module-bluetooth/Bluetooth/BtKeysStorage.cpp => module-bluetooth/Bluetooth/BtKeysStorage.cpp +0 -1
@@ 59,7 59,6 @@ namespace bluetooth
}
keys = std::move(keysJson[strings::keys].array_items());
- LOG_INFO("Imported keys: %d", static_cast<unsigned int>(keys.size()));
}
void KeyStorage::closeStorage()
A module-bluetooth/Bluetooth/Device.cpp => module-bluetooth/Bluetooth/Device.cpp +81 -0
@@ 0,0 1,81 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "Device.hpp"
+#include <btstack_util.h>
+
+Devicei::Devicei(std::string name) : Device(std::move(name))
+{
+ pageScanRepetitionMode = {};
+ clockOffset = {};
+ classOfDevice = {};
+ state = DEVICE_STATE::REMOTE_NAME_FAILURE;
+ deviceState = DeviceState::Unknown;
+ isPairingSSP = false;
+
+ memset(address, 0, sizeof(address));
+}
+
+Devicei::Devicei(bd_addr_t &address) : Devicei()
+{
+ setAddress(&address);
+}
+
+Devicei &Devicei::operator=(const Devicei &d)
+{
+ if (&d == this) {
+ return *this;
+ }
+ setAddress(&d.address);
+ setName(d.name.data());
+ pageScanRepetitionMode = d.pageScanRepetitionMode;
+ clockOffset = d.clockOffset;
+ classOfDevice = d.classOfDevice;
+ state = d.state;
+ deviceState = d.deviceState;
+ isPairingSSP = d.isPairingSSP;
+ return *this;
+}
+
+Devicei::Devicei(const Devicei &d) : Devicei(d.name.data())
+{
+ operator=(d);
+}
+
+Devicei &Devicei::operator=(Devicei &&d) noexcept
+{
+ setAddress(&d.address);
+ setName(d.name.data());
+ pageScanRepetitionMode = d.pageScanRepetitionMode;
+ clockOffset = d.clockOffset;
+ classOfDevice = d.classOfDevice;
+ state = d.state;
+ deviceState = d.deviceState;
+ isPairingSSP = d.isPairingSSP;
+ return *this;
+}
+
+Devicei::Devicei(Devicei &&d) noexcept : Devicei(d.name.data())
+{
+ operator=(d);
+}
+
+void Devicei::setAddress(bd_addr_t *addr)
+{
+ memcpy(&address, addr, sizeof address);
+}
+
+bool Devicei::operator==(const Devicei &cmpDevice) const
+{
+ return (strcmp(cmpDevice.name.data(), name.data()) == 0) && (bd_addr_cmp(cmpDevice.address, address) == 0);
+}
+
+bool Devicei::operator!=(const Devicei &cmpDevice) const
+{
+ return (strcmp(cmpDevice.name.data(), name.data()) != 0) || (bd_addr_cmp(cmpDevice.address, address) != 0);
+}
+
+auto Devicei::address_str() const -> const char *
+{
+ return bd_addr_to_str(address);
+}
M module-bluetooth/Bluetooth/Device.hpp => module-bluetooth/Bluetooth/Device.hpp +24 -32
@@ 5,7 5,6 @@
#include <array>
#include <cstring>
#include <module-bluetooth/lib/btstack/src/bluetooth.h>
-#include <btstack_util.h>
#include <string>
#include <utility>
@@ 17,20 16,25 @@ struct Device
static constexpr auto NameBufferSize = 240;
explicit Device(std::string name = "")
{
+ setName(name);
+ }
+ virtual ~Device() = default;
+ std::array<char, NameBufferSize> name;
+ void setName(const std::string &name)
+ {
if (name.size() > NameBufferSize) {
throw std::runtime_error("Requested name is bigger than buffer size");
}
strcpy(this->name.data(), name.c_str());
}
- virtual ~Device() = default;
- std::array<char, NameBufferSize> name;
};
enum DEVICE_STATE
{
REMOTE_NAME_REQUEST,
REMOTE_NAME_INQUIRED,
- REMOTE_NAME_FETCHED
+ REMOTE_NAME_FETCHED,
+ REMOTE_NAME_FAILURE,
};
namespace TYPE_OF_SERVICE
@@ 96,37 100,25 @@ enum class DeviceState
struct Devicei : public Device
{
public:
- bd_addr_t address;
- uint8_t pageScanRepetitionMode;
- uint16_t clockOffset;
- uint32_t classOfDevice; ///> Class of Device/Service
+ mutable bd_addr_t address{};
+ uint8_t pageScanRepetitionMode{};
+ uint16_t clockOffset{};
+ uint32_t classOfDevice{}; ///> Class of Device/Service
DEVICE_STATE state;
DeviceState deviceState;
-
- explicit Devicei(std::string name = "") : Device(std::move(name))
- {
- memset(address, 0, sizeof(address));
- }
+ bool isPairingSSP = false;
+
+ explicit Devicei(std::string name = "");
+ explicit Devicei(bd_addr_t &address);
+ Devicei &operator=(const Devicei &d);
+ Devicei(const Devicei &d);
+ Devicei &operator=(Devicei &&d) noexcept;
+ Devicei(Devicei &&d) noexcept;
~Devicei() override = default;
- void setAddress(bd_addr_t *addr)
- {
- memcpy(&address, addr, sizeof address);
- }
-
- inline bool operator==(const Devicei &cmpDevice) const
- {
- return (strcmp(cmpDevice.name.data(), name.data()) == 0) && (bd_addr_cmp(cmpDevice.address, address) == 0);
- }
-
- inline bool operator!=(const Devicei &cmpDevice) const
- {
- return (strcmp(cmpDevice.name.data(), name.data()) != 0) || (bd_addr_cmp(cmpDevice.address, address) != 0);
- }
-
- auto address_str() const -> const char *
- {
- return bd_addr_to_str(address);
- }
+ void setAddress(bd_addr_t *addr);
+ bool operator==(const Devicei &cmpDevice) const;
+ bool operator!=(const Devicei &cmpDevice) const;
+ auto address_str() const -> const char *;
};
struct DeviceMetadata_t
A module-bluetooth/Bluetooth/error_bluetooth.cpp => module-bluetooth/Bluetooth/error_bluetooth.cpp +142 -0
@@ 0,0 1,142 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "error_bluetooth.hpp"
+#include <module-bluetooth/lib/btstack/src/bluetooth.h>
+
+namespace bluetooth
+{
+ const char *error_cstr(int err)
+ {
+ switch (err) {
+ case ERROR_CODE_SUCCESS:
+ return "ERROR_CODE_SUCCESS";
+ case ERROR_CODE_UNKNOWN_HCI_COMMAND:
+ return "ERROR_CODE_UNKNOWN_HCI_COMMAND";
+ case ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER:
+ return "ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER";
+ case ERROR_CODE_HARDWARE_FAILURE:
+ return "ERROR_CODE_HARDWARE_FAILURE";
+ case ERROR_CODE_PAGE_TIMEOUT:
+ return "ERROR_CODE_PAGE_TIMEOUT";
+ case ERROR_CODE_AUTHENTICATION_FAILURE:
+ return "ERROR_CODE_AUTHENTICATION_FAILURE";
+ case ERROR_CODE_PIN_OR_KEY_MISSING:
+ return "ERROR_CODE_PIN_OR_KEY_MISSING";
+ case ERROR_CODE_MEMORY_CAPACITY_EXCEEDED:
+ return "ERROR_CODE_MEMORY_CAPACITY_EXCEEDED";
+ case ERROR_CODE_CONNECTION_TIMEOUT:
+ return "ERROR_CODE_CONNECTION_TIMEOUT";
+ case ERROR_CODE_CONNECTION_LIMIT_EXCEEDED:
+ return "ERROR_CODE_CONNECTION_LIMIT_EXCEEDED";
+ case ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED:
+ return "ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED";
+ case ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS:
+ return "ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS";
+ case ERROR_CODE_COMMAND_DISALLOWED:
+ return "ERROR_CODE_COMMAND_DISALLOWED";
+ case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES:
+ return "ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES";
+ case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS:
+ return "ERROR_CODE_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS";
+ case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR:
+ return "ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR";
+ case ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED:
+ return "ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED";
+ case ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE:
+ return "ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE";
+ case ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS:
+ return "ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS";
+ case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION:
+ return "ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION";
+ case ERROR_CODE_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES:
+ return "ERROR_CODE_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES";
+ case ERROR_CODE_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF:
+ return "ERROR_CODE_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF";
+ case ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST:
+ return "ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST";
+ case ERROR_CODE_REPEATED_ATTEMPTS:
+ return "ERROR_CODE_REPEATED_ATTEMPTS";
+ case ERROR_CODE_PAIRING_NOT_ALLOWED:
+ return "ERROR_CODE_PAIRING_NOT_ALLOWED";
+ case ERROR_CODE_UNKNOWN_LMP_PDU:
+ return "ERROR_CODE_UNKNOWN_LMP_PDU";
+ case ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE_UNSUPPORTED_LMP_FEATURE:
+ return "ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE_UNSUPPORTED_LMP_FEATURE";
+ case ERROR_CODE_SCO_OFFSET_REJECTED:
+ return "ERROR_CODE_SCO_OFFSET_REJECTED";
+ case ERROR_CODE_SCO_INTERVAL_REJECTED:
+ return "ERROR_CODE_SCO_INTERVAL_REJECTED";
+ case ERROR_CODE_SCO_AIR_MODE_REJECTED:
+ return "ERROR_CODE_SCO_AIR_MODE_REJECTED";
+ case ERROR_CODE_INVALID_LMP_PARAMETERS_INVALID_LL_PARAMETERS:
+ return "ERROR_CODE_INVALID_LMP_PARAMETERS_INVALID_LL_PARAMETERS";
+ case ERROR_CODE_UNSPECIFIED_ERROR:
+ return "ERROR_CODE_UNSPECIFIED_ERROR";
+ case ERROR_CODE_UNSUPPORTED_LMP_PARAMETER_VALUE_UNSUPPORTED_LL_PARAMETER_VALUE:
+ return "ERROR_CODE_UNSUPPORTED_LMP_PARAMETER_VALUE_UNSUPPORTED_LL_PARAMETER_VALUE";
+ case ERROR_CODE_ROLE_CHANGE_NOT_ALLOWED:
+ return "ERROR_CODE_ROLE_CHANGE_NOT_ALLOWED";
+ case ERROR_CODE_LMP_RESPONSE_TIMEOUT_LL_RESPONSE_TIMEOUT:
+ return "ERROR_CODE_LMP_RESPONSE_TIMEOUT_LL_RESPONSE_TIMEOUT";
+ case ERROR_CODE_LMP_ERROR_TRANSACTION_COLLISION:
+ return "ERROR_CODE_LMP_ERROR_TRANSACTION_COLLISION";
+ case ERROR_CODE_LMP_PDU_NOT_ALLOWED:
+ return "ERROR_CODE_LMP_PDU_NOT_ALLOWED";
+ case ERROR_CODE_ENCRYPTION_MODE_NOT_ACCEPTABLE:
+ return "ERROR_CODE_ENCRYPTION_MODE_NOT_ACCEPTABLE";
+ case ERROR_CODE_LINK_KEY_CANNOT_BE_CHANGED:
+ return "ERROR_CODE_LINK_KEY_CANNOT_BE_CHANGED";
+ case ERROR_CODE_REQUESTED_QOS_NOT_SUPPORTED:
+ return "ERROR_CODE_REQUESTED_QOS_NOT_SUPPORTED";
+ case ERROR_CODE_INSTANT_PASSED:
+ return "ERROR_CODE_INSTANT_PASSED";
+ case ERROR_CODE_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED:
+ return "ERROR_CODE_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED";
+ case ERROR_CODE_DIFFERENT_TRANSACTION_COLLISION:
+ return "ERROR_CODE_DIFFERENT_TRANSACTION_COLLISION";
+ case ERROR_CODE_RESERVED:
+ return "ERROR_CODE_RESERVED";
+ case ERROR_CODE_QOS_UNACCEPTABLE_PARAMETER:
+ return "ERROR_CODE_QOS_UNACCEPTABLE_PARAMETER";
+ case ERROR_CODE_QOS_REJECTED:
+ return "ERROR_CODE_QOS_REJECTED";
+ case ERROR_CODE_CHANNEL_CLASSIFICATION_NOT_SUPPORTED:
+ return "ERROR_CODE_CHANNEL_CLASSIFICATION_NOT_SUPPORTED";
+ case ERROR_CODE_INSUFFICIENT_SECURITY:
+ return "ERROR_CODE_INSUFFICIENT_SECURITY";
+ case ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE:
+ return "ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE";
+ case ERROR_CODE_ROLE_SWITCH_PENDING:
+ return "ERROR_CODE_ROLE_SWITCH_PENDING";
+ case ERROR_CODE_RESERVED_SLOT_VIOLATION:
+ return "ERROR_CODE_RESERVED_SLOT_VIOLATION";
+ case ERROR_CODE_ROLE_SWITCH_FAILED:
+ return "ERROR_CODE_ROLE_SWITCH_FAILED";
+ case ERROR_CODE_EXTENDED_INQUIRY_RESPONSE_TOO_LARGE:
+ return "ERROR_CODE_EXTENDED_INQUIRY_RESPONSE_TOO_LARGE";
+ case ERROR_CODE_SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST:
+ return "ERROR_CODE_SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST";
+ case ERROR_CODE_HOST_BUSY_PAIRING:
+ return "ERROR_CODE_HOST_BUSY_PAIRING";
+ case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND:
+ return "ERROR_CODE_CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND";
+ case ERROR_CODE_CONTROLLER_BUSY:
+ return "ERROR_CODE_CONTROLLER_BUSY";
+ case ERROR_CODE_UNACCEPTABLE_CONNECTION_PARAMETERS:
+ return "ERROR_CODE_UNACCEPTABLE_CONNECTION_PARAMETERS";
+ case ERROR_CODE_DIRECTED_ADVERTISING_TIMEOUT:
+ return "ERROR_CODE_DIRECTED_ADVERTISING_TIMEOUT";
+ case ERROR_CODE_CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE:
+ return "ERROR_CODE_CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE";
+ case ERROR_CODE_CONNECTION_FAILED_TO_BE_ESTABLISHED:
+ return "ERROR_CODE_CONNECTION_FAILED_TO_BE_ESTABLISHED";
+ case ERROR_CODE_MAC_CONNECTION_FAILED:
+ return "ERROR_CODE_MAC_CONNECTION_FAILED";
+ case ERROR_CODE_COARSE_CLOCK_ADJUSTMENT_REJECTED_BUT_WILL_TRY_TO_ADJUST_USING_CLOCK_DRAGGING:
+ return "ERROR_CODE_COARSE_CLOCK_ADJUSTMENT_REJECTED_BUT_WILL_TRY_TO_ADJUST_USING_CLOCK_DRAGGING";
+ default:
+ return "ERROR_CODE_UNDEFINED";
+ }
+ }
+} // namespace bluetooth
A module-bluetooth/Bluetooth/error_bluetooth.hpp => module-bluetooth/Bluetooth/error_bluetooth.hpp +8 -0
@@ 0,0 1,8 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/// all these are taken from the defines to have textual representation
+namespace bluetooth
+{
+ const char *error_cstr(int err);
+}
M module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp +3 -0
@@ 82,6 82,9 @@ namespace bluetooth
hci_set_link_key_db(bluetooth::KeyStorage::getKeyStorage());
hci_event_callback_registration.callback = &hci_packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
+
+ gap_ssp_set_io_capability(SSP_IO_CAPABILITY_KEYBOARD_ONLY);
+ gap_ssp_set_auto_accept(false);
LOG_DEBUG("BT worker run success");
return Error::Success;
}
A module-bluetooth/Bluetooth/interface/profiles/GAP/Devices.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/Devices.cpp +64 -0
@@ 0,0 1,64 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "Devices.hpp"
+#include <btstack_util.h>
+
+namespace bluetooth::gap
+{
+ auto Devices::getList() -> std::vector<Devicei>
+ {
+ return {devices.begin(), devices.end()};
+ }
+
+ Devices::iter Devices::find(bd_addr_t &addr)
+ {
+ return std::find_if(std::begin(devices), std::end(devices), [addr](const Devicei &device) {
+ return bd_addr_cmp(addr, device.address) == 0;
+ });
+ }
+
+ Devices::iter Devices::find(DEVICE_STATE st)
+ {
+ return std::find_if(
+ std::begin(devices), std::end(devices), [st](const Devicei &device) { return st == device.state; });
+ }
+
+ void Devices::for_each(const std::function<void(Devicei &)> &f)
+ {
+ if (not f) {
+ return;
+ }
+ for (auto &el : devices) {
+ f(el);
+ }
+ }
+
+ Devices::iter Devices::end()
+ {
+ return std::end(devices);
+ }
+
+ Devices::iter Devices::put(Devicei &&dev)
+ {
+ if (const auto &it = find(dev.address); it != end()) {
+ devices.erase(it);
+ }
+ devices.emplace_back(dev);
+ return std::prev(devices.end());
+ }
+
+ Devices::iter Devices::put(bd_addr_t &addr)
+ {
+ if (const auto &it = find(addr); it != end()) {
+ devices.erase(it);
+ }
+ devices.emplace_back(Devicei(addr));
+ return std::prev(devices.end());
+ }
+
+ void Devices::clear()
+ {
+ devices.clear();
+ }
+} // namespace bluetooth::gap
A module-bluetooth/Bluetooth/interface/profiles/GAP/Devices.hpp => module-bluetooth/Bluetooth/interface/profiles/GAP/Devices.hpp +30 -0
@@ 0,0 1,30 @@
+// 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 <Bluetooth/Device.hpp>
+#include <list>
+#include <vector>
+#include <functional>
+
+namespace bluetooth::gap
+{
+ /// class to store and get devices in GAP operations
+ class Devices
+ {
+ std::list<Devicei> devices;
+
+ public:
+ using iter = decltype(devices)::iterator;
+ iter find(bd_addr_t &addr);
+ iter find(DEVICE_STATE st);
+ void for_each(const std::function<void(Devicei &)> &f);
+ iter end();
+ // adds element, if element already on list - remove and add anew
+ iter put(Devicei &&dev);
+ // same as above
+ iter put(bd_addr_t &addr);
+ void clear();
+ auto getList() -> std::vector<Devicei>;
+ };
+} // namespace bluetooth::gap
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp +190 -89
@@ 2,12 2,17 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "GAP.hpp"
+#include "Devices.hpp"
+#include "GAP/used_events.hpp"
-#include <log/log.hpp>
+#include <Bluetooth/error_bluetooth.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
#include <service-bluetooth/messages/ResponseVisibleDevices.hpp>
#include <service-bluetooth/messages/Unpair.hpp>
#include <service-bluetooth/messages/Passkey.hpp>
+#include <service-bluetooth/Constants.hpp>
+#include <log/log.hpp>
+#include <memory>
extern "C"
{
#include "btstack.h"
@@ 15,11 20,27 @@ extern "C"
};
namespace bluetooth
{
- Devicei GAP::currentlyProccesedDevice;
sys::Service *GAP::ownerService = nullptr;
- std::vector<Devicei> GAP::devices;
btstack_packet_callback_registration_t GAP::cb_handler;
- ScanState GAP::state;
+ stack::state GAP::state;
+
+ namespace gap
+ {
+ enum class state
+ {
+ scan_off = 0,
+ scan_on,
+ } static state;
+ }
+
+ static gap::Devices &devices()
+ {
+ static std::unique_ptr<gap::Devices> dev;
+ if (not dev) {
+ dev = std::make_unique<gap::Devices>();
+ }
+ return *dev;
+ };
auto GAP::registerScan() -> Error
{
@@ 34,11 55,15 @@ namespace bluetooth
auto GAP::scan() -> Error
{
if (hci_get_state() == HCI_STATE_WORKING) {
- devices.clear();
+ if (gap::state == gap::state::scan_on) {
+ stopScan();
+ }
+ devices().clear();
if (auto ret = startScan(); ret != 0) {
- LOG_ERROR("Start scan error!: 0x%X", ret);
+ LOG_ERROR("Start scan error!: 0x%02X - %s", ret, error_cstr(ret));
return Error(Error::LibraryError, ret);
}
+ gap::state = gap::state::scan_on;
}
else {
return Error(Error::NotReady);
@@ 48,6 73,7 @@ namespace bluetooth
void GAP::stopScan()
{
+ gap::state = gap::state::scan_off;
gap_inquiry_force_stop();
LOG_INFO("Scan stopped!");
}
@@ 61,30 87,20 @@ namespace bluetooth
auto GAP::pair(Devicei device, std::uint8_t protectionLevel) -> bool
{
if (hci_get_state() == HCI_STATE_WORKING) {
- auto devIndex = getDeviceIndexForAddress(devices, device.address);
- currentlyProccesedDevice = devices.at(devIndex);
-
+ auto it = devices().find(device.address);
+ if (it == devices().end()) {
+ LOG_ERROR("device not found: %s", device.address_str());
+ return false;
+ }
return gap_dedicated_bonding(device.address, protectionLevel) == 0;
}
return false;
}
- auto GAP::getDeviceIndexForAddress(const std::vector<Devicei> &devs, const bd_addr_t addr) -> int
- {
- auto result = std::find_if(std::begin(devs), std::end(devs), [addr](const Devicei &device) {
- return bd_addr_cmp(addr, device.address) == 0;
- });
-
- if (result == std::end(devs)) {
- return -1;
- }
-
- return std::distance(std::begin(devs), result);
- }
void GAP::sendDevices()
{
- auto msg = std::make_shared<message::bluetooth::ResponseVisibleDevices>(devices);
+ auto msg = std::make_shared<message::bluetooth::ResponseVisibleDevices>(devices().getList());
ownerService->bus.sendMulticast(std::move(msg), sys::BusChannel::BluetoothNotifications);
}
@@ 94,48 110,28 @@ namespace bluetooth
return gap_inquiry_start(inquiryIntervalSeconds);
}
- auto GAP::remoteNameToFetch() -> bool
- {
- auto result = std::find_if(std::begin(devices), std::end(devices), [](Devicei &device) {
- return device.state == REMOTE_NAME_REQUEST;
- });
-
- return result != std::end(devices);
- }
-
- void GAP::fetchRemoteName()
- {
- for (auto &device : bluetooth::GAP::devices) {
- if (device.state == REMOTE_NAME_REQUEST) {
- device.state = REMOTE_NAME_INQUIRED;
- LOG_INFO("Get remote name...");
- gap_remote_name_request(device.address, device.pageScanRepetitionMode, device.clockOffset | 0x8000);
- return;
- }
- }
- }
-
void GAP::continueScanning()
{
- if (remoteNameToFetch()) {
- fetchRemoteName();
+ if (const auto &it = devices().find(REMOTE_NAME_REQUEST); it != devices().end()) {
+ LOG_INFO("Get remote name for %s", it->name.data());
+ it->state = REMOTE_NAME_INQUIRED;
+ gap_remote_name_request(it->address, it->pageScanRepetitionMode, it->clockOffset | 0x8000);
return;
}
- startScan();
+ if (gap::state == gap::state::scan_on) {
+ startScan();
+ }
}
+
auto GAP::updateDeviceName(std::uint8_t *packet, bd_addr_t &addr) -> bool
{
reverse_bd_addr(&packet[3], addr);
- auto index = getDeviceIndexForAddress(devices, addr);
- if (index >= 0) {
- if (packet[2] == 0) {
- devices[index].state = REMOTE_NAME_FETCHED;
- strcpy(devices[index].name.data(), reinterpret_cast<const char *>(&packet[9]));
- return true;
- }
- else {
- LOG_INFO("Failed to get name: page timeout");
+ if (auto it = devices().find(addr); it != devices().end()) {
+ it->state = packet[2] ? REMOTE_NAME_FAILURE : REMOTE_NAME_FETCHED;
+ if (it->state != REMOTE_NAME_FAILURE) {
+ strcpy(it->name.data(), reinterpret_cast<const char *>(&packet[9]));
}
+ return it->state == REMOTE_NAME_FETCHED;
}
return false;
}
@@ 148,6 144,7 @@ namespace bluetooth
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 ");
+ LOG_INFO("with address: %s, ", device.address_str());
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);
@@ 171,14 168,15 @@ namespace bluetooth
strcpy(device.name.data(), bd_addr_to_str(devAddr));
}
- devices.emplace_back(std::move(device));
+ devices().put(std::move(device));
}
- void GAP::processInquiryResult(std::uint8_t *packet, bd_addr_t &addr)
+ void GAP::processInquiryResult(std::uint8_t *packet)
{
+ bd_addr_t addr;
gap_event_inquiry_result_get_bd_addr(packet, addr);
- auto index = getDeviceIndexForAddress(devices, addr);
- if (index >= 0) {
+ auto it = devices().find(addr);
+ if (it != devices().end()) {
return; // already in our list
}
uint32_t classOfDevice = gap_event_inquiry_result_get_class_of_device(packet);
@@ 194,12 192,11 @@ namespace bluetooth
}
void GAP::processInquiryComplete()
{
- for (auto &device : devices) {
- // retry remote name request
- if (device.state == REMOTE_NAME_INQUIRED) {
- device.state = REMOTE_NAME_REQUEST;
+ devices().for_each([](Devicei &d) {
+ if (d.state == REMOTE_NAME_INQUIRED) {
+ d.state = REMOTE_NAME_REQUEST;
}
- }
+ });
continueScanning();
}
void GAP::processNameRequestComplete(std::uint8_t *packet, bd_addr_t &addr)
@@ 209,13 206,15 @@ namespace bluetooth
}
continueScanning();
}
+
void GAP::processDedicatedBondingCompleted(std::uint8_t *packet, bd_addr_t &addr)
{
auto result = packet[2];
-
- auto msg = std::make_shared<BluetoothPairResultMessage>(currentlyProccesedDevice, result == 0u);
- ownerService->bus.sendUnicast(std::move(msg), "ServiceBluetooth");
+ auto it = devices().find(addr);
+ auto msg = std::make_shared<BluetoothPairResultMessage>(it != devices().end() ? *it : Devicei(), result == 0u);
+ ownerService->bus.sendUnicast(std::move(msg), service::name::bluetooth);
}
+
/* @text In ACTIVE, the following events are processed:
* - GAP Inquiry result event: BTstack provides a unified inquiry result that contain
* Class of Device (CoD), page scan mode, clock offset. RSSI and name (from EIR) are optional.
@@ 225,71 224,136 @@ namespace bluetooth
* - Remote name request complete event: the remote name is stored in the table and the
* state is updated to REMOTE_NAME_FETCHED. The query of remote names is continued.
*/
- void GAP::activeStateHandler(std::uint8_t eventType, std::uint8_t *packet, bd_addr_t &addr)
+ void GAP::activeStateHandler(std::uint8_t eventType, std::uint8_t *packet, std::uint16_t size)
{
+ if (not(eventType == HCI_EVENT_TRANSPORT_PACKET_SENT || eventType == HCI_EVENT_COMMAND_STATUS ||
+ eventType == HCI_EVENT_INQUIRY_COMPLETE || eventType == HCI_EVENT_COMMAND_COMPLETE)) {
+ LOG_DEBUG("event: 0x%02X - %s - size: %" PRIu16, eventType, evt_cstr(eventType), size);
+ }
switch (eventType) {
+ case HCI_EVENT_TRANSPORT_PACKET_SENT:
+ break;
+ case HCI_EVENT_EXTENDED_INQUIRY_RESPONSE:
+ break;
+ case GAP_EVENT_PAIRING_STARTED:
+ break;
+
+ case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
+ break;
+
+ case HCI_EVENT_USER_CONFIRMATION_REQUEST: {
+ bd_addr_t addr;
+ hci_event_user_confirmation_request_get_bd_addr(packet, addr);
+ hci_connection_t *conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL);
+ hci_send_cmd(&hci_user_confirmation_request_reply, &conn->address);
+ } break;
+
+ case HCI_EVENT_PIN_CODE_REQUEST: {
+ bd_addr_t addr;
+ hci_event_pin_code_request_get_bd_addr(packet, addr);
+ auto it = devices().find(addr);
+ if (it == devices().end()) {
+ gap_remote_name_request(addr, PAGE_SCAN_MODE_STANDARD, 0);
+ it = devices().put(addr);
+ }
+ it->isPairingSSP = false;
+
+ auto msg = std::make_shared<::message::bluetooth::RequestPasskey>(*it);
+ ownerService->bus.sendMulticast(std::move(msg), sys::BusChannel::BluetoothNotifications);
+ } break;
+
+ case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES_COMPLETE: {
+ uint16_t handle = little_endian_read_16(packet, 3);
+ hci_connection_t *conn = hci_connection_for_handle(handle);
+ auto yes = gap_ssp_supported_on_both_sides(conn->con_handle);
+ auto it = devices().find(conn->address);
+ if (it == devices().end()) {
+ return;
+ }
+ it->isPairingSSP = yes;
+ } break;
case GAP_EVENT_INQUIRY_RESULT:
- processInquiryResult(packet, addr);
+ processInquiryResult(packet);
break;
case GAP_EVENT_INQUIRY_COMPLETE:
processInquiryComplete();
break;
-
- case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
+ case HCI_EVENT_USER_PASSKEY_REQUEST: {
+ bd_addr_t addr;
+ hci_event_user_passkey_request_get_bd_addr(packet, addr);
+ auto it = devices().find(addr);
+ if (it == devices().end()) {
+ gap_remote_name_request(addr, PAGE_SCAN_MODE_STANDARD, 0);
+ it = devices().put(addr);
+ }
+ it->isPairingSSP = true;
+ ownerService->bus.sendMulticast(std::make_shared<::message::bluetooth::RequestPasskey>(*it),
+ sys::BusChannel::BluetoothNotifications);
+ } break;
+ case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: {
+ bd_addr_t addr;
+ hci_event_remote_name_request_complete_get_bd_addr(packet, addr);
processNameRequestComplete(packet, addr);
- break;
+ } break;
case GAP_EVENT_DEDICATED_BONDING_COMPLETED:
+ bd_addr_t addr;
+ reverse_bd_addr(&packet[3], addr);
processDedicatedBondingCompleted(packet, addr);
break;
+ case HCI_EVENT_SIMPLE_PAIRING_COMPLETE: {
+ bd_addr_t addr;
+ hci_event_simple_pairing_complete_get_bd_addr(packet, addr);
+ processSimplePairingCompleted(packet, addr);
+ } break;
+ case GAP_EVENT_PAIRING_COMPLETE:
+ LOG_DEBUG("status: 0x%02X", packet[10]);
+ break;
default:
break;
}
}
+
void GAP::initStateHandler(std::uint8_t eventType, std::uint8_t *packet)
{
if (eventType == BTSTACK_EVENT_STATE) {
if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING) {
- state = ScanState::active;
+ state = stack::state::working;
}
}
}
+
void GAP::packetHandler(std::uint8_t packet_type, std::uint16_t channel, std::uint8_t *packet, std::uint16_t size)
{
- bd_addr_t addr;
if (packet_type != HCI_EVENT_PACKET) {
return;
}
- if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST) {
- bd_addr_t address;
- LOG_DEBUG("PIN code request!");
- hci_event_pin_code_request_get_bd_addr(packet, address);
- auto msg = std::make_shared<::message::bluetooth::RequestPasskey>();
- ownerService->bus.sendMulticast(std::move(msg), sys::BusChannel::BluetoothNotifications);
- }
const auto eventType = hci_event_packet_get_type(packet);
switch (state) {
- case ScanState::init:
+ case stack::state::init:
initStateHandler(eventType, packet);
break;
- case ScanState::active:
- activeStateHandler(eventType, packet, addr);
+ case stack::state::working:
+ activeStateHandler(eventType, packet, size);
break;
default:
break;
}
}
+
GAP::GAP(sys::Service *owner)
{
ownerService = owner;
- state = ScanState::init;
+ state = stack::state::init;
}
- auto GAP::getDevicesList() -> const std::vector<Devicei> &
+
+ auto GAP::getDevicesList() -> std::vector<Devicei>
{
- return devices;
+ return devices().getList();
}
+
auto GAP::unpair(Devicei device) -> bool
{
LOG_INFO("Unpairing device");
@@ 300,8 364,45 @@ namespace bluetooth
sys::BusChannel::BluetoothNotifications);
return true;
}
- void GAP::respondPinCode(const std::string &pin)
+
+ void GAP::respondPinCode(const std::string &pin, Devicei d)
+ {
+ LOG_DEBUG("pairing response for device: %s pin: %s is SSP? %s",
+ d.address_str(),
+ pin.c_str(),
+ d.isPairingSSP ? "yes" : "no");
+ if (!d.isPairingSSP) {
+ gap_pin_code_response(d.address, pin.c_str());
+ return;
+ }
+
+ unsigned int passkey = 0;
+ try {
+ passkey = stoi(pin);
+ LOG_DEBUG("Sending %06u as a passkey", passkey);
+ }
+ catch (const std::invalid_argument &e) {
+ LOG_ERROR("STOI error: %s", e.what());
+ }
+
+ gap_ssp_passkey_response(d.address, passkey);
+ }
+
+ void GAP::processSimplePairingCompleted(std::uint8_t *packet, bd_addr_t &addr)
{
- gap_pin_code_response(currentlyProccesedDevice.address, pin.c_str());
+ auto status = hci_event_simple_pairing_complete_get_status(packet);
+ auto it = devices().find(addr);
+ LOG_INFO("HCI_EVENT_SIMPLE_PAIRING_COMPLETE: 0x%02X - %s - device found: %s : address: %s",
+ status,
+ error_cstr(status),
+ it != devices().end() ? "found" : "fail",
+ bd_addr_to_str(addr));
+ if (it == devices().end()) {
+ auto msg = std::make_shared<BluetoothPairResultMessage>(Devicei(), false);
+ ownerService->bus.sendUnicast(std::move(msg), service::name::bluetooth);
+ return;
+ }
+ auto msg = std::make_shared<BluetoothPairResultMessage>(*it, status == ERROR_CODE_SUCCESS);
+ ownerService->bus.sendUnicast(std::move(msg), service::name::bluetooth);
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp +18 -13
@@ 12,35 12,40 @@ extern "C"
}
namespace bluetooth
{
- enum ScanState
+ namespace stack
{
- init,
- active,
- done
- };
+ enum state
+ {
+ off,
+ init,
+ working,
+ halting,
+ sleeping,
+ falling_asleep
+ };
+ }
+
class GAP
{
- static std::vector<Devicei> devices;
static sys::Service *ownerService;
static btstack_packet_callback_registration_t cb_handler;
static constexpr auto inquiryIntervalSeconds = 5;
- static ScanState state;
+ static stack::state state;
static void sendDevices();
static auto startScan() -> int;
- static auto remoteNameToFetch() -> bool;
- static void fetchRemoteName();
static void continueScanning();
static auto updateDeviceName(std::uint8_t *packet, bd_addr_t &addr) -> bool;
static void addNewDevice(std::uint8_t *packet, bd_addr_t &addr);
- static void activeStateHandler(std::uint8_t eventType, std::uint8_t *packet, bd_addr_t &addr);
+ static void activeStateHandler(std::uint8_t eventType, std::uint8_t *packet, std::uint16_t size);
static void packetHandler(std::uint8_t packet_type,
std::uint16_t channel,
std::uint8_t *packet,
std::uint16_t size);
- static void processInquiryResult(std::uint8_t *packet, bd_addr_t &addr);
+ static void processInquiryResult(std::uint8_t *packet);
static void processInquiryComplete();
static void processNameRequestComplete(std::uint8_t *packet, bd_addr_t &addr);
static void processDedicatedBondingCompleted(std::uint8_t *packet, bd_addr_t &addr);
+ static void processSimplePairingCompleted(std::uint8_t *packet, bd_addr_t &addr);
static void initStateHandler(std::uint8_t eventType, std::uint8_t *packet);
static auto getDeviceIndexForAddress(const std::vector<Devicei> &devs, const bd_addr_t addr) -> int;
@@ 52,8 57,8 @@ namespace bluetooth
void setVisibility(bool visibility);
auto pair(Devicei device, std::uint8_t protectionLevel = 0) -> bool;
auto unpair(Devicei device) -> bool;
- static auto getDevicesList() -> const std::vector<Devicei> &;
- static void respondPinCode(const std::string &pin);
+ static auto getDevicesList() -> std::vector<Devicei>;
+ static void respondPinCode(const std::string &pin, Devicei d);
static Devicei currentlyProccesedDevice;
explicit GAP(sys::Service *owner);
A module-bluetooth/Bluetooth/interface/profiles/GAP/used_events.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/used_events.cpp +57 -0
@@ 0,0 1,57 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "used_events.hpp"
+#include <module-bluetooth/lib/btstack/src/btstack_event.h>
+
+namespace bluetooth
+{
+ const char *evt_cstr(int evt)
+ {
+ switch (evt) {
+ // ----------
+ // HCI EVENTS
+ // ----------
+ case HCI_EVENT_TRANSPORT_PACKET_SENT:
+ return "HCI_EVENT_TRANSPORT_PACKET_SENT";
+ case HCI_EVENT_COMMAND_COMPLETE:
+ return "HCI_EVENT_COMMAND_COMPLETE";
+ case HCI_EVENT_COMMAND_STATUS:
+ return "HCI_EVENT_COMMAND_STATUS";
+ case HCI_EVENT_INQUIRY_COMPLETE:
+ return "HCI_EVENT_INQUIRY_COMPLETE";
+ case HCI_EVENT_EXTENDED_INQUIRY_RESPONSE:
+ return "HCI_EVENT_EXTENDED_INQUIRY_RESPONSE";
+ case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
+ return "HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE";
+ case HCI_EVENT_USER_CONFIRMATION_REQUEST:
+ return "HCI_EVENT_USER_CONFIRMATION_REQUEST";
+ case HCI_EVENT_PIN_CODE_REQUEST:
+ return "HCI_EVENT_PIN_CODE_REQUEST";
+ case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES_COMPLETE:
+ return "HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES_COMPLETE";
+ case HCI_EVENT_USER_PASSKEY_REQUEST:
+ return "HCI_EVENT_USER_PASSKEY_REQUEST";
+ case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
+ return "HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE";
+ case HCI_EVENT_SIMPLE_PAIRING_COMPLETE:
+ return "HCI_EVENT_SIMPLE_PAIRING_COMPLETE";
+
+ // ----------
+ // GAP EVENTS
+ // ----------
+ case GAP_EVENT_PAIRING_COMPLETE:
+ return "GAP_EVENT_PAIRING_COMPLETE";
+ case GAP_EVENT_DEDICATED_BONDING_COMPLETED:
+ return "GAP_EVENT_DEDICATED_BONDING_COMPLETED";
+ case GAP_EVENT_INQUIRY_RESULT:
+ return "GAP_EVENT_INQUIRY_RESULT";
+ case GAP_EVENT_INQUIRY_COMPLETE:
+ return "GAP_EVENT_INQUIRY_COMPLETE";
+ case GAP_EVENT_PAIRING_STARTED:
+ return "GAP_EVENT_PAIRING_STARTED";
+ default:
+ return "EVENT_UNKNOWN";
+ }
+ }
+} // namespace bluetooth
A module-bluetooth/Bluetooth/interface/profiles/GAP/used_events.hpp => module-bluetooth/Bluetooth/interface/profiles/GAP/used_events.hpp +9 -0
@@ 0,0 1,9 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+namespace bluetooth
+{
+ const char *evt_cstr(int evt);
+}
M module-bluetooth/CMakeLists.txt => module-bluetooth/CMakeLists.txt +4 -0
@@ 10,12 10,16 @@ module_is_test_entity()
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/audio/BluetoothAudioDevice.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/BluetoothWorker.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/error_bluetooth.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/WorkerController.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/CommandHandler.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/Device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/glucode/BluetoothRunLoop.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/BluetoothDriverImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/BtKeysStorage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/GAP/GAP.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/GAP/Devices.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/GAP/used_events.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/A2DP/A2DP.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/A2DP/AVRCP.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/A2DP/AVDTP.cpp
M module-bluetooth/tests/CMakeLists.txt => module-bluetooth/tests/CMakeLists.txt +1 -0
@@ 5,6 5,7 @@ add_catch2_executable(
tests-main.cpp
tests-StatefulController.cpp
tests-BluetoothDevicesModel.cpp
+ tests-Devicei.cpp
LIBS
module-sys
module-bluetooth
A module-bluetooth/tests/test-Devicei.cpp => module-bluetooth/tests/test-Devicei.cpp +14 -0
@@ 0,0 1,14 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+TEST_CASE("Given StatefulController when process command successfully then turned on")
+{
+ auto driver = std::make_unique<DriverMock>();
+ auto processor = std::make_unique<HandlerMock>();
+ StatefulController controller{std::move(driver), std::move(processor), InitializerMock};
+ controller.turnOn();
+ REQUIRE(controller.isOn());
+
+ controller.processCommand(bluetooth::Command(Command::Type::PowerOn));
+ REQUIRE(controller.isOn());
+}
M module-bluetooth/tests/tests-BluetoothDevicesModel.cpp => module-bluetooth/tests/tests-BluetoothDevicesModel.cpp +1 -0
@@ 4,6 4,7 @@
#include <catch2/catch.hpp>
#include "Device.hpp"
#include "service-bluetooth/BluetoothDevicesModel.hpp"
+
TEST_CASE("Devicei comparison")
{
Devicei device1{"Dev1"};
A module-bluetooth/tests/tests-Devicei.cpp => module-bluetooth/tests/tests-Devicei.cpp +62 -0
@@ 0,0 1,62 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <catch2/catch.hpp>
+#include "Device.hpp"
+#include <btstack_util.h>
+
+Devicei genDev()
+{
+ Devicei from("from");
+ bd_addr_t addr{0, 1, 2, 3, 4, 5};
+ from.setAddress(&addr);
+ from.pageScanRepetitionMode = 1;
+ from.clockOffset = 1;
+ from.classOfDevice = 1;
+ from.state = DEVICE_STATE::REMOTE_NAME_REQUEST;
+ from.deviceState = DeviceState::Paired;
+ from.isPairingSSP = true;
+ return from;
+}
+
+TEST_CASE("Devicei - create copy and move")
+{
+ Devicei from = genDev();
+ Devicei to;
+
+ SECTION("create - by copy")
+ {
+ SECTION("ctor")
+ {
+ to = Devicei(from);
+ }
+ SECTION("operator")
+ {
+ to.operator=(from);
+ }
+ }
+
+ SECTION("move")
+ {
+ // please see that that section depends on previous section working fine
+ Devicei base = from;
+ SECTION("ctor")
+ {
+ to = std::move(base);
+ }
+ SECTION("operator")
+ {
+ to.operator=(std::move(from));
+ }
+ }
+
+ REQUIRE(from == to);
+ REQUIRE(!(from != to));
+ REQUIRE(bd_addr_cmp(from.address, to.address) == 0);
+ REQUIRE(from.pageScanRepetitionMode == to.pageScanRepetitionMode);
+ REQUIRE(from.clockOffset == to.clockOffset);
+ REQUIRE(from.classOfDevice == to.classOfDevice);
+ REQUIRE(from.state == to.state);
+ REQUIRE(from.deviceState == to.deviceState);
+ REQUIRE(from.isPairingSSP == to.isPairingSSP);
+}
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +1 -1
@@ 349,7 349,7 @@ auto ServiceBluetooth::handle(message::bluetooth::DisconnectResult *msg) -> std:
auto ServiceBluetooth::handle(message::bluetooth::ResponsePasskey *msg) -> std::shared_ptr<sys::Message>
{
auto passKey = msg->getPasskey();
- bluetooth::GAP::respondPinCode(passKey);
+ bluetooth::GAP::respondPinCode(passKey, msg->getDevice());
return sys::MessageNone{};
}
M module-services/service-bluetooth/service-bluetooth/BluetoothDevicesModel.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothDevicesModel.cpp +6 -0
@@ 70,11 70,17 @@ void BluetoothDevicesModel::syncDevicesWithApp()
sys::BusChannel::BluetoothNotifications);
}
}
+
void BluetoothDevicesModel::setInternalDeviceState(const Devicei &device, const DeviceState &state)
{
auto dev = getDeviceByAddress(device.address);
+ if (not dev) {
+ LOG_ERROR("no such device - ignored");
+ return;
+ }
dev.value().get().deviceState = state;
}
+
void BluetoothDevicesModel::mergeInternalDeviceState(const Devicei &device)
{
try {
D module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.cpp +0 -172
@@ 1,172 0,0 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include "BluetoothSettingsModel.hpp"
-
-#include <service-bluetooth/Constants.hpp>
-#include <service-bluetooth/messages/BondedDevices.hpp>
-#include <service-bluetooth/messages/Connect.hpp>
-#include <service-bluetooth/messages/DeviceName.hpp>
-#include <service-bluetooth/messages/Disconnect.hpp>
-#include <service-bluetooth/messages/Status.hpp>
-#include <service-bluetooth/messages/SetStatus.hpp>
-#include <service-bluetooth/messages/SetDeviceName.hpp>
-#include <service-bluetooth/messages/Passkey.hpp>
-#include <service-bluetooth/messages/Unpair.hpp>
-
-BluetoothSettingsModel::BluetoothSettingsModel(app::Application *application) : application{application}
-{}
-
-void BluetoothSettingsModel::requestStatus()
-{
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestStatus>(), service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::setStatus(const bool desiredBluetoothState, const bool desiredVisibility)
-{
- BluetoothStatus status{.state = desiredBluetoothState ? BluetoothStatus::State::On : BluetoothStatus::State::Off,
- .visibility = desiredVisibility};
- message::bluetooth::SetStatus setStatus(status);
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::SetStatus>(std::move(setStatus)),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestDeviceName()
-{
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestDeviceName>(), service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::setDeviceName(const UTF8 &deviceName)
-{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::SetDeviceName>(deviceName),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestBondedDevices()
-{
- application->bus.sendUnicast(std::make_shared<::message::bluetooth::RequestBondedDevices>(),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestScan()
-{
- application->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Scan),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::stopScan()
-{
- application->bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::StopScan),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestDevicePair(const std::string &addr)
-{
- application->bus.sendUnicast(std::make_shared<BluetoothPairMessage>(addr), service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestDeviceUnpair(const Devicei &device)
-{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::Unpair>(bd_addr_to_str(device.address)),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::responsePasskey(const std::string &passkey)
-{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::ResponsePasskey>(passkey),
- service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestConnection(const std::string &addr)
-{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::Connect>(addr), service::name::bluetooth);
-}
-
-void BluetoothSettingsModel::requestDisconnection()
-{
- application->bus.sendUnicast(std::make_shared<message::bluetooth::Disconnect>(), service::name::bluetooth);
-}
-void BluetoothSettingsModel::mergeDevicesList(const std::vector<Devicei> &devicesList)
-{
- devices.insert(std::end(devices), std::begin(devicesList), std::end(devicesList));
-
- // remove duplicates
- auto end = std::end(devices);
- for (auto it = std::begin(devices); it != end; ++it) {
- end = std::remove(it + 1, end, *it);
- }
- devices.erase(end, std::end(devices));
-}
-void BluetoothSettingsModel::setActiveDeviceState(const DeviceState &state)
-{
- auto activeDevice = getActiveDevice();
- if (activeDevice.has_value()) {
- activeDevice.value().get().deviceState = state;
- }
-}
-auto BluetoothSettingsModel::getActiveDevice() -> std::optional<std::reference_wrapper<Devicei>>
-{
- try {
- return devices.at(activeDeviceIndex);
- }
- catch (const std::out_of_range &oor) {
- LOG_FATAL("NO DEVICE FOUND!");
- return std::nullopt;
- }
-}
-auto BluetoothSettingsModel::getSelectedDevice() -> std::optional<std::reference_wrapper<Devicei>>
-{
- try {
- return devices.at(selectedDeviceIndex);
- }
- catch (const std::out_of_range &oor) {
- LOG_FATAL("NO DEVICE FOUND!");
- return std::nullopt;
- }
-}
-void BluetoothSettingsModel::setActiveDevice(const Devicei &device)
-{
- auto itr = std::find(std::begin(devices), std::end(devices), device);
- activeDeviceIndex = std::distance(std::begin(devices), itr);
-}
-void BluetoothSettingsModel::setSelectedDevice(const Devicei &device)
-{
- auto itr = std::find(std::begin(devices), std::end(devices), device);
- selectedDeviceIndex = std::distance(std::begin(devices), itr);
-}
-void BluetoothSettingsModel::insertDevice(const Devicei device)
-{
- devices.emplace_back(device);
-}
-auto BluetoothSettingsModel::getDeviceByAddress(const std::string &address)
- -> std::optional<std::reference_wrapper<Devicei>>
-{
- auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [address](const Devicei &device) {
- return bd_addr_to_str(device.address) == address;
- });
-
- if (deviceIt == std::end(devices)) {
- return std::nullopt;
- }
- return std::ref(*deviceIt);
-}
-void BluetoothSettingsModel::removeDevice(const Devicei &device)
-{
- devices.erase(std::remove(std::begin(devices), std::end(devices), device), std::end(devices));
-}
-auto BluetoothSettingsModel::getDevices() -> std::vector<Devicei> &
-{
- return devices;
-}
-auto BluetoothSettingsModel::isDeviceConnecting() -> bool
-{
-
- auto deviceIt = std::find_if(std::begin(devices), std::end(devices), [](const Devicei &device) {
- return device.deviceState == DeviceState::Connecting;
- });
-
- if (deviceIt != std::end(devices)) {
- return true;
- }
- return false;
-}
D module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothSettingsModel.hpp +0 -59
@@ 1,59 0,0 @@
-// 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 "Application.hpp"
-#include <Device.hpp>
-
-extern "C"
-{
-#include <module-bluetooth/lib/btstack/src/btstack_util.h>
-}
-
-class ActiveDevice
-{
- public:
- explicit ActiveDevice(std::string address) : address(std::move(address))
- {}
- ActiveDevice() = default;
- DeviceState state = DeviceState::Unknown;
- std::string address;
-};
-
-class BluetoothSettingsModel
-{
- public:
- explicit BluetoothSettingsModel(app::Application *application);
-
- void requestStatus();
- void setStatus(bool desiredBluetoothState, bool desiredVisibility);
- void requestDeviceName();
- void setDeviceName(const UTF8 &deviceName);
- void requestBondedDevices();
- void requestScan();
- void stopScan();
- void requestDevicePair(const std::string &addr);
- void requestDeviceUnpair(const Devicei &device);
- void responsePasskey(const std::string &passkey);
- void requestConnection(const std::string &addr);
- void requestDisconnection();
- void replaceDevicesList(const std::vector<Devicei> &devicesList);
- void setActiveDeviceState(const DeviceState &state);
- auto getActiveDevice() -> std::optional<std::reference_wrapper<Devicei>>;
- auto getSelectedDevice() -> std::optional<std::reference_wrapper<Devicei>>;
- auto getDeviceByAddress(const std::string &address) -> std::optional<std::reference_wrapper<Devicei>>;
- void setActiveDevice(const Devicei &device);
- void setSelectedDevice(const Devicei &device);
- void insertDevice(Devicei device);
- void removeDevice(const Devicei &device);
- auto getDevices() -> std::vector<Devicei> &;
- auto isDeviceConnecting() -> bool;
-
- private:
- std::vector<Devicei> devices{};
- std::uint16_t activeDeviceIndex = 0;
- std::uint16_t selectedDeviceIndex = 0;
- app::Application *application = nullptr;
- Devicei dummyDevice{""};
-};
M module-services/service-bluetooth/service-bluetooth/messages/Passkey.hpp => module-services/service-bluetooth/service-bluetooth/messages/Passkey.hpp +21 -2
@@ 8,18 8,37 @@
namespace message::bluetooth
{
class RequestPasskey : public BluetoothMessage
- {};
+ {
+ Devicei device;
+
+ public:
+ explicit RequestPasskey(const Devicei &dev) : device(dev)
+ {}
+
+ [[nodiscard]] auto getDevice()
+ {
+ return device;
+ }
+ };
class ResponsePasskey : public BluetoothMessage
{
+ Devicei device;
+
public:
- explicit ResponsePasskey(std::string passkey) : passkey(std::move(passkey))
+ ResponsePasskey(std::string passkey, const Devicei &dev) : device(dev), passkey(std::move(passkey))
{}
+
[[nodiscard]] auto getPasskey() const -> std::string
{
return passkey;
}
+ [[nodiscard]] auto getDevice()
+ {
+ return device;
+ }
+
private:
std::string passkey;
};
M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +1 -0
@@ 20,6 20,7 @@ namespace Log
{"ServiceAntenna", logger_level::LOGERROR},
{"ServiceAudio", logger_level::LOGINFO},
{"ServiceBluetooth", logger_level::LOGINFO},
+ {"ServiceBluetooth_w1", logger_level::LOGINFO},
{"ServiceFota", logger_level::LOGINFO},
{"ServiceEink", logger_level::LOGINFO},
{"ServiceDB", logger_level::LOGINFO},