139 lines
6.8 KiB
Zig
139 lines
6.8 KiB
Zig
//! ACPI / PnP hardware-ID (`_HID`) names: the flat analog of pci-class.zig for
|
|
//! `acpi_device` nodes. Unlike PCI, ACPI has no class/subclass/prog-IF taxonomy — a
|
|
//! device's identity *is* its `_HID` string (`PNP0303` simply means "PS/2 keyboard"),
|
|
//! so this is a plain id <-> name registry rather than a hierarchical decoder.
|
|
//! The well-known PnP/ACPI IDs; vendor-specific ids (e.g. `QEMU0002`, `INTC1234`) have
|
|
//! no standard name and decode to nothing. Pure reference data, so it is shared by
|
|
//! kernel discovery (the device-tree dump) and any user-space driver or tool.
|
|
//!
|
|
//! Code that means a specific device names the `HardwareId` variant instead of its
|
|
//! `_HID` string — `HardwareId.ps2_keyboard.hid()` reads without a registry lookup,
|
|
//! where a bare `"PNP0303"` does not.
|
|
|
|
const std = @import("std");
|
|
|
|
/// The common standard PnP/ACPI hardware IDs, as named values. Prefix ranges hint at
|
|
/// the grouping (PNP03xx keyboards, PNP0Fxx pointing devices, PNP0Cxx ACPI
|
|
/// power/thermal, PNP0Axx buses), but there is no formal hierarchy — hence a flat
|
|
/// enum over a flat registry.
|
|
pub const HardwareId = enum {
|
|
programmable_interrupt_controller,
|
|
system_timer,
|
|
high_precision_event_timer,
|
|
dma_controller,
|
|
ps2_keyboard,
|
|
parallel_port,
|
|
ecp_parallel_port,
|
|
serial_port,
|
|
floppy_disk_controller,
|
|
system_speaker,
|
|
pci_bus,
|
|
generic_container,
|
|
/// The second id the ACPI spec assigns the same "Generic Container Device" name.
|
|
generic_container_extended,
|
|
pci_express_root_bridge,
|
|
real_time_clock,
|
|
system_board,
|
|
motherboard_reserved_resources,
|
|
math_coprocessor,
|
|
acpi_system_board,
|
|
embedded_controller,
|
|
control_method_battery,
|
|
fan,
|
|
power_button,
|
|
lid,
|
|
sleep_button,
|
|
pci_interrupt_link,
|
|
microsoft_ps2_mouse,
|
|
ps2_mouse,
|
|
ac_adapter,
|
|
processor_device,
|
|
processor_aggregator,
|
|
processor_container,
|
|
|
|
const Entry = struct { hid: []const u8, name: []const u8 };
|
|
|
|
/// The registry row for this id: its `_HID` string and human-readable name.
|
|
fn entry(self: HardwareId) Entry {
|
|
return switch (self) {
|
|
.programmable_interrupt_controller => .{ .hid = "PNP0000", .name = "Programmable Interrupt Controller (PIC)" },
|
|
.system_timer => .{ .hid = "PNP0100", .name = "System Timer (PIT)" },
|
|
.high_precision_event_timer => .{ .hid = "PNP0103", .name = "High Precision Event Timer (HPET)" },
|
|
.dma_controller => .{ .hid = "PNP0200", .name = "DMA Controller" },
|
|
.ps2_keyboard => .{ .hid = "PNP0303", .name = "PS/2 Keyboard" },
|
|
.parallel_port => .{ .hid = "PNP0400", .name = "Standard LPT Parallel Port" },
|
|
.ecp_parallel_port => .{ .hid = "PNP0401", .name = "ECP Parallel Port" },
|
|
.serial_port => .{ .hid = "PNP0501", .name = "16550A-compatible Serial Port" },
|
|
.floppy_disk_controller => .{ .hid = "PNP0700", .name = "PC Floppy Disk Controller" },
|
|
.system_speaker => .{ .hid = "PNP0800", .name = "System Speaker" },
|
|
.pci_bus => .{ .hid = "PNP0A03", .name = "PCI Bus" },
|
|
.generic_container => .{ .hid = "PNP0A05", .name = "Generic Container Device" },
|
|
.generic_container_extended => .{ .hid = "PNP0A06", .name = "Generic Container Device" },
|
|
.pci_express_root_bridge => .{ .hid = "PNP0A08", .name = "PCI Express Root Bridge" },
|
|
.real_time_clock => .{ .hid = "PNP0B00", .name = "Real-Time Clock (RTC)" },
|
|
.system_board => .{ .hid = "PNP0C01", .name = "System Board" },
|
|
.motherboard_reserved_resources => .{ .hid = "PNP0C02", .name = "Motherboard Reserved Resources" },
|
|
.math_coprocessor => .{ .hid = "PNP0C04", .name = "Math Coprocessor" },
|
|
.acpi_system_board => .{ .hid = "PNP0C08", .name = "ACPI System Board" },
|
|
.embedded_controller => .{ .hid = "PNP0C09", .name = "ACPI Embedded Controller" },
|
|
.control_method_battery => .{ .hid = "PNP0C0A", .name = "ACPI Control Method Battery" },
|
|
.fan => .{ .hid = "PNP0C0B", .name = "ACPI Fan" },
|
|
.power_button => .{ .hid = "PNP0C0C", .name = "ACPI Power Button" },
|
|
.lid => .{ .hid = "PNP0C0D", .name = "ACPI Lid" },
|
|
.sleep_button => .{ .hid = "PNP0C0E", .name = "ACPI Sleep Button" },
|
|
.pci_interrupt_link => .{ .hid = "PNP0C0F", .name = "PCI Interrupt Link Device" },
|
|
.microsoft_ps2_mouse => .{ .hid = "PNP0F03", .name = "Microsoft PS/2 Mouse" },
|
|
.ps2_mouse => .{ .hid = "PNP0F13", .name = "PS/2 Mouse" },
|
|
.ac_adapter => .{ .hid = "ACPI0003", .name = "AC Adapter" },
|
|
.processor_device => .{ .hid = "ACPI0007", .name = "Processor Device" },
|
|
.processor_aggregator => .{ .hid = "ACPI000C", .name = "Processor Aggregator" },
|
|
.processor_container => .{ .hid = "ACPI0010", .name = "Processor Container" },
|
|
};
|
|
}
|
|
|
|
/// This id's `_HID` string (e.g. `.ps2_keyboard` -> "PNP0303").
|
|
pub fn hid(self: HardwareId) []const u8 {
|
|
return self.entry().hid;
|
|
}
|
|
|
|
/// This id's human-readable name (e.g. `.ps2_keyboard` -> "PS/2 Keyboard").
|
|
pub fn description(self: HardwareId) []const u8 {
|
|
return self.entry().name;
|
|
}
|
|
|
|
/// The named value for a `_HID` string, or null if it is not a known standard
|
|
/// id (vendor-specific ids are not in the registry).
|
|
pub fn fromHid(hid_string: []const u8) ?HardwareId {
|
|
for (std.enums.values(HardwareId)) |id| {
|
|
if (std.mem.eql(u8, id.hid(), hid_string)) return id;
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
/// The human-readable name for a `_HID` string, or "" if it is not a known standard
|
|
/// id (vendor-specific ids have no registry name — callers just print the raw HID).
|
|
pub fn description(hid: []const u8) []const u8 {
|
|
return (HardwareId.fromHid(hid) orelse return "").description();
|
|
}
|
|
|
|
test "decodes standard PnP/ACPI ids and leaves the rest alone" {
|
|
const eq = std.testing.expectEqualStrings;
|
|
try eq("PS/2 Keyboard", description("PNP0303"));
|
|
try eq("PS/2 Mouse", description("PNP0F13"));
|
|
try eq("PCI Express Root Bridge", description("PNP0A08"));
|
|
try eq("Real-Time Clock (RTC)", description("PNP0B00"));
|
|
try eq("", description("QEMU0002")); // vendor-specific: no standard name
|
|
try eq("", description("")); // no HID at all
|
|
}
|
|
|
|
test "named values round-trip through their _HID strings" {
|
|
const testing = std.testing;
|
|
try testing.expectEqualStrings("PNP0303", HardwareId.ps2_keyboard.hid());
|
|
try testing.expectEqual(@as(?HardwareId, .ps2_mouse), HardwareId.fromHid("PNP0F13"));
|
|
try testing.expectEqual(@as(?HardwareId, null), HardwareId.fromHid("QEMU0002"));
|
|
for (std.enums.values(HardwareId)) |id| {
|
|
try testing.expectEqual(@as(?HardwareId, id), HardwareId.fromHid(id.hid()));
|
|
}
|
|
}
|