Skip to content

Commit 25f79f4

Browse files
feat: add props
1 parent 0ee2e52 commit 25f79f4

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed

example.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,30 @@ pub fn main() !void {
2222

2323
const encoder = node.getEncoder(connector.encoderId) catch null;
2424

25+
if (connector.props()) |props| {
26+
for (props) |propId| {
27+
var prop: libdrm.types.ModeGetProperty = .{
28+
.propId = propId,
29+
};
30+
try prop.getAllocated(node.fd, alloc);
31+
defer prop.deinit(alloc);
32+
33+
if (prop.blobs()) |blobs| {
34+
for (blobs) |blobId| {
35+
var blob: libdrm.types.ModeGetBlob = .{
36+
.blobId = blobId,
37+
};
38+
try blob.getAllocated(node.fd, alloc);
39+
defer blob.deinit(alloc);
40+
41+
std.debug.print("{}\n", .{blob});
42+
}
43+
}
44+
45+
std.debug.print("{}\n", .{prop});
46+
}
47+
}
48+
2549
std.debug.print("{} {?}\n", .{ connector, encoder });
2650
}
2751
}

libdrm/types.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub usingnamespace @import("types/mode/crtc.zig");
99
pub usingnamespace @import("types/mode/conn.zig");
1010
pub usingnamespace @import("types/mode/fb.zig");
1111
pub usingnamespace @import("types/mode/plane.zig");
12+
pub usingnamespace @import("types/mode/props.zig");
1213

