diff --git a/.cache/clangd/index/CoreService.cpp.4E2160035C5FBDAD.idx b/.cache/clangd/index/CoreService.cpp.4E2160035C5FBDAD.idx index 2182812..5551faf 100644 Binary files a/.cache/clangd/index/CoreService.cpp.4E2160035C5FBDAD.idx and b/.cache/clangd/index/CoreService.cpp.4E2160035C5FBDAD.idx differ diff --git a/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx b/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx index ff9885c..5a63b62 100644 Binary files a/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx and b/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx differ diff --git a/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx b/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx index c2f9e98..2725458 100644 Binary files a/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx and b/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx differ diff --git a/.cache/clangd/index/IDeviceMonitor.h.35FD4D7CC78F8E5E.idx b/.cache/clangd/index/IDeviceMonitor.h.35FD4D7CC78F8E5E.idx index 360b03f..9449e3a 100644 Binary files a/.cache/clangd/index/IDeviceMonitor.h.35FD4D7CC78F8E5E.idx and b/.cache/clangd/index/IDeviceMonitor.h.35FD4D7CC78F8E5E.idx differ diff --git a/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx b/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx index f5bb5c9..3248cdd 100644 Binary files a/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx and b/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx differ diff --git a/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx b/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx index 20edc35..7a4fb0c 100644 Binary files a/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx and b/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx differ diff --git a/.cache/clangd/index/UdevDeviceMonitor.h.0028E083196B240B.idx b/.cache/clangd/index/UdevDeviceMonitor.h.0028E083196B240B.idx index 420e228..0c9dcd7 100644 Binary files a/.cache/clangd/index/UdevDeviceMonitor.h.0028E083196B240B.idx and b/.cache/clangd/index/UdevDeviceMonitor.h.0028E083196B240B.idx differ diff --git a/.cache/clangd/index/main.cpp.76A75E580B25A05E.idx b/.cache/clangd/index/main.cpp.76A75E580B25A05E.idx index dc96be6..f1635ba 100644 Binary files a/.cache/clangd/index/main.cpp.76A75E580B25A05E.idx and b/.cache/clangd/index/main.cpp.76A75E580B25A05E.idx differ diff --git a/bin/softbus_daemon b/bin/softbus_daemon index 37b5ac5..5ec808f 100755 Binary files a/bin/softbus_daemon and b/bin/softbus_daemon differ diff --git a/main.cpp b/main.cpp index 3b0b49b..16375e6 100644 --- a/main.cpp +++ b/main.cpp @@ -14,7 +14,7 @@ void signalHandler(int signal) if (coreService) { coreService->shutdown(); } - + QCoreApplication::quit(); } @@ -67,6 +67,14 @@ int main(int argc, char *argv[]) << "valid roles are: CoreRouter, CollectorSerial, CollectorCan, Collector, SqlServer"; return 1; } + // 开启coreserive的初始化工作|线程 + // QThread* coreServiceThread = new QThread(); + // CoreService* coreService = new CoreService(); + // coreService->moveToThread(coreServiceThread); + // QObject::connect(coreServiceThread, &QThread::started, coreService, &CoreService::initialize); + // QObject::connect(coreServiceThread, &QThread::finished, coreService, &CoreService::deleteLater); + // QObject::connect(coreServiceThread, &QThread::finished, coreServiceThread, &QThread::deleteLater); + // coreServiceThread->start(); CoreService* coreService = CoreService::instance(); if (!coreService->initialize()) { diff --git a/src/device_bus/DeviceBus.cpp b/src/device_bus/DeviceBus.cpp index d939c65..d1b319c 100644 --- a/src/device_bus/DeviceBus.cpp +++ b/src/device_bus/DeviceBus.cpp @@ -52,15 +52,27 @@ bool DeviceBus::initialize(const QJsonObject &rootConfig) { d->manager->setDeviceTreeModel(d->treeModel); d->manager->setRegistry(d->registry.get()); + // 1) Load persisted config and initialize manager + if (!d->manager->initialize(rootConfig)) { + return false; + } + + // 2) Start monitor service if (!d->monitorService) { d->monitorService = std::make_unique(nullptr); d->monitorService->setRegistry(d->registry.get()); d->monitorService->setDirtyCallback([this]() { this->markDeviceTreeDirty(); }); - if (!d->monitorService->start()) { - LOG_WARNING() << "DeviceBus: device monitor service start failed"; - } } - return d->manager->initialize(rootConfig); + if (!d->monitorService->start()) { + LOG_WARNING() << "DeviceBus: device monitor service start failed"; + } + + // 3) Initial snapshot scan (register existing devices) + d->monitorService->initialScan(); + + // 4) Reconcile runtime instances against latest tree model + d->manager->reconcileFromTreeModel(); + return true; } void DeviceBus::shutdown() { diff --git a/src/device_bus/manager/DeviceBusManager.cpp b/src/device_bus/manager/DeviceBusManager.cpp index 678f1eb..4a7d6b3 100644 --- a/src/device_bus/manager/DeviceBusManager.cpp +++ b/src/device_bus/manager/DeviceBusManager.cpp @@ -4,6 +4,7 @@ #include #include +#include // #include #include "hardware/drivers/serial/SerialQtDriver.h" @@ -58,6 +59,44 @@ bool DeviceBusManager::initialize(const QJsonObject& rootConfig) return true; } +bool DeviceBusManager::reconcileFromTreeModel() +{ + if (!m_treeModel) { + return false; + } + + QSet desiredSerialEndpoints; + const auto nodes = m_treeModel->nodes(); + for (const auto& n : nodes) { + if (!n.enabled) continue; + if (!n.params.value(QStringLiteral("online")).toBool(true)) continue; + + auto kind = softbus::devices::kindFromType(n.type); + if (kind == softbus::devices::DeviceKind::Unknown) { + kind = softbus::devices::inferDeviceKindFromEndpoint(n.endpoint); + } + + if (kind == softbus::devices::DeviceKind::Serial) { + desiredSerialEndpoints.insert(n.endpoint); + if (!m_serialDevicesByEndpoint.contains(n.endpoint)) { + initializeSerialDevice(n.endpoint, n.params); + } + m_deviceEndpointsMap.insert(n.endpoint, kind); + } + } + + // Remove runtime devices that are no longer desired/offline + const auto currentKeys = m_serialDevicesByEndpoint.keys(); + for (const auto& endpoint : currentKeys) { + if (!desiredSerialEndpoints.contains(endpoint)) { + shutdownSerialDevice(endpoint); + m_deviceEndpointsMap.remove(endpoint); + } + } + + return true; +} + void DeviceBusManager::shutdown() { // 关闭并销毁所有串口设备 diff --git a/src/device_bus/manager/DeviceBusManager.h b/src/device_bus/manager/DeviceBusManager.h index 317a470..e2d084a 100644 --- a/src/device_bus/manager/DeviceBusManager.h +++ b/src/device_bus/manager/DeviceBusManager.h @@ -20,6 +20,7 @@ public: void setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry); bool initialize(const QJsonObject& rootConfig); + bool reconcileFromTreeModel(); void shutdown(); private: diff --git a/src/device_bus/monitor/DeviceMonitorService.cpp b/src/device_bus/monitor/DeviceMonitorService.cpp index 418bf82..8258a56 100644 --- a/src/device_bus/monitor/DeviceMonitorService.cpp +++ b/src/device_bus/monitor/DeviceMonitorService.cpp @@ -49,6 +49,19 @@ bool DeviceMonitorService::start() return ok; } +bool DeviceMonitorService::initialScan() +{ + bool any = false; + for (auto& m : m_monitors) { + const auto snapshot = m->snapshotExisting(); + for (const auto& ev : snapshot) { + onEvent(ev); + any = true; + } + } + return any; +} + void DeviceMonitorService::stop() { if (!m_started) return; diff --git a/src/device_bus/monitor/DeviceMonitorService.h b/src/device_bus/monitor/DeviceMonitorService.h index 8ecb696..ed8795e 100644 --- a/src/device_bus/monitor/DeviceMonitorService.h +++ b/src/device_bus/monitor/DeviceMonitorService.h @@ -23,6 +23,7 @@ public: bool start(); void stop(); + bool initialScan(); void setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry); void setDirtyCallback(std::function cb); diff --git a/src/device_bus/monitor/IDeviceMonitor.h b/src/device_bus/monitor/IDeviceMonitor.h index 115b754..2bb685c 100644 --- a/src/device_bus/monitor/IDeviceMonitor.h +++ b/src/device_bus/monitor/IDeviceMonitor.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -20,6 +21,7 @@ public: virtual bool start() = 0; virtual void stop() = 0; + virtual std::vector snapshotExisting() = 0; void setCallback(EventCallback cb) { m_cb = std::move(cb); } diff --git a/src/device_bus/monitor/NetlinkDeviceMonitor.cpp b/src/device_bus/monitor/NetlinkDeviceMonitor.cpp index ca94e25..76ed342 100644 --- a/src/device_bus/monitor/NetlinkDeviceMonitor.cpp +++ b/src/device_bus/monitor/NetlinkDeviceMonitor.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -149,6 +150,38 @@ void NetlinkDeviceMonitor::onReadable() } } +std::vector NetlinkDeviceMonitor::snapshotExisting() +{ + std::vector out; + + ifaddrs* ifaddr = nullptr; + if (::getifaddrs(&ifaddr) != 0) { + return out; + } + + QSet seen; + for (ifaddrs* it = ifaddr; it != nullptr; it = it->ifa_next) { + if (!it->ifa_name) continue; + + const QString ifname = QString::fromUtf8(it->ifa_name); + if (ifname.isEmpty() || seen.contains(ifname)) continue; + seen.insert(ifname); + + DeviceEvent ev; + ev.timestamp = QDateTime::currentDateTimeUtc(); + ev.type = DeviceEventType::NetInterface; + ev.action = DeviceEventAction::Add; + ev.subsystem = QStringLiteral("net"); + ev.ifname = ifname; + ev.ifindex = ::if_nametoindex(it->ifa_name); + ev.linkUp = (it->ifa_flags & IFF_RUNNING) != 0; + out.push_back(ev); + } + + ::freeifaddrs(ifaddr); + return out; +} + } // namespace softbus::device_bus::monitor #endif // __linux__ diff --git a/src/device_bus/monitor/NetlinkDeviceMonitor.h b/src/device_bus/monitor/NetlinkDeviceMonitor.h index 2f43bfd..287610a 100644 --- a/src/device_bus/monitor/NetlinkDeviceMonitor.h +++ b/src/device_bus/monitor/NetlinkDeviceMonitor.h @@ -7,6 +7,7 @@ #include #include #include +#include namespace softbus::device_bus::monitor { @@ -20,6 +21,7 @@ public: bool start() override; void stop() override; + std::vector snapshotExisting() override; private: void onReadable(); diff --git a/src/device_bus/monitor/UdevDeviceMonitor.cpp b/src/device_bus/monitor/UdevDeviceMonitor.cpp index 4e7122d..3134ff9 100644 --- a/src/device_bus/monitor/UdevDeviceMonitor.cpp +++ b/src/device_bus/monitor/UdevDeviceMonitor.cpp @@ -3,6 +3,8 @@ #if defined(__linux__) #include +#include +#include #include @@ -10,6 +12,37 @@ namespace softbus::device_bus::monitor { +namespace { + +bool isWhitelistedSerialDevnode(const QString& devnode) +{ + if (devnode.startsWith(QStringLiteral("/dev/ttyUSB"))) return true; + if (devnode.startsWith(QStringLiteral("/dev/ttyACM"))) return true; + + // Board UART allowlist: ttyS1 ~ ttyS6 + static const QRegularExpression kTtySRe(QStringLiteral("^/dev/ttyS(\\d+)$")); + const auto m = kTtySRe.match(devnode); + if (m.hasMatch()) { + bool ok = false; + const int n = m.captured(1).toInt(&ok); + if (ok && n >= 1 && n <= 6) return true; + } + return false; +} + +bool isConsoleLikeTty(const QString& devnode) +{ + if (devnode == QStringLiteral("/dev/console")) return true; + if (devnode == QStringLiteral("/dev/tty")) return true; + if (devnode == QStringLiteral("/dev/ptmx")) return true; + if (devnode.startsWith(QStringLiteral("/dev/pts/"))) return true; + + // Linux VT consoles: /dev/tty0.../dev/tty63 (without 'S') + static const QRegularExpression kVtRe(QStringLiteral("^/dev/tty(\\d+)$")); + return kVtRe.match(devnode).hasMatch(); +} + +} // namespace UdevDeviceMonitor::UdevDeviceMonitor(QObject* parent) : IDeviceMonitor(parent) @@ -94,35 +127,7 @@ void UdevDeviceMonitor::onReadable() const char* action = udev_device_get_action(dev); DeviceEvent ev = toEvent(dev, action); - // Drop unknown action (usually noise / incomplete events) - if (ev.action == DeviceEventAction::Unknown) { - udev_device_unref(dev); - continue; - } - - // USB: only keep usb_device (drop interface-level noise) - if (ev.subsystem == QStringLiteral("usb")) { - const QString devtype = ev.props.value(QStringLiteral("DEVTYPE")); - if (!devtype.isEmpty() && devtype != QStringLiteral("usb_device")) { - udev_device_unref(dev); - continue; - } - - // Drop most "change" spam for usb (keep add/remove) - if (ev.action == DeviceEventAction::Change) { - udev_device_unref(dev); - continue; - } - - // If it carries no stable identifiers, it's not useful - if (ev.devnode.isEmpty() && ev.vid.isEmpty() && ev.pid.isEmpty() && ev.serial.isEmpty()) { - udev_device_unref(dev); - continue; - } - } - - // Storage: keep add/remove; drop change spam - if (ev.type == DeviceEventType::Storage && ev.action == DeviceEventAction::Change) { + if (!shouldKeepEvent(ev)) { udev_device_unref(dev); continue; } @@ -132,6 +137,117 @@ void UdevDeviceMonitor::onReadable() } } +std::vector UdevDeviceMonitor::snapshotExisting() +{ + std::vector out; + if (!m_udev) { + // Snapshot can be requested before start(); create temp context. + m_udev = udev_new(); + if (!m_udev) { + LOG_ERROR() << "UdevDeviceMonitor: snapshot udev_new failed"; + return out; + } + } + + udev_enumerate* en = udev_enumerate_new(m_udev); + if (!en) { + return out; + } + + udev_enumerate_add_match_subsystem(en, "tty"); + udev_enumerate_add_match_subsystem(en, "usb"); + udev_enumerate_add_match_subsystem(en, "block"); + if (udev_enumerate_scan_devices(en) != 0) { + udev_enumerate_unref(en); + return out; + } + + udev_list_entry* devices = udev_enumerate_get_list_entry(en); + udev_list_entry* entry = nullptr; + udev_list_entry_foreach(entry, devices) { + const char* path = udev_list_entry_get_name(entry); + if (!path) continue; + + udev_device* dev = udev_device_new_from_syspath(m_udev, path); + if (!dev) continue; + + DeviceEvent ev = toEvent(dev, "add"); + if (shouldKeepEvent(ev)) { + out.push_back(ev); + } + + udev_device_unref(dev); + } + + udev_enumerate_unref(en); + return out; +} + +bool UdevDeviceMonitor::shouldKeepEvent(const DeviceEvent& ev) const +{ + // Drop unknown action (usually noise / incomplete events) + if (ev.action == DeviceEventAction::Unknown) { + return false; + } + + // Serial tty: keep only business serial nodes. + if (ev.subsystem == QStringLiteral("tty")) { + if (ev.devnode.isEmpty()) { + LOG_ERROR() << "UdevDeviceMonitor: devnode is empty" << ev.devnode; + return false; + } + if (isConsoleLikeTty(ev.devnode)) { + LOG_INFO() << "UdevDeviceMonitor: console like tty" << ev.devnode; + return false; + } + if (!isWhitelistedSerialDevnode(ev.devnode)) { + LOG_INFO() << "UdevDeviceMonitor: not whitelisted serial devnode" << ev.devnode; + return false; + } + } + + // USB: only keep usb_device (drop interface-level noise) + if (ev.subsystem == QStringLiteral("usb")) { + const QString devtype = ev.props.value(QStringLiteral("DEVTYPE")); + if (!devtype.isEmpty() && devtype != QStringLiteral("usb_device")) { + return false; + } + + // Drop most "change" spam for usb (keep add/remove) + if (ev.action == DeviceEventAction::Change) { + return false; + } + + // If it carries no stable identifiers, it's not useful + if (ev.devnode.isEmpty() && ev.vid.isEmpty() && ev.pid.isEmpty() && ev.serial.isEmpty()) { + return false; + } + + // Drop Linux root hubs/controller pseudo devices. + if (ev.vid == QStringLiteral("1d6b")) { + return false; + } + const QString modelLower = ev.model.toLower(); + if (modelLower.contains(QStringLiteral("hub")) || + modelLower.contains(QStringLiteral("host_controller")) || + modelLower.contains(QStringLiteral("xhci"))) { + return false; + } + } + + // Block: keep only usb-backed storage add/remove, drop non-storage blocks. + if (ev.subsystem == QStringLiteral("block")) { + if (ev.type != DeviceEventType::Storage) { + return false; + } + if (ev.action == DeviceEventAction::Change) { + return false; + } + } + + return true; +} + QString UdevDeviceMonitor::getProp(struct udev_device* dev, const char* key) { if (!dev || !key) return {}; diff --git a/src/device_bus/monitor/UdevDeviceMonitor.h b/src/device_bus/monitor/UdevDeviceMonitor.h index 4db01de..a1db0b6 100644 --- a/src/device_bus/monitor/UdevDeviceMonitor.h +++ b/src/device_bus/monitor/UdevDeviceMonitor.h @@ -20,9 +20,11 @@ public: bool start() override; void stop() override; + std::vector snapshotExisting() override; private: void onReadable(); + bool shouldKeepEvent(const DeviceEvent& ev) const; DeviceEvent toEvent(struct udev_device* dev, const char* action); static QString getProp(struct udev_device* dev, const char* key); diff --git a/src/device_bus/monitor/WindowsDeviceMonitor.cpp b/src/device_bus/monitor/WindowsDeviceMonitor.cpp index 367d661..71731d9 100644 --- a/src/device_bus/monitor/WindowsDeviceMonitor.cpp +++ b/src/device_bus/monitor/WindowsDeviceMonitor.cpp @@ -38,5 +38,11 @@ void WindowsDeviceMonitor::stop() #endif } +std::vector WindowsDeviceMonitor::snapshotExisting() +{ + // TODO: implement full snapshot on Windows. + return {}; +} + } // namespace softbus::device_bus::monitor diff --git a/src/device_bus/monitor/WindowsDeviceMonitor.h b/src/device_bus/monitor/WindowsDeviceMonitor.h index c380764..43f1f62 100644 --- a/src/device_bus/monitor/WindowsDeviceMonitor.h +++ b/src/device_bus/monitor/WindowsDeviceMonitor.h @@ -15,6 +15,7 @@ public: bool start() override; void stop() override; + std::vector snapshotExisting() override; private: #if defined(_WIN32) diff --git a/src/device_bus/registry/DeviceRegistry.cpp b/src/device_bus/registry/DeviceRegistry.cpp index 5937434..6e5ca41 100644 --- a/src/device_bus/registry/DeviceRegistry.cpp +++ b/src/device_bus/registry/DeviceRegistry.cpp @@ -85,6 +85,27 @@ QString DeviceRegistry::buildStableKey(const softbus::device_bus::monitor::Devic { const QString type = inferType(ev); + // Important: ttyACM/ttyUSB 可能“同一条物理设备多路口”但 serial 相同, + // 旧逻辑会导致 stableKey 冲突并相互覆盖 endpoint。 + // tty 事件:devnode 必须用于唯一标识(ttyACM 可能多路口但 serial 可能相同)。 + // 若具备 SYSPATH,也一并拼接,便于跨层级归并与排查。 + if (ev.type == softbus::device_bus::monitor::DeviceEventType::Serial || + ev.subsystem == QStringLiteral("tty")) { + const QString syspath = ev.props.value(QStringLiteral("SYSPATH")); + if (!ev.devnode.isEmpty()) { + if (!syspath.isEmpty()) { + return type + QStringLiteral("|syspath|") + syspath + QStringLiteral("|devnode|") + ev.devnode; + } + return type + QStringLiteral("|devnode|") + ev.devnode; + } + if (!syspath.isEmpty()) { + return type + QStringLiteral("|syspath|") + syspath; + } + if (!ev.serial.isEmpty()) { + return type + QStringLiteral("|serial|") + ev.serial; + } + } + if (!ev.serial.isEmpty()) { return type + QStringLiteral("|serial|") + ev.serial; } @@ -109,6 +130,15 @@ QString DeviceRegistry::buildStableKey(const softbus::device_bus::monitor::Devic QString DeviceRegistry::buildPreferredNodeId(const softbus::device_bus::monitor::DeviceEvent& ev, const QString& stableKey) { + // For tty devices (ttyS/ttyUSB/ttyACM...), a single physical device may expose + // multiple ports that share the same serial. If we only use `serial` as id, + // upsert() will collide by preferredId and overwrite endpoints. + if (ev.type == softbus::device_bus::monitor::DeviceEventType::Serial || + ev.subsystem == QStringLiteral("tty")) { + const QByteArray hash = QCryptographicHash::hash(stableKey.toUtf8(), QCryptographicHash::Sha1).toHex(); + return QStringLiteral("dev_") + QString::fromUtf8(hash.left(12)); + } + if (!ev.serial.isEmpty()) { return QStringLiteral("dev_serial_") + ev.serial; }