Skip to content

Commit 5a5753a

Browse files
committed
feat(ll-driver-detect): add driver upgrade
1. Add driver upgrade and improves detection accuracy with remote repository integration. 2. Optimize unit tests.
1 parent 7331d3f commit 5a5753a

12 files changed

Lines changed: 334 additions & 309 deletions

apps/ll-driver-detect/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,4 @@ pfl_add_executable(
1616
./src/dbus_notifier.cpp
1717
LINK_LIBRARIES
1818
PRIVATE
19-
CLI11::CLI11
20-
linglong::linglong
21-
linglong::utils)
19+
linglong::linglong)

apps/ll-driver-detect/src/driver_detection_manager.cpp

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "driver_detection_manager.h"
66

7+
#include "linglong/utils/cmd.h"
78
#include "linglong/utils/log/log.h"
89
#include "nvidia_driver_detector.h"
910

@@ -14,9 +15,10 @@ DriverDetectionManager::DriverDetectionManager()
1415
registerDetectors();
1516
}
1617

17-
utils::error::Result<DriverDetectionResult> DriverDetectionManager::detectAllDrivers()
18+
utils::error::Result<std::vector<GraphicsDriverInfo>>
19+
DriverDetectionManager::detectAvailableDrivers()
1820
{
19-
DriverDetectionResult result;
21+
std::vector<GraphicsDriverInfo> detectedDrivers;
2022

2123
for (const auto &detector : detectors_) {
2224
auto detectionResult = detector->detect();
@@ -27,13 +29,13 @@ utils::error::Result<DriverDetectionResult> DriverDetectionManager::detectAllDri
2729
continue;
2830
}
2931

30-
result.detectedDrivers.emplace_back(*detectionResult);
32+
detectedDrivers.emplace_back(*detectionResult);
3133
LogD("Detected driver: {} version: {}",
3234
detectionResult->packageName,
33-
detectionResult->version);
35+
detectionResult->packageVersion);
3436
}
3537

36-
return result;
38+
return detectedDrivers;
3739
}
3840

3941
void DriverDetectionManager::registerDetectors()
@@ -46,4 +48,33 @@ void DriverDetectionManager::registerDetectors()
4648
LogD("Registered {} driver detectors", detectors_.size());
4749
}
4850

51+
linglong::utils::error::Result<void>
52+
DriverDetectionManager::installDriverPackage(const std::vector<GraphicsDriverInfo> &drivers)
53+
{
54+
LINGLONG_TRACE("installDriverPackage")
55+
56+
try {
57+
for (const auto &info : drivers) {
58+
LogD("Processing driver: Identify={}, Version={}, Package={}",
59+
info.identify,
60+
info.packageVersion,
61+
info.packageName);
62+
63+
// Execute ll-cli install command to install the package
64+
auto packageRef = info.packageName + "/" + info.packageVersion;
65+
auto ret = linglong::utils::Cmd("ll-cli").exec(
66+
{ "install", packageRef, "--repo", info.repoName });
67+
if (!ret) {
68+
return LINGLONG_ERR("Installation command failed: " + ret.error().message());
69+
}
70+
71+
LogD("Driver package installation command executed successfully: {}", *ret);
72+
}
73+
74+
return LINGLONG_OK;
75+
} catch (const std::exception &e) {
76+
return LINGLONG_ERR("Failed to install driver package: " + std::string(e.what()));
77+
}
78+
}
79+
4980
} // namespace linglong::driver::detect

apps/ll-driver-detect/src/driver_detection_manager.h

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,11 @@
66

77
#include "driver_detector.h"
88

9-
#include <algorithm>
109
#include <memory>
1110
#include <vector>
1211