1314
pub const Event = union(Type) {
1415
vblank: VBlank,

libdrm/types/mode/props.zig

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
const std = @import("std");
2+
const Allocator = std.mem.Allocator;
3+
const os = @import("../../os.zig");
4+
5+
pub const ModeGetBlob = extern struct {
6+
blobId: u32 = 0,
7+
len: u32 = 0,
8+
dataPtr: u64 = 0,
9+
10+
pub const req = os.IOCTL.IOWR(0xAC, ModeGetBlob);
11+
12+
pub fn get(self: *ModeGetBlob, fd: std.os.fd_t) !void {
13+
return switch (std.os.errno(os.ioctl(fd, req, @intFromPtr(self)))) {
14+
.SUCCESS => {},
15+
.BADF => error.NotOpenForWriting,
16+
.NOENT => error.NotFound,
17+
.FAULT => unreachable,
18+
.INVAL => unreachable,
19+
.NOTTY => error.NotATerminal,
20+
.OPNOTSUPP => error.NotSupported,
21+
else => |e| std.os.unexpectedErrno(e),
22+
};
23+
}
24+
25+
pub fn getAllocated(self: *ModeGetBlob, fd: std.os.fd_t, alloc: Allocator) !void {
26+
try self.get(fd);
27+
28+
errdefer self.deinit(alloc);
29+
if (self.len > 0) self.dataPtr = @intFromPtr((try alloc.alloc(u8, self.len)).ptr);
30+
31+
try self.get(fd);
32+
}
33+
34+
pub fn deinit(self: *const ModeGetBlob, alloc: Allocator) void {
35+
if (self.data()) |v| alloc.free(v);
36+
}
37+
38+
pub fn format(self: *const ModeGetBlob, comptime _: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
39+
_ = options;
40+
41+
try writer.writeAll(@typeName(ModeGetBlob));
42+
try writer.print("{{ .blobId = {}, .len = {}", .{
43+
self.blobId,
44+
self.len,
45+
});
46+
47+
if (self.data()) |v| try writer.print(", .data = {any}", .{v});
48+
49+
try writer.writeAll(" }");
50+
}
51+
52+
fn fieldPointer(self: *const ModeGetBlob, comptime field: std.meta.FieldEnum(ModeGetBlob), comptime T: type, count: u32) ?[]const T {
53+
if (@field(self, @tagName(field)) == 0) return null;
54+
return @as([*]T, @ptrFromInt(@field(self, @tagName(field))))[0..count];
55+
}
56+
57+
pub inline fn data(self: *const ModeGetBlob) ?[]const u8 {
58+
return self.fieldPointer(.dataPtr, u8, self.len);
59+
}
60+
};
61+
62+
pub const ModePropertyEnum = extern struct {
63+
value: u64 = 0,
64+
name: [32]u8 = undefined,
65+
66+
pub fn format(self: *const ModePropertyEnum, comptime _: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
67+
_ = options;
68+
69+
try writer.writeAll(@typeName(ModePropertyEnum));
70+
try writer.print("{{ .value = {}, .name = \"{s}\" }}", .{
71+
self.value,
72+
self.name,
73+
});
74+
}
75+
};
76+
77+
pub const ModeGetProperty = extern struct {
78+
valuesPtr: u64 = 0,
79+
enumBlobPtr: u64 = 0,
80+
propId: u32 = 0,
81+
flags: Flags = undefined,
82+
name: [32]u8 = undefined,
83+
countValues: u32 = 0,
84+
countEnumBlobs: u32 = 0,
85+
86+
pub const req = os.IOCTL.IOWR(0xAA, ModeGetProperty);
87+
88+
pub const Flags = packed struct(u32) {
89+
pending: u1,
90+
range: u1,
91+
immutable: u1,
92+
@"enum": u1,
93+
blob: u1,
94+
bitmask: u1,
95+
__future: u26,
96+
};
97+
98+
pub fn get(self: *ModeGetProperty, fd: std.os.fd_t) !void {
99+
return switch (std.os.errno(os.ioctl(fd, req, @intFromPtr(self)))) {
100+
.SUCCESS => {},
101+
.BADF => error.NotOpenForWriting,
102+
.NOENT => error.NotFound,
103+
.FAULT => unreachable,
104+
.INVAL => unreachable,
105+
.NOTTY => error.NotATerminal,
106+
.OPNOTSUPP => error.NotSupported,
107+
else => |e| std.os.unexpectedErrno(e),
108+
};
109+
}
110+
111+
pub fn getAllocated(self: *ModeGetProperty, fd: std.os.fd_t, alloc: Allocator) !void {
112+
try self.get(fd);
113+
114+
errdefer self.deinit(alloc);
115+
if (self.countValues > 0 and self.flags.blob == 0) self.valuesPtr = @intFromPtr((try alloc.alloc(u64, self.countValues)).ptr);
116+
if (self.countEnumBlobs > 0) {
117+
if (self.flags.@"enum" == 1) {
118+
self.enumBlobPtr = @intFromPtr((try alloc.alloc(ModePropertyEnum, self.countEnumBlobs)).ptr);
119+
} else if (self.flags.blob == 1) {
120+
self.valuesPtr = @intFromPtr((try alloc.alloc(u32, self.countEnumBlobs)).ptr);
121+
self.enumBlobPtr = @intFromPtr((try alloc.alloc(u32, self.countEnumBlobs)).ptr);
122+
}
123+
}
124+
125+
try self.get(fd);
126+
}
127+
128+
pub fn deinit(self: *const ModeGetProperty, alloc: Allocator) void {
129+
if (self.values()) |v| alloc.free(v);
130+
if (self.enums()) |v| alloc.free(v);
131+
if (self.blobValues()) |v| alloc.free(v);
132+
if (self.blobs()) |v| alloc.free(v);
133+
}
134+
135+
pub fn format(self: *const ModeGetProperty, comptime _: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
136+
_ = options;
137+
138+
try writer.writeAll(@typeName(ModeGetProperty));
139+
try writer.print("{{ .propId = {}, .flags = {}, .name = \"{s}\"", .{
140+
self.propId,
141+
self.flags,
142+
self.name,
143+
});
144+
145+
if (self.values()) |v| try writer.print(", .values = {any}", .{v});
146+
if (self.enums()) |v| try writer.print(", .enums = {any}", .{v});
147+
if (self.blobValues()) |v| try writer.print(", .blobValues = {any}", .{v});
148+
if (self.blobs()) |v| try writer.print(", .blobs = {any}", .{v});
149+
150+
try writer.writeAll(" }");
151+
}
152+
153+
fn fieldPointer(self: *const ModeGetProperty, comptime field: std.meta.FieldEnum(ModeGetProperty), comptime T: type, count: u32) ?[]const T {
154+
if (@field(self, @tagName(field)) == 0) return null;
155+
return @as([*]T, @ptrFromInt(@field(self, @tagName(field))))[0..count];
156+
}
157+
158+
pub inline fn values(self: *const ModeGetProperty) ?[]const u64 {
159+
return if (self.flags.blob == 1) null else self.fieldPointer(.valuesPtr, u64, self.countValues);
160+
}
161+
162+
pub inline fn enums(self: *const ModeGetProperty) ?[]const ModePropertyEnum {
163+
return if (self.flags.@"enum" == 1) self.fieldPointer(.enumBlobPtr, ModePropertyEnum, self.countEnumBlobs) else null;
164+
}
165+
166+
pub inline fn blobValues(self: *const ModeGetProperty) ?[]const u32 {
167+
return if (self.flags.blob == 1) self.fieldPointer(.valuesPtr, u32, self.countEnumBlobs) else null;
168+
}
169+
170+
pub inline fn blobs(self: *const ModeGetProperty) ?[]const u32 {
171+
return if (self.flags.blob == 1) self.fieldPointer(.enumBlobPtr, u32, self.countEnumBlobs) else null;
172+
}
173+
};

0 commit comments

Comments
 (0)