const std = @import("std"); const os = std.os.linux; const Drm = @import("request.zig").Drm; const Card = @import("card.zig").Card; const RawConnector = extern struct { encoder_ids: ?*u32, modes: ?*ModeInfo, prop_ids: ?*u32, prop_value_ids: ?*u64, count_modes: u32, count_props: u32, count_encoders: u32, encoder_id: u32, connector_id: u32, connector_type: u32, connector_type_id: u32, connection: Connection, mm_width: u32, mm_height: u32, subpixel: u32, pad: u32, }; const Connection = enum(u32) { undefined_state = 0, connected = 1, disconnected = 2, unknown = 3, }; const ModeInfo = extern struct { const Self = @This(); const Flags = packed struct(u32) { phsync: bool, nhsync: bool, pvsync: bool, nvsync: bool, interlace: bool, dblscan: bool, csync: bool, pcsync: bool, ncsync: bool, hskew: bool, bcast: bool, pixmux: bool, dblclk: bool, clkdiv2: bool, _padding: u18, }; clock: u32, hdisplay: u16, hsync_start: u16, hsync_end: u16, htotal: u16, hskew: u16, vdisplay: u16, vsync_start: u16, vsync_end: u16, vtotal: u16, vscan: u16, vrefresh: u32, flags: Flags, type: u32, name: [32]u8, pub fn frame_rate(self: *const Self) f32 { var rate = (@as(u64, @intCast(self.clock)) * 1000000 / self.htotal + self.vtotal / 2) / self.vtotal; if (self.flags.interlace) { rate *= 2; } if (self.flags.dblscan) { rate /= 2; } if (self.vscan > 1) { rate /= self.vscan; } return @as(f32, @floatFromInt(rate)) / 1000.0; } }; pub const Connector = struct { const Self = @This(); card: *Card, encoder_ids: []u32, modes: []ModeInfo, prop_ids: []u32, prop_value_ids: []u64, encoder_id: u32, connector_id: u32, connector_type: u32, connector_type_id: u32, connection: Connection, mm_width: u32, mm_height: u32, subpixel: u32, pad: u32, pub fn raw_without_ids(card: *Card, id: u32) !RawConnector { var result = std.mem.zeroInit(RawConnector, .{ .connector_id = id }); try Drm.get_connector.request(card.file.handle, RawConnector, &result); return result; } // NOTE: This function does not take in account // that there might be some hot-plugging going // on. This might have to change in the future. pub fn init(card: *Card, id: u32) !Self { var raw = try Self.raw_without_ids(card, id); const resources = .{ .encoder_ids = try card.allocator.alloc(u32, raw.count_encoders), .modes = try card.allocator.alloc(ModeInfo, raw.count_modes), .prop_ids = try card.allocator.alloc(u32, raw.count_props), .prop_value_ids = try card.allocator.alloc(u64, raw.count_props), .encoder_id = raw.encoder_id, .connector_id = raw.connector_id, .connector_type = raw.connector_type, .connector_type_id = raw.connector_type_id, .connection = raw.connection, .mm_width = raw.mm_width, .mm_height = raw.mm_height, .subpixel = raw.subpixel, .pad = raw.pad, .card = card, }; @memset(resources.encoder_ids, 0); @memset(resources.modes, std.mem.zeroes(ModeInfo)); @memset(resources.prop_ids, 0); @memset(resources.prop_value_ids, 0); raw.encoder_ids = @ptrCast(resources.encoder_ids); raw.modes = @ptrCast(resources.modes); raw.prop_ids = @ptrCast(resources.prop_ids); raw.prop_value_ids = @ptrCast(resources.prop_value_ids); try Drm.get_connector.request(card.file.handle, RawConnector, &raw); return resources; } pub fn deinit(self: *Self) void { self.card.allocator.free(self.encoder_ids); self.card.allocator.free(self.modes); self.card.allocator.free(self.prop_ids); } };