1312
namespace linglong::driver::detect {
1413

15-
// Result of driver detection for all available drivers
16-
struct DriverDetectionResult
17-
{
18-
std::vector<GraphicsDriverInfo> detectedDrivers;
19-
20-
bool hasAvailableDrivers() const
21-
{
22-
return std::any_of(detectedDrivers.begin(), detectedDrivers.end(), [](const auto &driver) {
23-
return !driver.isInstalled;
24-
});
25-
}
26-
};
27-
2814
// Manager class that coordinates detection of multiple graphics drivers
2915
class DriverDetectionManager
3016
{
@@ -34,12 +20,12 @@ class DriverDetectionManager
3420

3521
// Detect all available graphics drivers on the system
3622
// Returns all detected drivers, or empty vector if none found
37-
utils::error::Result<DriverDetectionResult> detectAllDrivers();
23+
utils::error::Result<std::vector<GraphicsDriverInfo>> detectAvailableDrivers();
24+
linglong::utils::error::Result<void> installDriverPackage(const std::vector<GraphicsDriverInfo> &drivers);
3825

3926
protected:
4027
// Register all available driver detectors
4128
virtual void registerDetectors();
42-
4329
std::vector<std::unique_ptr<DriverDetector>> detectors_;
4430
};
4531

apps/ll-driver-detect/src/driver_detector.h

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,71 @@
66

77
#include "linglong/utils/error/error.h"
88

9+
#include <algorithm>
10+
#include <charconv>
911
#include <string>
12+
#include <string_view>
13+
#include <vector>
1014

1115
namespace linglong::driver::detect {
1216

17+
inline std::vector<int> splitVersion(std::string_view version)
18+
{
19+
constexpr size_t expected_components = 4;
20+
std::vector<int> components;
21+
components.reserve(expected_components);
22+
23+
auto convert_part = [](std::string_view part) -> int {
24+
int val = 0;
25+
auto result = std::from_chars(part.data(), part.data() + part.size(), val);
26+
if (result.ec == std::errc::invalid_argument
27+
|| result.ec == std::errc::result_out_of_range) {
28+
throw std::invalid_argument("Invalid version number component");
29+
}
30+
return val;
31+
};
32+
33+
size_t pos = 0;
34+
size_t prev = 0;
35+
36+
while ((pos = version.find('.', prev)) != std::string_view::npos) {
37+
components.push_back(convert_part(version.substr(prev, pos - prev)));
38+
prev = pos + 1;
39+
}
40+
41+
if (prev < version.size()) {
42+
components.push_back(convert_part(version.substr(prev)));
43+
}
44+
45+
return components;
46+
}
47+
48+
inline int compareVersions(std::string_view v1, std::string_view v2)
49+
{
50+
auto vec1 = splitVersion(v1);
51+
auto vec2 = splitVersion(v2);
52+
53+
const size_t size1 = vec1.size();
54+
const size_t size2 = vec2.size();
55+
const size_t max_size = std::max(size1, size2);
56+
57+
for (size_t i = 0; i < max_size; ++i) {
58+
int val1 = (i < size1) ? vec1[i] : 0;
59+
int val2 = (i < size2) ? vec2[i] : 0;
60+
61+
if (val1 != val2) {
62+
return (val1 > val2) ? 1 : -1;
63+
}
64+
}
65+
return 0;
66+
}
67+
1368
struct GraphicsDriverInfo
1469
{
1570
std::string identify;
16-
std::string version;
1771
std::string packageName;
18-
bool isInstalled = false;
72+
std::string packageVersion;
73+
std::string repoName{ "stable" };
1974
};
2075

2176
class DriverDetector
@@ -29,6 +84,9 @@ class DriverDetector
2984
// Check if the driver package is installed
3085
virtual utils::error::Result<bool> checkPackageInstalled(const std::string &packageName) = 0;
3186

87+
// Check if the driver package can upgraded
88+
virtual utils::error::Result<bool> checkPackageUpgradable(const std::string &packageName) = 0;
89+
3290
// Get the Identify of driver this detector handles
3391
virtual std::string getDriverIdentify() const = 0;
3492
};

apps/ll-driver-detect/src/main.cpp

Lines changed: 10 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include "driver_detection_manager.h"
1010
#include "driver_detector.h"
1111
#include "linglong/common/global/initialize.h"
12-
#include "linglong/utils/cmd.h"
1312
#include "linglong/utils/error/error.h"
1413
#include "linglong/utils/gettext.h"
1514
#include "tl/expected.hpp"
@@ -86,41 +85,6 @@ linglong::utils::error::Result<DriverDetectionConfigManager> setupConfigManager(
8685
return configManager;
8786
}
8887

89-
linglong::utils::error::Result<void>
90-
installDriverPackage(const std::vector<GraphicsDriverInfo> &drivers)
91-
{
92-
LINGLONG_TRACE("installDriverPackage")
93-
94-
try {
95-
for (const auto &driverInfo : drivers) {
96-
LogD("Processing driver: Identify={}, Version={}, Package={}, Installed={}",
97-
driverInfo.identify,
98-
driverInfo.version,
99-
driverInfo.packageName,
100-
driverInfo.isInstalled);
101-
102-
if (driverInfo.isInstalled) {
103-
LogD("Driver package is already installed: {}", driverInfo.packageName);
104-
continue;
105-
}
106-
107-
// Execute ll-cli install command to install the package
108-
auto ret = linglong::utils::Cmd("ll-cli").exec({ "install", driverInfo.packageName });
109-
if (!ret) {
110-
return LINGLONG_ERR("Installation command failed: " + ret.error().message());
111-
}
112-
113-
LogD("Driver package installation command executed successfully: {}", *ret);
114-
}
115-
116-
return LINGLONG_OK;
117-
} catch (const std::exception &e) {
118-
return LINGLONG_ERR("Failed to install driver package: " + std::string(e.what()));
119-
}
120-
121-
return LINGLONG_OK;
122-
}
123-
12488
} // namespace
12589

