Integrate shared C transport with desktop and Android frontends, add radio probes and detailed Windows diagnostics, and fix GUI build dependencies and early configuration startup errors.
112 lines
5.6 KiB
C++
112 lines
5.6 KiB
C++
#include "desktop_ble.h"
|
|
#include "../../../lib/ble/ble_identity.h"
|
|
#include "../../../lib/debug_config.h"
|
|
|
|
DesktopBle::DesktopBle(UASYNC* ua, uint64_t nodeId) : m_ua(ua), m_nodeId(nodeId) { m_clock.start(); }
|
|
DesktopBle::~DesktopBle() { ble_destroy(m_transport); }
|
|
|
|
void DesktopBle::advertise() {
|
|
if (m_snapshot.state != BLE_READY) return;
|
|
const bool enabled = m_snapshot.flags & 2;
|
|
if (ble_advertise(m_transport, enabled ? m_identity.constData() : nullptr, enabled ? size_t(m_identity.size()) : 0)) {
|
|
m_snapshot.advertising = BLE_CLOSED;
|
|
m_snapshot.advertisingReason = QStringLiteral("Could not publish Bluetooth advertisement");
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE desktop advertisement request failed");
|
|
}
|
|
}
|
|
|
|
void DesktopBle::apply(int flags, const char* name) {
|
|
const QByteArray nextName(name);
|
|
if (flags == m_snapshot.flags && nextName == m_name) return;
|
|
const int previous = m_snapshot.flags;
|
|
m_snapshot.flags = flags;
|
|
m_name = nextName;
|
|
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE desktop settings: enabled=%d advertise=%d incoming=%d",
|
|
!!(flags & 1), !!(flags & 2), !!(flags & 4));
|
|
if (!(flags & 1)) {
|
|
ble_destroy(m_transport); m_transport = nullptr;
|
|
m_snapshot = {}; m_snapshot.flags = flags;
|
|
m_peers.clear(); m_connections.clear();
|
|
return;
|
|
}
|
|
uint8_t bytes[BLE_BROADCAST_MAX];
|
|
const int length = ble_identity_encode(bytes, m_nodeId, name);
|
|
if (length < 0) {
|
|
m_snapshot.reason = QStringLiteral("Invalid Bluetooth node identity");
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE desktop identity encoding failed node=%016llx", (unsigned long long)m_nodeId);
|
|
return;
|
|
}
|
|
m_identity = QByteArray(reinterpret_cast<const char*>(bytes), length);
|
|
if (m_transport) {
|
|
if ((flags ^ previous) & 4) ble_set_incoming(m_transport, !!(flags & 4));
|
|
advertise();
|
|
return;
|
|
}
|
|
ble_config config{};
|
|
config.node_id = m_nodeId; config.company_id = 0xffff; config.arg = this;
|
|
config.callbacks.status = [](void* arg, ble_state state, const char* reason) {
|
|
auto* self = static_cast<DesktopBle*>(arg);
|
|
self->m_snapshot.state = state; self->m_snapshot.reason = QString::fromUtf8(reason);
|
|
if (state == BLE_CLOSED) {
|
|
self->m_snapshot.advertising = BLE_CLOSED;
|
|
self->m_snapshot.advertisingReason = self->m_snapshot.reason;
|
|
}
|
|
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE desktop state=%d reason=%s", state, reason);
|
|
if (state == BLE_READY) self->advertise();
|
|
};
|
|
config.callbacks.advertising = [](void* arg, ble_state state, const char* reason) {
|
|
auto* self = static_cast<DesktopBle*>(arg);
|
|
self->m_snapshot.advertising = state; self->m_snapshot.advertisingReason = QString::fromUtf8(reason);
|
|
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE desktop advertising=%d reason=%s", state, reason);
|
|
};
|
|
config.callbacks.validate = [](void*, ble_link_id link, uint64_t node) {
|
|
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE desktop validation allow link=%llu node=%016llx",
|
|
(unsigned long long)link, (unsigned long long)node);
|
|
return 1;
|
|
};
|
|
config.callbacks.connection = [](void* arg, ble_link_id link, uint64_t node, ble_state state, const char* reason) {
|
|
auto* self = static_cast<DesktopBle*>(arg);
|
|
if (state == BLE_READY) self->m_connections.insert(link, true);
|
|
else self->m_connections.remove(link);
|
|
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE desktop connection link=%llu node=%016llx state=%d reason=%s",
|
|
(unsigned long long)link, (unsigned long long)node, state, reason);
|
|
};
|
|
config.callbacks.broadcast = [](void* arg, const ble_endpoint*, const uint8_t* data, size_t length, int rssi) {
|
|
auto* self = static_cast<DesktopBle*>(arg);
|
|
ble_identity peer{};
|
|
if (ble_identity_decode(&peer, data, length) || peer.node_id == self->m_nodeId) return;
|
|
if (!self->m_peers.contains(peer.node_id)) {
|
|
if (self->m_peers.size() >= 64) return;
|
|
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "BLE desktop discovered node=%016llx name=%s rssi=%d",
|
|
(unsigned long long)peer.node_id, peer.name, rssi);
|
|
}
|
|
const QString text = QStringLiteral("%1 · %2 · %3 dBm").arg(QString::fromUtf8(peer.name),
|
|
QString::number(peer.node_id, 16).rightJustified(16, '0'), rssi == 127 ? QStringLiteral("?") : QString::number(rssi));
|
|
self->m_peers.insert(peer.node_id, {text, self->m_clock.elapsed()});
|
|
};
|
|
m_snapshot.state = BLE_STARTING; m_snapshot.reason.clear();
|
|
m_transport = ble_create(m_ua, &config);
|
|
if (!m_transport) {
|
|
m_snapshot.state = BLE_CLOSED; m_snapshot.reason = QStringLiteral("Could not create Bluetooth transport");
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE desktop transport creation failed");
|
|
return;
|
|
}
|
|
ble_set_incoming(m_transport, !!(flags & 4));
|
|
if (ble_start(m_transport)) {
|
|
m_snapshot.state = BLE_CLOSED;
|
|
if (m_snapshot.reason.isEmpty()) m_snapshot.reason = QStringLiteral("Could not start Bluetooth transport");
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "BLE desktop start failed");
|
|
}
|
|
}
|
|
|
|
DesktopBleSnapshot DesktopBle::snapshot() {
|
|
const qint64 now = m_clock.elapsed();
|
|
m_snapshot.peers.clear();
|
|
for (auto it = m_peers.begin(); it != m_peers.end();) {
|
|
if (now - it->seen > 30000) it = m_peers.erase(it);
|
|
else { m_snapshot.peers.append(it->text); ++it; }
|
|
}
|
|
m_snapshot.connections = m_connections.size();
|
|
return m_snapshot;
|
|
}
|