Update GPU functions to support multiple GPUs and adjust system info structure accordingly
All checks were successful
PikaOS Package Build & Release (amd64-v3) / build (push) Successful in 51s

This commit is contained in:
ferreo 2024-11-30 19:22:08 +00:00
parent 5ef827d040
commit 946c64d5ab
5 changed files with 156 additions and 114 deletions

View File

@ -1 +1 @@
1
2

View File

@ -1,4 +1,4 @@
pikafetch (0.1.0-101pika1) pika; urgency=medium
pikafetch (0.1.0-101pika2) pika; urgency=medium
* Initial release.

View File

@ -1,118 +1,131 @@
const std = @import("std");
pub fn getGPUInfo(allocator: std.mem.Allocator) ![]const u8 {
const vendor_file = std.fs.openFileAbsolute("/sys/class/drm/card0/device/vendor", .{}) catch |err| switch (err) {
error.FileNotFound => return allocator.dupe(u8, "Unknown GPU"),
else => return err,
};
defer vendor_file.close();
const device_file = std.fs.openFileAbsolute("/sys/class/drm/card0/device/device", .{}) catch |err| switch (err) {
error.FileNotFound => return allocator.dupe(u8, "Unknown GPU"),
else => return err,
};
defer device_file.close();
var vendor_buf: [32]u8 = undefined;
var device_buf: [32]u8 = undefined;
const vendor_bytes = try vendor_file.readAll(&vendor_buf);
const device_bytes = try device_file.readAll(&device_buf);
const vendor_str = std.mem.trim(u8, vendor_buf[0..vendor_bytes], "\n\r \t0x");
const device_str = std.mem.trim(u8, device_buf[0..device_bytes], "\n\r \t0x");
const vendor_id = try std.fmt.parseInt(u32, vendor_str, 16);
const device_id = try std.fmt.parseInt(u32, device_str, 16);
const modalias_file = std.fs.openFileAbsolute("/sys/class/drm/card0/device/modalias", .{}) catch |err| switch (err) {
error.FileNotFound => null,
else => return err,
};
defer if (modalias_file) |f| f.close();
const name_file = std.fs.openFileAbsolute("/sys/class/drm/card0/device/product", .{}) catch |err| switch (err) {
error.FileNotFound => null,
else => return err,
};
defer if (name_file) |f| f.close();
const model_file = std.fs.openFileAbsolute("/sys/class/drm/card0/device/model", .{}) catch |err| switch (err) {
error.FileNotFound => null,
else => return err,
};
defer if (model_file) |f| f.close();
const subsystem_file = std.fs.openFileAbsolute("/sys/class/drm/card0/device/subsystem_device", .{}) 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;
pub fn getGPUInfo(allocator: std.mem.Allocator) ![][]const u8 {
var gpus = std.ArrayList([]const u8).init(allocator);
errdefer {
for (gpus.items) |gpu| {
allocator.free(gpu);
}
gpus.deinit();
}
if (gpu_name.len == 0) {
if (model_file) |f| {
var card_num: u32 = 0;
while (true) : (card_num += 1) {
const card_path = try std.fmt.allocPrint(allocator, "/sys/class/drm/card{d}/device", .{card_num});
defer allocator.free(card_path);
const vendor_file = std.fs.openFileAbsolute(try std.fmt.allocPrint(allocator, "{s}/vendor", .{card_path}), .{}) catch |err| switch (err) {
error.FileNotFound => break, // No more cards found
else => return err,
};
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 device_buf: [32]u8 = undefined;
const vendor_bytes = try vendor_file.readAll(&vendor_buf);
const device_bytes = try device_file.readAll(&device_buf);
const vendor_str = std.mem.trim(u8, vendor_buf[0..vendor_bytes], "\n\r \t0x");
const device_str = std.mem.trim(u8, device_buf[0..device_bytes], "\n\r \t0x");
const vendor_id = try std.fmt.parseInt(u32, vendor_str, 16);
const device_id = try std.fmt.parseInt(u32, device_str, 16);
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 (findPCIName(vendor_id, device_id)) |model| {
return std.fmt.allocPrint(allocator, "{s} {s}", .{ switch (vendor_id) {
0x1002 => "AMD",
0x10de => "NVIDIA",
0x8086 => "Intel",
else => "Unknown",
}, model });
}
const driver_dir = std.fs.openDirAbsolute("/sys/class/drm/card0/device", .{}) catch |err| switch (err) {
error.FileNotFound => null,
else => return err,
};
if (driver_dir) |d| {
defer {
var dir = d;
dir.close();
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;
}
}
}
var path_buf: [256]u8 = undefined;
const path = d.readLink("driver", &path_buf) catch |err| switch (err) {
error.FileNotFound => return std.fmt.allocPrint(allocator, "{s} GPU (0x{x:0>4})", .{ switch (vendor_id) {
0x1002 => "AMD",
0x10de => "NVIDIA",
0x8086 => "Intel",
else => "Unknown",
}, device_id }),
else => return err,
};
const driver = std.fs.path.basename(path);
return std.fmt.allocPrint(allocator, "{s} (0x{x:0>4}, {s})", .{ switch (vendor_id) {
0x1002 => "AMD",
0x10de => "NVIDIA",
0x8086 => "Intel",
else => "Unknown",
}, device_id, driver });
// Declare and initialize the driver variable
var dir_handle = std.fs.openDirAbsolute(card_path, .{}) catch null;
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);
}
return std.fmt.allocPrint(allocator, "{s} GPU (0x{x:0>4})", .{ switch (vendor_id) {
0x1002 => "AMD",
0x10de => "NVIDIA",
0x8086 => "Intel",
else => "Unknown",
}, device_id });
if (gpus.items.len == 0) {
const unknown = try allocator.dupe(u8, "Unknown GPU");
try gpus.append(unknown);
}
return gpus.toOwnedSlice();
}
const pci_ids = @embedFile("../../data/pci.ids");

View File

@ -1,10 +1,22 @@
const std = @import("std");
pub fn getMotherboard(allocator: std.mem.Allocator) ![]const u8 {
const product_name = try std.fs.openFileAbsolute("/sys/class/dmi/id/product_name", .{});
defer product_name.close();
// Try board_name first as it's usually more reliable
const board_name = try std.fs.openFileAbsolute("/sys/class/dmi/id/board_name", .{});
defer board_name.close();
var buffer: [256]u8 = undefined;
const size = try product_name.readAll(&buffer);
return allocator.dupe(u8, std.mem.trim(u8, buffer[0..size], "\n\r "));
const size = try board_name.readAll(&buffer);
const name = std.mem.trim(u8, buffer[0..size], "\n\r ");
// If board_name is empty or generic, try product_name as fallback
if (name.len == 0) {
const product_name = try std.fs.openFileAbsolute("/sys/class/dmi/id/product_name", .{});
defer product_name.close();
const product_size = try product_name.readAll(&buffer);
return allocator.dupe(u8, std.mem.trim(u8, buffer[0..product_size], "\n\r "));
}
return allocator.dupe(u8, name);
}

View File

@ -25,7 +25,7 @@ pub const SystemInfo = struct {
packages: u32,
wm: []const u8,
terminal: []const u8,
gpu: []const u8,
gpus: [][]const u8,
swap_total: u64,
swap_used: u64,
disk_total: u64,
@ -41,7 +41,7 @@ pub const SystemInfo = struct {
var host: ?[]const u8 = null;
var wm_name: ?[]const u8 = null;
var terminal_name: ?[]const u8 = null;
var gpu_info: ?[]const u8 = null;
var gpu_list: ?[][]const u8 = null;
var shell_info: ?[]const u8 = null;
var cpu_info: ?[]const u8 = null;
@ -53,7 +53,10 @@ pub const SystemInfo = struct {
if (host) |h| allocator.free(h);
if (wm_name) |w| allocator.free(w);
if (terminal_name) |t| allocator.free(t);
if (gpu_info) |g| allocator.free(g);
if (gpu_list) |list| {
for (list) |g| allocator.free(g);
allocator.free(list);
}
if (shell_info) |s| allocator.free(s);
if (cpu_info) |c| allocator.free(c);
}
@ -67,7 +70,7 @@ pub const SystemInfo = struct {
const pkg_count = try packages.getDpkgCount();
wm_name = try wm.getWM(allocator);
terminal_name = try terminal.getTerminal(allocator);
gpu_info = try gpu.getGPUInfo(allocator);
gpu_list = try gpu.getGPUInfo(allocator);
const shell_data = try shell.getShellInfo(allocator);
shell_info = shell_data.name;
cpu_info = try cpu.getCPUInfo(allocator);
@ -88,7 +91,7 @@ pub const SystemInfo = struct {
.packages = pkg_count,
.wm = wm_name.?,
.terminal = terminal_name.?,
.gpu = gpu_info.?,
.gpus = gpu_list.?,
.swap_total = swap_info.total,
.swap_used = swap_info.used,
.disk_total = disk_info.total,
@ -106,13 +109,16 @@ pub const SystemInfo = struct {
self.allocator.free(self.host);
self.allocator.free(self.wm);
self.allocator.free(self.terminal);
self.allocator.free(self.gpu);
for (self.gpus) |gpu_info| {
self.allocator.free(gpu_info);
}
self.allocator.free(self.gpus);
self.allocator.free(self.shell_name);
self.allocator.free(self.cpu_info);
}
pub fn formatInfo(self: *const SystemInfo) ![]const []const u8 {
var info = try std.ArrayList([]const u8).initCapacity(self.allocator, 14);
var info = try std.ArrayList([]const u8).initCapacity(self.allocator, 13 + self.gpus.len);
errdefer {
for (info.items) |item| {
@ -160,7 +166,18 @@ pub const SystemInfo = struct {
try std.fmt.allocPrint(self.allocator, "{s}WM:{s} {s}", .{ colors.Color.bold, colors.Color.reset, self.wm }),
try std.fmt.allocPrint(self.allocator, "{s}Terminal:{s} {s}", .{ colors.Color.bold, colors.Color.reset, self.terminal }),
try std.fmt.allocPrint(self.allocator, "{s}CPU:{s} {s}", .{ colors.Color.bold, colors.Color.reset, self.cpu_info }),
try std.fmt.allocPrint(self.allocator, "{s}GPU:{s} {s}", .{ colors.Color.bold, colors.Color.reset, self.gpu }),
});
for (self.gpus, 0..) |gpu_info, i| {
try info.append(try std.fmt.allocPrint(self.allocator, "{s}GPU{s}{s}: {s}", .{
colors.Color.bold,
if (self.gpus.len > 1) try std.fmt.allocPrint(self.allocator, " {d}", .{i + 1}) else "",
colors.Color.reset,
gpu_info,
}));
}
try info.appendSlice(&[_][]const u8{
try std.fmt.allocPrint(self.allocator, "{s}Memory:{s} {d:.2} {s} / {d:.2} {s} ({s}{d}%{s})", .{
colors.Color.bold, colors.Color.reset,
calculations.mem_fmt.value, calculations.mem_fmt.unit,