12690
int main(int argc, char *argv[])
@@ -191,7 +155,7 @@ int main(int argc, char *argv[])
191155
DriverDetectionManager detectionManager;
192156

193157
// Run driver detection and handling for all available drivers
194-
auto result = detectionManager.detectAllDrivers();
158+
auto result = detectionManager.detectAvailableDrivers();
195159

196160
if (!result) {
197161
LogF("Driver detection failed: {}", result.error().message());
@@ -201,8 +165,8 @@ int main(int argc, char *argv[])
201165

202166
const auto &detectionResult = *result;
203167

204-
if (!detectionResult.hasAvailableDrivers()) {
205-
std::cout << "No available graphics drivers detected or already installed" << std::endl;
168+
if (detectionResult.size() == 0) {
169+
LogD("No graphics drivers detected that require installation or upgrade");
206170
return 0;
207171
}
208172

@@ -211,22 +175,21 @@ int main(int argc, char *argv[])
211175
"will be performed."
212176
<< std::endl;
213177
std::cout << "Detected drivers:" << std::endl;
214-
for (const auto &driverInfo : detectionResult.detectedDrivers) {
178+
for (const auto &info : detectionResult) {
215179
std::cout << "----------------------------------------" << std::endl;
216-
std::cout << " Identify: " << driverInfo.identify << std::endl;
217-
std::cout << " Version: " << driverInfo.version << std::endl;
218-
std::cout << " Package: " << driverInfo.packageName << std::endl;
219-
std::cout << " Installed: " << (driverInfo.isInstalled ? "Yes" : "No") << std::endl;
180+
std::cout << " Identify: " << info.identify << std::endl;
181+
std::cout << " Version: " << info.packageVersion << std::endl;
182+
std::cout << " Package: " << info.packageName << std::endl;
220183
std::cout << "----------------------------------------" << std::endl;
221184
}
222185
return 0;
223186
}
224187

225-
LogD("Detected {} graphics driver(s)", detectionResult.detectedDrivers.size());
188+
LogD("Detected {} graphics driver(s)", detectionResult.size());
226189

227190
if (options.installOnly) {
228191
std::cout << "Install-only: installing detected drivers without notifications" << std::endl;
229-
auto installResult = installDriverPackage(detectionResult.detectedDrivers);
192+
auto installResult = detectionManager.installDriverPackage(detectionResult);
230193
if (!installResult) {
231194
LogW("Failed to install driver package {}: {}",
232195
options.packageName,
@@ -270,7 +233,7 @@ int main(int argc, char *argv[])
270233
if (response.action == kActionInstallNow && response.success) {
271234
LogD("User chose to install graphics driver");
272235

273-
auto installResult = installDriverPackage(detectionResult.detectedDrivers);
236+
auto installResult = detectionManager.installDriverPackage(detectionResult);
274237
if (!installResult) {
275238
LogW("Failed to install driver package: {}", installResult.error().message());
276239
return 1;

0 commit comments

Comments
 (0)