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 target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
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(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "pikafetch",
|
.name = "pikafetch",
|
||||||
.root_source_file = .{ .cwd_relative = "src/main.zig" },
|
.root_source_file = .{ .cwd_relative = "src/main.zig" },
|
||||||
@ -17,9 +11,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add options to the executable
|
|
||||||
exe.root_module.addOptions("build_options", options);
|
|
||||||
|
|
||||||
exe.linkLibC();
|
exe.linkLibC();
|
||||||
b.installArtifact(exe);
|
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.
|
* 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
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
|
||||||
Notes:
|
|
||||||
The contents of src/data/pci.ids is licensed under GNU General Public License (version 2 or higher)
|
|
File diff suppressed because it is too large
Load Diff
@ -3,26 +3,8 @@ const mem = std.mem;
|
|||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const allocPrint = std.fmt.allocPrint;
|
const allocPrint = std.fmt.allocPrint;
|
||||||
|
const vector = @import("std").simd;
|
||||||
const VendorId = struct {
|
const builtin = @import("builtin");
|
||||||
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 {
|
const GPUInfo = struct {
|
||||||
vendor: []const u8,
|
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.startsWith(u8, entry.name, "card")) continue;
|
||||||
if (mem.indexOf(u8, entry.name, "-")) |_| continue;
|
if (mem.indexOf(u8, entry.name, "-")) |_| continue;
|
||||||
|
|
||||||
const vendor_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/vendor", .{entry.name});
|
if (try detectGPU(allocator, entry.name)) |gpu| {
|
||||||
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| {
|
|
||||||
try gpus.append(gpu);
|
try gpus.append(gpu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,8 +71,21 @@ pub fn getGPUInfo(allocator: mem.Allocator) ![][]const u8 {
|
|||||||
return gpus.toOwnedSlice();
|
return gpus.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detectNvidiaGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
fn detectGPU(allocator: mem.Allocator, card_name: []const u8) !?[]const u8 {
|
||||||
// First try to get device ID for PCI lookup
|
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});
|
const device_path = try allocPrint(allocator, "/sys/class/drm/{s}/device/device", .{card_name});
|
||||||
defer allocator.free(device_path);
|
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_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_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 model = try allocPrint(allocator, "(vendor: 0x{s}, device: 0x{s})", .{ vendor_str, device_str });
|
||||||
|
errdefer allocator.free(model);
|
||||||
// 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 gpu_info = GPUInfo{
|
const gpu_info = GPUInfo{
|
||||||
.vendor = "NVIDIA",
|
.vendor = "GPU",
|
||||||
.model = model_name.?, // Safe because we always set it above
|
.model = model,
|
||||||
.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}),
|
|
||||||
.driver = null,
|
.driver = null,
|
||||||
.memory = null,
|
.memory = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatted = try gpu_info.format(allocator);
|
const formatted = try gpu_info.format(allocator);
|
||||||
|
allocator.free(model);
|
||||||
return formatted;
|
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