generated from general-packages/pika-pkg-template
Update GPU detection logic
All checks were successful
PikaOS Package Build & Release (amd64-v3) / build (push) Successful in 49s
All checks were successful
PikaOS Package Build & Release (amd64-v3) / build (push) Successful in 49s
- Enhanced GPU detection functions to support multiple GPU vendors (NVIDIA, AMD, Intel) and improved memory reporting.
This commit is contained in:
parent
946c64d5ab
commit
f118503903
2
.github/release-nest-v3
vendored
2
.github/release-nest-v3
vendored
@ -1 +1 @@
|
|||||||
2
|
3
|
@ -1,4 +1,4 @@
|
|||||||
pikafetch (0.1.0-101pika2) pika; urgency=medium
|
pikafetch (0.1.0-101pika3) pika; urgency=medium
|
||||||
|
|
||||||
* Initial release.
|
* Initial release.
|
||||||
|
|
||||||
|
@ -1,7 +1,62 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const mem = std.mem;
|
||||||
|
const fs = std.fs;
|
||||||
|
const ArrayList = std.ArrayList;
|
||||||
|
const allocPrint = std.fmt.allocPrint;
|
||||||
|
|
||||||
pub fn getGPUInfo(allocator: std.mem.Allocator) ![][]const u8 {
|
const VendorId = struct {
|
||||||
var gpus = std.ArrayList([]const u8).init(allocator);
|
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 GPUInfo = struct {
|
||||||
|
vendor: []const u8,
|
||||||
|
model: []const u8,
|
||||||
|
driver: ?[]const u8,
|
||||||
|
memory: ?u64,
|
||||||
|
|
||||||
|
pub fn format(self: GPUInfo, allocator: mem.Allocator) ![]const u8 {
|
||||||
|
if (self.memory) |memm| {
|
||||||
|
if (self.driver) |drv| {
|
||||||
|
return allocPrint(allocator, "{s} {s} ({s}, {d}MB)", .{
|
||||||
|
self.vendor, self.model, drv, memm,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return allocPrint(allocator, "{s} {s} ({d}MB)", .{
|
||||||
|
self.vendor, self.model, memm,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (self.driver) |drv| {
|
||||||
|
return allocPrint(allocator, "{s} {s} ({s})", .{
|
||||||
|
self.vendor, self.model, drv,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return allocPrint(allocator, "{s} {s}", .{
|
||||||
|
self.vendor, self.model,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn getGPUInfo(allocator: mem.Allocator) ![][]const u8 {
|
||||||
|
var gpus = ArrayList([]const u8).init(allocator);
|
||||||
errdefer {
|
errdefer {
|
||||||
for (gpus.items) |gpu| {
|
for (gpus.items) |gpu| {
|
||||||
allocator.free(gpu);
|
allocator.free(gpu);
|
||||||
@ -9,115 +64,55 @@ pub fn getGPUInfo(allocator: std.mem.Allocator) ![][]const u8 {
|
|||||||
gpus.deinit();
|
gpus.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
var card_num: u32 = 0;
|
var dir = fs.openDirAbsolute("/sys/class/drm", .{ .iterate = true }) catch {
|
||||||
while (true) : (card_num += 1) {
|
const unknown = try allocator.dupe(u8, "Unknown GPU");
|
||||||
const card_path = try std.fmt.allocPrint(allocator, "/sys/class/drm/card{d}/device", .{card_num});
|
try gpus.append(unknown);
|
||||||
defer allocator.free(card_path);
|
return gpus.toOwnedSlice();
|
||||||
|
};
|
||||||
|
defer dir.close();
|
||||||
|
|
||||||
const vendor_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "{s}/vendor", .{card_path}), .{}) catch |err| switch (err) {
|
var iter = dir.iterate();
|
||||||
error.FileNotFound => break, // No more cards found
|
while (try iter.next()) |entry| {
|
||||||
else => return err,
|
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();
|
defer vendor_file.close();
|
||||||
|
|
||||||
const device_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "{s}/device", .{card_path}), .{}) catch |err| switch (err) {
|
|
||||||
error.FileNotFound => continue,
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
defer device_file.close();
|
|
||||||
|
|
||||||
var vendor_buf: [32]u8 = undefined;
|
var vendor_buf: [32]u8 = undefined;
|
||||||
var device_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_bytes = try vendor_file.readAll(&vendor_buf);
|
const vendor_id = std.fmt.parseInt(u32, vendor_str, 16) catch continue;
|
||||||
const device_bytes = try device_file.readAll(&device_buf);
|
|
||||||
|
|
||||||
const vendor_str = std.mem.trim(u8, vendor_buf[0..vendor_bytes], "\n\r \t0x");
|
switch (vendor_id) {
|
||||||
const device_str = std.mem.trim(u8, device_buf[0..device_bytes], "\n\r \t0x");
|
VendorId.NVIDIA, VendorId.NVIDIA_2, VendorId.NVIDIA_3 => {
|
||||||
|
if (try detectNvidiaGPU(allocator, entry.name)) |gpu| {
|
||||||
const vendor_id = try std.fmt.parseInt(u32, vendor_str, 16);
|
try gpus.append(gpu);
|
||||||
const device_id = try std.fmt.parseInt(u32, device_str, 16);
|
continue;
|
||||||
|
|
||||||
const modalias_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "/sys/class/drm/card{d}/device/modalias", .{card_num}), .{}) catch |err| switch (err) {
|
|
||||||
error.FileNotFound => null,
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
defer if (modalias_file) |f| f.close();
|
|
||||||
|
|
||||||
const name_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "/sys/class/drm/card{d}/device/product", .{card_num}), .{}) catch |err| switch (err) {
|
|
||||||
error.FileNotFound => null,
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
defer if (name_file) |f| f.close();
|
|
||||||
|
|
||||||
const model_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "/sys/class/drm/card{d}/device/model", .{card_num}), .{}) catch |err| switch (err) {
|
|
||||||
error.FileNotFound => null,
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
defer if (model_file) |f| f.close();
|
|
||||||
|
|
||||||
const subsystem_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "/sys/class/drm/card{d}/device/subsystem_device", .{card_num}), .{}) catch |err| switch (err) {
|
|
||||||
error.FileNotFound => null,
|
|
||||||
else => return err,
|
|
||||||
};
|
|
||||||
defer if (subsystem_file) |f| f.close();
|
|
||||||
|
|
||||||
var name_buf: [256]u8 = undefined;
|
|
||||||
var gpu_name: []const u8 = "";
|
|
||||||
|
|
||||||
if (name_file) |f| {
|
|
||||||
const name_bytes = try f.readAll(&name_buf);
|
|
||||||
const name = std.mem.trim(u8, name_buf[0..name_bytes], "\n\r \t");
|
|
||||||
if (name.len > 0) {
|
|
||||||
gpu_name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpu_name.len == 0) {
|
|
||||||
if (model_file) |f| {
|
|
||||||
const name_bytes = try f.readAll(&name_buf);
|
|
||||||
const name = std.mem.trim(u8, name_buf[0..name_bytes], "\n\r \t");
|
|
||||||
if (name.len > 0) {
|
|
||||||
gpu_name = name;
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
VendorId.AMD, VendorId.AMD_2 => {
|
||||||
|
if (try detectAMDGPU(allocator, entry.name)) |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 => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Declare and initialize the driver variable
|
if (try detectGenericGPU(allocator, entry.name, vendor_id)) |gpu| {
|
||||||
var dir_handle = std.fs.openDirAbsolute(card_path, .{}) catch null;
|
try gpus.append(gpu);
|
||||||
const driver = if (dir_handle) |*dir| blk: {
|
}
|
||||||
defer dir.close();
|
|
||||||
var path_buf: [256]u8 = undefined;
|
|
||||||
if (dir.readLink("driver", &path_buf)) |path| {
|
|
||||||
break :blk std.fs.path.basename(path);
|
|
||||||
} else |_| {
|
|
||||||
break :blk null;
|
|
||||||
}
|
|
||||||
} else null;
|
|
||||||
|
|
||||||
const gpu_info = if (findPCIName(vendor_id, device_id)) |model|
|
|
||||||
try std.fmt.allocPrint(allocator, "{s} {s}", .{
|
|
||||||
switch (vendor_id) {
|
|
||||||
0x1002 => "AMD",
|
|
||||||
0x10de => "NVIDIA",
|
|
||||||
0x8086 => "Intel",
|
|
||||||
else => "Unknown",
|
|
||||||
},
|
|
||||||
model,
|
|
||||||
})
|
|
||||||
else
|
|
||||||
try std.fmt.allocPrint(allocator, "{s} GPU (0x{x:0>4}){s}", .{
|
|
||||||
switch (vendor_id) {
|
|
||||||
0x1002 => "AMD",
|
|
||||||
0x10de => "NVIDIA",
|
|
||||||
0x8086 => "Intel",
|
|
||||||
else => "Unknown",
|
|
||||||
},
|
|
||||||
device_id,
|
|
||||||
if (driver) |d| try std.fmt.allocPrint(allocator, ", {s}", .{d}) else "",
|
|
||||||
});
|
|
||||||
|
|
||||||
try gpus.append(gpu_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpus.items.len == 0) {
|
if (gpus.items.len == 0) {
|
||||||
@ -128,33 +123,193 @@ pub fn getGPUInfo(allocator: std.mem.Allocator) ![][]const u8 {
|
|||||||
return gpus.toOwnedSlice();
|
return gpus.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
const pci_ids = @embedFile("../../data/pci.ids");
|
fn detectNvidiaGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
||||||
|
const proc_path = try allocPrint(allocator, "/proc/driver/nvidia/gpus/{s}/information", .{card_name});
|
||||||
|
defer allocator.free(proc_path);
|
||||||
|
|
||||||
|
const info_file = fs.openFileAbsolute(proc_path, .{}) catch return null;
|
||||||
|
defer info_file.close();
|
||||||
|
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
const bytes_read = info_file.readAll(&buf) catch return null;
|
||||||
|
const content = buf[0..bytes_read];
|
||||||
|
|
||||||
|
var model_name: ?[]const u8 = null;
|
||||||
|
var vbios_version: ?[]const u8 = null;
|
||||||
|
var memory_size: ?u64 = null;
|
||||||
|
|
||||||
|
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 (model_name) |model| {
|
||||||
|
const gpu_info = GPUInfo{
|
||||||
|
.vendor = "NVIDIA",
|
||||||
|
.model = model,
|
||||||
|
.driver = vbios_version,
|
||||||
|
.memory = memory_size,
|
||||||
|
};
|
||||||
|
const formatted = try gpu_info.format(allocator);
|
||||||
|
return formatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detectAMDGPU(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 = "AMD",
|
||||||
|
.model = product_name,
|
||||||
|
.driver = driver,
|
||||||
|
.memory = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
fn findPCIName(vendor_id: u32, device_id: u32) ?[]const u8 {
|
||||||
var lines = std.mem.splitSequence(u8, pci_ids, "\n");
|
const pci_data = @embedFile("../../data/pci.ids");
|
||||||
|
var lines = mem.split(u8, pci_data, "\n");
|
||||||
var current_vendor: ?u32 = null;
|
var current_vendor: ?u32 = null;
|
||||||
|
|
||||||
while (lines.next()) |line| {
|
while (lines.next()) |line| {
|
||||||
if (line.len == 0 or line[0] == '#') continue;
|
const trimmed = mem.trim(u8, line, " \t\r");
|
||||||
|
if (trimmed.len == 0 or trimmed[0] == '#') continue;
|
||||||
|
|
||||||
if (line[0] != '\t') {
|
// Check if this is a vendor line (no tabs at start)
|
||||||
if (line.len < 4) continue;
|
if (trimmed[0] != '\t') {
|
||||||
const vid = std.fmt.parseInt(u32, line[0..4], 16) catch continue;
|
// Parse vendor ID
|
||||||
current_vendor = vid;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_vendor) |vid| {
|
// If we found our vendor, look for the device
|
||||||
if (vid != vendor_id) continue;
|
if (current_vendor) |vendor| {
|
||||||
|
if (vendor != vendor_id) continue;
|
||||||
|
|
||||||
if (line[0] == '\t' and line[1] != '\t') {
|
// Device lines have one tab
|
||||||
if (line.len < 5) continue;
|
if (trimmed[0] != '\t' or trimmed.len < 2) continue;
|
||||||
const did = std.fmt.parseInt(u32, std.mem.trim(u8, line[1..5], " "), 16) catch continue;
|
const device_line = mem.trim(u8, trimmed[1..], " \t");
|
||||||
if (did == device_id) {
|
|
||||||
return std.mem.trim(u8, line[6..], " \t");
|
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;
|
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}),
|
||||||
|
.driver = null,
|
||||||
|
.memory = null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatted = try gpu_info.format(allocator);
|
||||||
|
return formatted;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user