feat: get Device from Card.

This commit is contained in:
Jackson Netherwood-Imig
2026-03-06 15:17:51 -08:00
parent 411ec740e9
commit 35b92f2324
4 changed files with 61 additions and 20 deletions
+6 -4
View File
@@ -5,13 +5,15 @@ pub fn main(init: std.process.Init) !void {
const io = init.io; const io = init.io;
const gpa = init.gpa; const gpa = init.gpa;
const device = drm.Device.getFromDevId(io, gpa, drm.makeDev(226, 0), .{}) catch // const device = drm.Device.getFromDevId(io, gpa, drm.makeDev(226, 0), .{}) catch
try drm.Device.getFromDevId(io, gpa, drm.makeDev(226, 1), .{}); // try drm.Device.getFromDevId(io, gpa, drm.makeDev(226, 1), .{});
// const card = try device.openNode(io);
const card = try drm.Card.openAuto(io, .primary);
const device = try card.getDevice(io, gpa, .{});
std.log.info("Device node path: {s}.", .{device.nodePath()}); std.log.info("Device node path: {s}.", .{device.nodePath()});
// const card = try drm.Card.openAuto(io);
const card = try device.openNode(io);
defer card.close(io); defer card.close(io);
const res = try card.getModesettingResources(gpa); const res = try card.getModesettingResources(gpa);
defer res.deinit(gpa); defer res.deinit(gpa);
+16 -4
View File
@@ -1,11 +1,12 @@
const std = @import("std"); const std = @import("std");
const Device = @import("Device.zig");
const drm = @import("drm.zig"); const drm = @import("drm.zig");
const fmt = @import("format.zig"); const fmt = @import("format.zig");
const sys = @import("sys.zig"); const sys = @import("sys.zig");
const util = @import("util.zig");
const log = std.log.scoped(.drm); const log = std.log.scoped(.drm);
const Card = @This(); const Card = @This();
handle: std.Io.File, handle: std.Io.File,
@@ -24,13 +25,15 @@ pub fn open(io: std.Io, path: []const u8) OpenError!Card {
pub const OpenAutoError = OpenError || std.Io.Dir.Iterator.Error || error{NoDevicesFound}; pub const OpenAutoError = OpenError || std.Io.Dir.Iterator.Error || error{NoDevicesFound};
pub fn openAuto(io: std.Io) OpenAutoError!Card { pub fn openAuto(io: std.Io, target_type: ?drm.Device.NodeType) OpenAutoError!Card {
const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{ .iterate = true }); const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{ .iterate = true });
defer dir.close(io); defer dir.close(io);
var it = dir.iterateAssumeFirstIteration(); var it = dir.iterateAssumeFirstIteration();
while (try it.next(io)) |entry| if (entry.kind == .character_device) while (try it.next(io)) |entry| if (entry.kind == .character_device) {
return Card{ .handle = try dir.openFile(io, entry.name, .{ .mode = .read_write }) }; if (target_type) |t| if (!std.mem.startsWith(u8, entry.name, t.name())) continue;
return Card{ .handle = dir.openFile(io, entry.name, .{ .mode = .read_write }) catch continue };
};
return error.NoDevicesFound; return error.NoDevicesFound;
} }
@@ -39,6 +42,15 @@ pub fn close(self: Card, io: std.Io) void {
self.handle.close(io); self.handle.close(io);
} }
pub fn getDevId(self: Card) !std.posix.dev_t {
const stat = try util.statFile(self.handle.handle);
return drm.makeDev(stat.rdev_major, stat.rdev_minor);
}
pub fn getDevice(self: Card, io: std.Io, gpa: std.mem.Allocator, flags: Device.Flags) !Device {
return .getFromDevId(io, gpa, try self.getDevId(), flags);
}
pub fn handleEvents( pub fn handleEvents(
self: Card, self: Card,
io: std.Io, io: std.Io,
+11 -12
View File
@@ -4,6 +4,7 @@ const path_max = std.os.linux.PATH_MAX;
const Card = @import("Card.zig"); const Card = @import("Card.zig");
const drm = @import("drm.zig"); const drm = @import("drm.zig");
const sys = @import("sys.zig"); const sys = @import("sys.zig");
const util = @import("util.zig");
const log = std.log.scoped(.drm); const log = std.log.scoped(.drm);
const Device = @This(); const Device = @This();
@@ -183,6 +184,14 @@ pub const NodeType = enum {
control, control,
render, render,
pub const max = 3; pub const max = 3;
pub fn name(self: NodeType) []const u8 {
return switch (self) {
.primary => drm.primary_minor_name,
.control => drm.control_minor_name,
.render => drm.render_minor_name,
};
}
}; };
fn processDevice( fn processDevice(
@@ -202,7 +211,7 @@ fn processDevice(
if (node.len + 1 > max_node_length) if (node.len + 1 > max_node_length)
return error.NodePathTooLong; return error.NodePathTooLong;
const stat = try statx(node); const stat = try util.statPath(node);
const major = stat.rdev_major; const major = stat.rdev_major;
const minor = stat.rdev_minor; const minor = stat.rdev_minor;
@@ -375,7 +384,7 @@ fn parseConfigSysfsFile(io: std.Io, major: u32, minor: u32) !PciDeviceInfo {
} }
fn hasRdev(dev: Device, rdev: std.posix.dev_t) bool { fn hasRdev(dev: Device, rdev: std.posix.dev_t) bool {
const stat = statx(dev.nodePath()) catch return false; const stat = util.statPath(dev.nodePath()) catch return false;
return drm.makeDev(stat.rdev_major, stat.rdev_minor) == rdev; return drm.makeDev(stat.rdev_major, stat.rdev_minor) == rdev;
} }
@@ -386,13 +395,3 @@ fn getNodeType(name: []const u8) !NodeType {
return error.InvalidName; return error.InvalidName;
} }
fn statx(path: []const u8) !std.os.linux.Statx {
const posix_path = try std.posix.toPosixPath(path);
var stat_buf: std.os.linux.Statx = undefined;
const rc = std.os.linux.statx(std.os.linux.AT.FDCWD, &posix_path, 0, .{}, &stat_buf);
return switch (std.posix.errno(rc)) {
.SUCCESS => stat_buf,
else => |err| std.posix.unexpectedErrno(err),
};
}
+28
View File
@@ -0,0 +1,28 @@
const std = @import("std");
pub fn statPath(path: []const u8) !std.os.linux.Statx {
const posix_path = try std.posix.toPosixPath(path);
return statxInner(std.os.linux.AT.FDCWD, &posix_path, 0);
}
pub fn statFile(fd: std.posix.fd_t) !std.os.linux.Statx {
return statxInner(fd, "", std.os.linux.AT.EMPTY_PATH);
}
fn statxInner(fd: std.posix.fd_t, path: [*:0]const u8, flags: u32) !std.os.linux.Statx {
var stat_buf: std.os.linux.Statx = undefined;
const rc = std.posix.system.statx(fd, path, flags, .{}, &stat_buf);
return switch (std.posix.errno(rc)) {
.SUCCESS => stat_buf,
.ACCES => error.PermissionDenied,
.LOOP => error.SymLinkLoop,
.NAMETOOLONG => error.NameTooLong,
.NOENT => error.FileNotFound,
.NOMEM => error.SystemResources,
.NOTDIR => error.NotADirectory,
.BADF => unreachable,
.FAULT => unreachable,
.INVAL => unreachable,
else => |err| std.posix.unexpectedErrno(err),
};
}