generated from general-packages/pika-pkg-template
Refactor GPU detection logic and remove unused PCI ID data
All checks were successful
PikaOS Package Build & Release (amd64-v3) / build (push) Successful in 50s
All checks were successful
PikaOS Package Build & Release (amd64-v3) / build (push) Successful in 50s
- Removed the `pci.ids` file as it is no longer needed for GPU detection. - Simplified GPU detection functions to streamline vendor identification and model name retrieval. - Enhanced memory reporting and improved overall structure of GPU information. - Updated version in changelog to reflect these changes.
This commit is contained in:
parent
a2c372b101
commit
9db38b0c4d
2
.github/release-nest-v3
vendored
2
.github/release-nest-v3
vendored
@ -1 +1 @@
|
||||
1
|
||||
2
|
@ -4,12 +4,6 @@ pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const pci_ids_path = "data/pci.ids";
|
||||
|
||||
// Create the options module
|
||||
const options = b.addOptions();
|
||||
options.addOption([]const u8, "pci_ids_path", pci_ids_path);
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "pikafetch",
|
||||
.root_source_file = .{ .cwd_relative = "src/main.zig" },
|
||||
@ -17,9 +11,6 @@ pub fn build(b: *std.Build) void {
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// Add options to the executable
|
||||
exe.root_module.addOptions("build_options", options);
|
||||
|
||||
exe.linkLibC();
|
||||
b.installArtifact(exe);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
pikafetch (0.1.0-101pika6) pika; urgency=medium
|
||||
pikafetch (0.1.0-101pika7) pika; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
|
@ -18,7 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Notes:
|
||||
The contents of src/data/pci.ids is licensed under GNU General Public License (version 2 or higher)
|
||||
SOFTWARE.
|
File diff suppressed because it is too large
Load Diff
@ -3,26 +3,8 @@ const mem = std.mem;
|
||||
const fs = std.fs;
|
||||
const ArrayList = std.ArrayList;
|
||||
const allocPrint = std.fmt.allocPrint;
|
||||
|
||||
const VendorId = struct {
|
||||
const APPLE = 0x106b;
|
||||
const AMD = 0x1002;
|
||||
const AMD_2 = 0x1022;
|
||||
const INTEL = 0x8086;
|
||||
const INTEL_2 = 0x8087;
|
||||
const INTEL_3 = 0x03e7;
|
||||
const NVIDIA = 0x10de;
|
||||
const NVIDIA_2 = 0x12d2;
|
||||
const NVIDIA_3 = 0x0955;
|
||||
const MTHREADS = 0x1ed5;
|
||||
const QUALCOMM = 0x5143;
|
||||
const MTK = 0x14c3;
|
||||
const VMWARE = 0x15ad;
|
||||
const REDHAT = 0x1af4;
|
||||
const PARALLEL = 0x1ab8;
|
||||
const MICROSOFT = 0x1414;
|
||||
const ORACLE = 0x108e;
|
||||
};
|
||||
const vector = @import("std").simd;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const GPUInfo = struct {
|
||||
vendor: []const u8,
|
||||
@ -76,41 +58,7 @@ pub fn getGPUInfo(allocator: mem.Allocator) ![][]const u8 {
|
||||
if (!mem.startsWith(u8, entry.name, "card")) continue;
|
||||
if (mem.indexOf(u8, entry.name, "-")) |_| continue;
|
||||
|
||||
const vendor_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/vendor", .{entry.name});
|
||||
defer allocator.free(vendor_path);
|
||||
|
||||
const vendor_file = fs.openFileAbsolute(vendor_path, .{}) catch continue;
|
||||
defer vendor_file.close();
|
||||
|
||||
var vendor_buf: [32]u8 = undefined;
|
||||
const vendor_len = vendor_file.readAll(&vendor_buf) catch continue;
|
||||
const vendor_str = mem.trim(u8, vendor_buf[0..vendor_len], "\n\r \t0x");
|
||||
|
||||
const vendor_id = std.fmt.parseInt(u32, vendor_str, 16) catch continue;
|
||||
|
||||
switch (vendor_id) {
|
||||
VendorId.NVIDIA, VendorId.NVIDIA_2, VendorId.NVIDIA_3 => {
|
||||
if (try detectNvidiaGPU(allocator, entry.name)) |gpu| {
|
||||
try gpus.append(gpu);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
VendorId.AMD, VendorId.AMD_2 => {
|
||||
if (try detectAMDGPU(allocator, entry.name, vendor_id)) |gpu| {
|
||||
try gpus.append(gpu);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
VendorId.INTEL, VendorId.INTEL_2, VendorId.INTEL_3 => {
|
||||
if (try detectIntelGPU(allocator, entry.name)) |gpu| {
|
||||
try gpus.append(gpu);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
if (try detectGenericGPU(allocator, entry.name, vendor_id)) |gpu| {
|
||||
if (try detectGPU(allocator, entry.name)) |gpu| {
|
||||
try gpus.append(gpu);
|
||||
}
|
||||
}
|
||||
@ -123,8 +71,21 @@ pub fn getGPUInfo(allocator: mem.Allocator) ![][]const u8 {
|
||||
return gpus.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn detectNvidiaGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
||||
// First try to get device ID for PCI lookup
|
||||
fn detectGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
||||
if (try queryHwdb(allocator, card_name)) |gpu| {
|
||||
return gpu;
|
||||
}
|
||||
|
||||
const vendor_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/vendor", .{card_name});
|
||||
defer allocator.free(vendor_path);
|
||||
|
||||
const vendor_file = fs.openFileAbsolute(vendor_path, .{}) catch return null;
|
||||
defer vendor_file.close();
|
||||
|
||||
var vendor_buf: [32]u8 = undefined;
|
||||
const vendor_len = vendor_file.readAll(&vendor_buf) catch return null;
|
||||
const vendor_str = mem.trim(u8, vendor_buf[0..vendor_len], "\n\r \t0x");
|
||||
|
||||
const device_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/device", .{card_name});
|
||||
defer allocator.free(device_path);
|
||||
|
||||
@ -135,257 +96,174 @@ fn detectNvidiaGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8
|
||||
const device_len = device_file.readAll(&device_buf) catch return null;
|
||||
const device_str = mem.trim(u8, device_buf[0..device_len], "\n\r \t0x");
|
||||
|
||||
const device_id = std.fmt.parseInt(u32, device_str, 16) catch return null;
|
||||
|
||||
// Try /proc/driver/nvidia first
|
||||
const proc_path = try allocPrint(allocator, "/proc/driver/nvidia/gpus/{s}/information", .{card_name});
|
||||
defer allocator.free(proc_path);
|
||||
|
||||
var model_name: ?[]const u8 = null;
|
||||
var vbios_version: ?[]const u8 = null;
|
||||
var memory_size: ?u64 = null;
|
||||
|
||||
// Try to read from nvidia proc
|
||||
const info_file = fs.openFileAbsolute(proc_path, .{}) catch null;
|
||||
if (info_file) |file| {
|
||||
defer file.close();
|
||||
var buf: [1024]u8 = undefined;
|
||||
const bytes_read = file.readAll(&buf) catch 0;
|
||||
if (bytes_read > 0) {
|
||||
const content = buf[0..bytes_read];
|
||||
|
||||
var lines = mem.split(u8, content, "\n");
|
||||
while (lines.next()) |line| {
|
||||
if (mem.indexOf(u8, line, "Model:")) |_| {
|
||||
const start = mem.indexOf(u8, line, ":").? + 1;
|
||||
model_name = mem.trim(u8, line[start..], " \t\r\n");
|
||||
} else if (mem.indexOf(u8, line, "Video BIOS:")) |_| {
|
||||
const start = mem.indexOf(u8, line, ":").? + 1;
|
||||
vbios_version = mem.trim(u8, line[start..], " \t\r\n");
|
||||
} else if (mem.indexOf(u8, line, "Video Memory:")) |_| {
|
||||
const start = mem.indexOf(u8, line, ":").? + 1;
|
||||
const mem_str = mem.trim(u8, line[start..], " \t\r\nMB");
|
||||
memory_size = std.fmt.parseInt(u64, mem_str, 10) catch null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we couldn't get model name from nvidia proc, try product name
|
||||
if (model_name == null) {
|
||||
const product_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/product_name", .{card_name});
|
||||
defer allocator.free(product_path);
|
||||
|
||||
const product_file = fs.openFileAbsolute(product_path, .{}) catch null;
|
||||
if (product_file) |file| {
|
||||
defer file.close();
|
||||
var product_buf: [256]u8 = undefined;
|
||||
const len = file.readAll(&product_buf) catch 0;
|
||||
if (len > 0) {
|
||||
model_name = mem.trim(u8, product_buf[0..len], "\n\r \t");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If still no model name, try PCI lookup
|
||||
if (model_name == null) {
|
||||
model_name = if (findPCIName(VendorId.NVIDIA, device_id)) |name|
|
||||
name
|
||||
else
|
||||
try allocPrint(allocator, "NVIDIA GPU (0x{x:0>4})", .{device_id});
|
||||
}
|
||||
|
||||
// Get driver info if not already found from nvidia proc
|
||||
if (vbios_version == null) {
|
||||
const driver_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/driver", .{card_name});
|
||||
defer allocator.free(driver_path);
|
||||
|
||||
vbios_version = blk: {
|
||||
var dir_handle = fs.openDirAbsolute(driver_path, .{}) catch break :blk null;
|
||||
defer dir_handle.close();
|
||||
|
||||
var path_buf: [256]u8 = undefined;
|
||||
const path = dir_handle.readLink("driver", &path_buf) catch break :blk null;
|
||||
break :blk std.fs.path.basename(path);
|
||||
};
|
||||
}
|
||||
const model = try allocPrint(allocator, "(vendor: 0x{s}, device: 0x{s})", .{ vendor_str, device_str });
|
||||
errdefer allocator.free(model);
|
||||
|
||||
const gpu_info = GPUInfo{
|
||||
.vendor = "NVIDIA",
|
||||
.model = model_name.?, // Safe because we always set it above
|
||||
.driver = vbios_version,
|
||||
.memory = memory_size,
|
||||
};
|
||||
|
||||
const formatted = try gpu_info.format(allocator);
|
||||
return formatted;
|
||||
}
|
||||
|
||||
fn detectAMDGPU(allocator: mem.Allocator, card_name: []const u8, vendor_id: u32) !?[]const u8 {
|
||||
// Get device ID
|
||||
const device_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/device", .{card_name});
|
||||
defer allocator.free(device_path);
|
||||
|
||||
const device_file = fs.openFileAbsolute(device_path, .{}) catch return null;
|
||||
defer device_file.close();
|
||||
|
||||
var device_buf: [32]u8 = undefined;
|
||||
const device_len = device_file.readAll(&device_buf) catch return null;
|
||||
const device_str = mem.trim(u8, device_buf[0..device_len], "\n\r \t0x");
|
||||
|
||||
const device_id = std.fmt.parseInt(u32, device_str, 16) catch return null;
|
||||
|
||||
// Get model name from PCI database
|
||||
const model_name = if (findPCIName(vendor_id, device_id)) |name|
|
||||
name
|
||||
else
|
||||
try allocPrint(allocator, "GPU (0x{x:0>4})", .{device_id});
|
||||
|
||||
// Get driver info
|
||||
const driver = blk: {
|
||||
const driver_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/driver", .{card_name});
|
||||
defer allocator.free(driver_path);
|
||||
|
||||
var dir_handle = fs.openDirAbsolute(driver_path, .{}) catch break :blk null;
|
||||
defer dir_handle.close();
|
||||
|
||||
var path_buf: [256]u8 = undefined;
|
||||
const path = dir_handle.readLink("driver", &path_buf) catch break :blk null;
|
||||
break :blk std.fs.path.basename(path);
|
||||
};
|
||||
|
||||
// Get VRAM info
|
||||
var memory: ?u64 = null;
|
||||
const vram_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/mem_info_vram_total", .{card_name});
|
||||
defer allocator.free(vram_path);
|
||||
|
||||
if (fs.openFileAbsolute(vram_path, .{})) |vram_file| {
|
||||
defer vram_file.close();
|
||||
var vram_buf: [32]u8 = undefined;
|
||||
if (vram_file.readAll(&vram_buf)) |len| {
|
||||
const vram_str = mem.trim(u8, vram_buf[0..len], "\n\r \t");
|
||||
if (std.fmt.parseInt(u64, vram_str, 10)) |vram_bytes| {
|
||||
memory = vram_bytes / (1024 * 1024); // Convert to MB
|
||||
} else |_| {}
|
||||
} else |_| {}
|
||||
} else |_| {}
|
||||
|
||||
const gpu_info = GPUInfo{
|
||||
.vendor = "AMD",
|
||||
.model = model_name,
|
||||
.driver = driver,
|
||||
.memory = memory,
|
||||
};
|
||||
|
||||
const formatted = try gpu_info.format(allocator);
|
||||
return formatted;
|
||||
}
|
||||
|
||||
fn detectIntelGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
||||
const product_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/product_name", .{card_name});
|
||||
defer allocator.free(product_path);
|
||||
|
||||
var product_name: []const u8 = undefined;
|
||||
if (fs.openFileAbsolute(product_path, .{})) |product_file| {
|
||||
defer product_file.close();
|
||||
var product_buf: [256]u8 = undefined;
|
||||
const product_len = product_file.readAll(&product_buf) catch return null;
|
||||
product_name = mem.trim(u8, product_buf[0..product_len], "\n\r \t");
|
||||
} else |_| {
|
||||
return null;
|
||||
}
|
||||
|
||||
const driver_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/driver", .{card_name});
|
||||
defer allocator.free(driver_path);
|
||||
|
||||
const driver = blk: {
|
||||
var dir_handle = fs.openDirAbsolute(driver_path, .{}) catch break :blk null;
|
||||
defer dir_handle.close();
|
||||
|
||||
var path_buf: [256]u8 = undefined;
|
||||
const path = dir_handle.readLink("driver", &path_buf) catch break :blk null;
|
||||
break :blk std.fs.path.basename(path);
|
||||
};
|
||||
|
||||
const gpu_info = GPUInfo{
|
||||
.vendor = "Intel",
|
||||
.model = product_name,
|
||||
.driver = driver,
|
||||
.memory = null,
|
||||
};
|
||||
|
||||
const formatted = try gpu_info.format(allocator);
|
||||
return formatted;
|
||||
}
|
||||
|
||||
fn findPCIName(vendor_id: u32, device_id: u32) ?[]const u8 {
|
||||
const pci_data = @embedFile("../../data/pci.ids");
|
||||
var lines = mem.split(u8, pci_data, "\n");
|
||||
var current_vendor: ?u32 = null;
|
||||
|
||||
while (lines.next()) |line| {
|
||||
const trimmed = mem.trim(u8, line, " \r\n");
|
||||
if (trimmed.len == 0 or trimmed[0] == '#') continue;
|
||||
|
||||
// Count leading tabs
|
||||
const tab_count = for (trimmed, 0..) |c, i| {
|
||||
if (c != '\t') break @as(usize, @intCast(i));
|
||||
} else trimmed.len;
|
||||
|
||||
// No tabs = vendor line
|
||||
if (tab_count == 0) {
|
||||
const space_idx = mem.indexOf(u8, trimmed, " ") orelse continue;
|
||||
const vendor_str = trimmed[0..space_idx];
|
||||
current_vendor = std.fmt.parseInt(u32, vendor_str, 16) catch continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// One tab = device line
|
||||
if (tab_count == 1 and current_vendor != null and current_vendor.? == vendor_id) {
|
||||
const device_line = trimmed[tab_count..];
|
||||
const space_idx = mem.indexOf(u8, device_line, " ") orelse continue;
|
||||
const device_str = device_line[0..space_idx];
|
||||
const found_device = std.fmt.parseInt(u32, device_str, 16) catch continue;
|
||||
|
||||
if (found_device == device_id) {
|
||||
return device_line[space_idx + 1 ..];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
fn detectGenericGPU(allocator: mem.Allocator, card_name: []const u8, vendor_id: u32) !?[]const u8 {
|
||||
const device_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/device", .{card_name});
|
||||
defer allocator.free(device_path);
|
||||
|
||||
const device_file = fs.openFileAbsolute(device_path, .{}) catch return null;
|
||||
defer device_file.close();
|
||||
|
||||
var device_buf: [32]u8 = undefined;
|
||||
const device_len = device_file.readAll(&device_buf) catch return null;
|
||||
const device_str = mem.trim(u8, device_buf[0..device_len], "\n\r \t0x");
|
||||
|
||||
const device_id = std.fmt.parseInt(u32, device_str, 16) catch return null;
|
||||
|
||||
const vendor_name = switch (vendor_id) {
|
||||
VendorId.AMD, VendorId.AMD_2 => "AMD",
|
||||
VendorId.INTEL, VendorId.INTEL_2, VendorId.INTEL_3 => "Intel",
|
||||
VendorId.NVIDIA, VendorId.NVIDIA_2, VendorId.NVIDIA_3 => "NVIDIA",
|
||||
else => "Unknown",
|
||||
};
|
||||
|
||||
const gpu_info = GPUInfo{
|
||||
.vendor = vendor_name,
|
||||
.model = if (findPCIName(vendor_id, device_id)) |name|
|
||||
name
|
||||
else
|
||||
try allocPrint(allocator, "GPU (0x{x:0>4})", .{device_id}),
|
||||
.vendor = "GPU",
|
||||
.model = model,
|
||||
.driver = null,
|
||||
.memory = null,
|
||||
};
|
||||
|
||||
const formatted = try gpu_info.format(allocator);
|
||||
allocator.free(model);
|
||||
return formatted;
|
||||
}
|
||||
|
||||
fn getShortVendorName(vendor: []const u8) []const u8 {
|
||||
if (mem.startsWith(u8, vendor, "Advanced Micro Devices")) return "AMD";
|
||||
if (mem.startsWith(u8, vendor, "AMD")) return "AMD";
|
||||
if (mem.startsWith(u8, vendor, "NVIDIA Corporation")) return "NVIDIA";
|
||||
if (mem.startsWith(u8, vendor, "Intel Corporation")) return "Intel";
|
||||
return vendor;
|
||||
}
|
||||
|
||||
fn simdStartsWith(haystack: []const u8, needle: []const u8) bool {
|
||||
if (haystack.len < needle.len) return false;
|
||||
|
||||
const Vec = @Vector(32, u8);
|
||||
var i: usize = 0;
|
||||
|
||||
while (i + 32 <= needle.len) : (i += 32) {
|
||||
const hay = @as(Vec, haystack[i .. i + 32][0..32].*);
|
||||
const ned = @as(Vec, needle[i .. i + 32][0..32].*);
|
||||
const mask = hay == ned;
|
||||
if (!@reduce(.And, mask)) return false;
|
||||
}
|
||||
|
||||
const Vec8 = @Vector(8, u8);
|
||||
while (i + 8 <= needle.len) : (i += 8) {
|
||||
const hay = @as(Vec8, haystack[i .. i + 8][0..8].*);
|
||||
const ned = @as(Vec8, needle[i .. i + 8][0..8].*);
|
||||
const mask = hay == ned;
|
||||
if (!@reduce(.And, mask)) return false;
|
||||
}
|
||||
|
||||
while (i < needle.len) : (i += 1) {
|
||||
if (haystack[i] != needle[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn cleanModelName(model: []const u8) []const u8 {
|
||||
var start: usize = 0;
|
||||
while (start < model.len and (model[start] == ' ' or std.ascii.isDigit(model[start]))) : (start += 1) {}
|
||||
|
||||
const trimmed = model[start..];
|
||||
|
||||
if (mem.startsWith(u8, trimmed, "AMD")) return trimmed["AMD".len..];
|
||||
if (mem.startsWith(u8, trimmed, "NVIDIA")) return trimmed["NVIDIA".len..];
|
||||
if (mem.startsWith(u8, trimmed, "Intel")) return trimmed["Intel".len..];
|
||||
|
||||
if (mem.indexOf(u8, trimmed, "[")) |bracket_start| {
|
||||
if (mem.indexOf(u8, trimmed[bracket_start..], "]")) |bracket_end| {
|
||||
return trimmed[bracket_start + 1 .. bracket_start + bracket_end];
|
||||
}
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
fn queryHwdb(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
||||
const modalias_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/modalias", .{card_name});
|
||||
defer allocator.free(modalias_path);
|
||||
|
||||
const modalias_file = fs.openFileAbsolute(modalias_path, .{}) catch return null;
|
||||
defer modalias_file.close();
|
||||
|
||||
var modalias_buf: [256]u8 = undefined;
|
||||
const modalias = modalias_file.readAll(&modalias_buf) catch return null;
|
||||
const modalias_str = mem.trimRight(u8, modalias_buf[0..modalias], "\n");
|
||||
|
||||
if (!mem.startsWith(u8, modalias_str, "pci:")) return null;
|
||||
|
||||
var vendor_id: ?[]const u8 = null;
|
||||
var device_id: ?[]const u8 = null;
|
||||
|
||||
var modalias_idx: usize = 4;
|
||||
while (modalias_idx < modalias_str.len) : (modalias_idx += 1) {
|
||||
if (modalias_str[modalias_idx] == 'v' and modalias_idx + 9 <= modalias_str.len) {
|
||||
vendor_id = modalias_str[modalias_idx + 1 .. modalias_idx + 9];
|
||||
var j = modalias_idx + 9;
|
||||
while (j < modalias_str.len) : (j += 1) {
|
||||
if (modalias_str[j] == 'd' and j + 9 <= modalias_str.len) {
|
||||
device_id = modalias_str[j + 1 .. j + 9];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vendor_id == null or device_id == null) return null;
|
||||
|
||||
const hwdb_file = fs.openFileAbsolute("/usr/lib/udev/hwdb.d/20-pci-vendor-model.hwdb", .{}) catch return null;
|
||||
defer hwdb_file.close();
|
||||
|
||||
const stat = try hwdb_file.stat();
|
||||
const mapped = try std.posix.mmap(
|
||||
null,
|
||||
@as(usize, @intCast(stat.size)),
|
||||
std.posix.PROT.READ,
|
||||
.{ .TYPE = std.os.linux.MAP_TYPE.PRIVATE },
|
||||
hwdb_file.handle,
|
||||
0,
|
||||
);
|
||||
defer std.posix.munmap(mapped);
|
||||
|
||||
var vendor_name: ?[]const u8 = null;
|
||||
var model_name: ?[]const u8 = null;
|
||||
|
||||
const vendor_pattern = try allocPrint(allocator, "pci:v{s}*", .{vendor_id.?});
|
||||
defer allocator.free(vendor_pattern);
|
||||
const device_pattern = try allocPrint(allocator, "pci:v{s}d{s}*", .{ vendor_id.?, device_id.? });
|
||||
defer allocator.free(device_pattern);
|
||||
|
||||
var it = mem.split(u8, mapped, "\n");
|
||||
while (it.next()) |line| {
|
||||
const trimmed = mem.trim(u8, line, " \t\r\n");
|
||||
if (trimmed.len == 0 or simdStartsWith(trimmed, "#")) continue;
|
||||
|
||||
if (vendor_name == null and simdStartsWith(trimmed, vendor_pattern)) {
|
||||
if (it.next()) |next_line| {
|
||||
const next_trimmed = mem.trim(u8, next_line, " \t\r\n");
|
||||
if (simdStartsWith(next_trimmed, "ID_VENDOR_FROM_DATABASE=")) {
|
||||
const raw_vendor = next_trimmed["ID_VENDOR_FROM_DATABASE=".len..];
|
||||
vendor_name = try allocator.dupe(u8, raw_vendor);
|
||||
}
|
||||
}
|
||||
} else if (model_name == null and simdStartsWith(trimmed, device_pattern)) {
|
||||
if (it.next()) |next_line| {
|
||||
const next_trimmed = mem.trim(u8, next_line, " \t\r\n");
|
||||
if (simdStartsWith(next_trimmed, "ID_MODEL_FROM_DATABASE=")) {
|
||||
const raw_model = next_trimmed["ID_MODEL_FROM_DATABASE=".len..];
|
||||
model_name = try allocator.dupe(u8, raw_model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vendor_name != null and model_name != null) break;
|
||||
}
|
||||
|
||||
if (vendor_name != null and model_name != null) {
|
||||
const gpu_info = GPUInfo{
|
||||
.vendor = try allocator.dupe(u8, getShortVendorName(vendor_name.?)),
|
||||
.model = try allocator.dupe(u8, cleanModelName(model_name.?)),
|
||||
.driver = null,
|
||||
.memory = null,
|
||||
};
|
||||
|
||||
const formatted = try gpu_info.format(allocator);
|
||||
allocator.free(gpu_info.vendor);
|
||||
allocator.free(gpu_info.model);
|
||||
if (vendor_name != null) allocator.free(vendor_name.?);
|
||||
if (model_name != null) allocator.free(model_name.?);
|
||||
return formatted;
|
||||
}
|
||||
|
||||
if (vendor_name != null) allocator.free(vendor_name.?);
|
||||
if (model_name != null) allocator.free(model_name.?);
|
||||
return null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user