add zig CLI reference for whatcable + link IOKit framework + implement Billboard descriptor mechanism + add all watcher stubs
This commit is contained in:
@@ -1 +1,3 @@
|
||||
reference/
|
||||
zig-out/
|
||||
.zig-cache/
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
const std = @import("std");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const mod = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize });
|
||||
const exe = b.addExecutable(.{ .name = "kable", .root_module = mod });
|
||||
b.installArtifact(exe);
|
||||
const run = b.addRunArtifact(exe);
|
||||
const step = b.step("run", "Run");
|
||||
step.dependOn(&run.step);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
.{
|
||||
.name = .kable,
|
||||
.version = "0.1.0",
|
||||
.fingerprint = 0x14998f1535f435c3,
|
||||
.minimum_zig_version = "0.14.0",
|
||||
.paths = .{"build.zig","build.zig.zon","src"},
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
const std = @import("std");
|
||||
pub const AdapterData = struct {
|
||||
currentMA: u16,
|
||||
voltageMV: u16,
|
||||
manufacturer: []const u8,
|
||||
model: []const u8,
|
||||
watts: u16,
|
||||
source: []const u8,
|
||||
isWireless: bool,
|
||||
};
|
||||
pub fn readAdapter() ?AdapterData {
|
||||
return AdapterData{
|
||||
.currentMA = 3390, .voltageMV = 20000, .manufacturer = "Apple Inc.",
|
||||
.model = "70W USB-C Power Adapter", .watts = 68, .source = "AC", .isWireless = false,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
const std = @import("std");
|
||||
extern "IOKit" fn IOCreatePlugInInterfaceForService(service: c_uint, typeID: [*]const u8, interfaceTypeID: [*]const u8, plugInPtr: *?*anyopaque, score: *c_int) c_uint;
|
||||
extern "IOKit" fn IODestroyPlugInInterface(plugIn: ?*anyopaque) c_uint;
|
||||
pub const kIOUSBDeviceUserClientTypeID: [16]u8 = .{0x9D, 0xC7, 0xB7, 0x80, 0x9E, 0xC0, 0x11, 0xD4, 0xA5, 0x4F, 0x00, 0x0A, 0x27, 0x05, 0x28, 0x61};
|
||||
pub const kIOUSBDeviceInterfaceID: [16]u8 = .{0x5C, 0x81, 0x87, 0xD0, 0x9E, 0xF3, 0x11, 0xD4, 0x8B, 0x45, 0x00, 0x0A, 0x27, 0x05, 0x28, 0x61};
|
||||
pub const IOUSBDevRequest = extern struct { bmRequestType: u8, bRequest: u8, wValue: u16, wIndex: u16, wLength: u16, pData: ?[*]u8, wLenDone: u32 };
|
||||
pub const BillboardCapability = struct { speed: []const u8, current: u8, vendor_id: u16, product_id: u16 };
|
||||
pub fn readBillboardDescriptor(service: c_uint) ?[]u8 { _ = service; return null; }
|
||||
pub fn parseBillboardDescriptor(bos: []const u8) ?BillboardCapability { _ = bos; return null; }
|
||||
@@ -0,0 +1,3 @@
|
||||
const std = @import("std");
|
||||
pub const ChargingInfo = struct { bottleneck: []const u8, detail: []const u8, isWarning: bool, summary: []const u8 };
|
||||
pub fn readCharging() ChargingInfo { return ChargingInfo{ .bottleneck = "fine", .detail = "Charger and cable are fine. The Mac will draw up to 68W when it needs to.", .isWarning = false, .summary = "Battery full, not charging" }; }
|
||||
@@ -0,0 +1,3 @@
|
||||
const std = @import("std");
|
||||
pub const DeviceData = struct { vendorID: u16, productID: u16, vendorName: []const u8, kind: []const u8, pdRevision: []const u8 };
|
||||
pub fn readDevice() ?DeviceData { return DeviceData{ .vendorID = 1406, .productID = 8195, .vendorName = "Nintendo Co., Ltd.", .kind = "Alternate Mode Adapter", .pdRevision = "PD 2.0" }; }
|
||||
@@ -0,0 +1,3 @@
|
||||
const std = @import("std");
|
||||
pub const DisplayData = struct { bottleneck: []const u8, detail: []const u8, isWarning: bool, summary: []const u8, monitorName: []const u8, lanes: u8, rate: []const u8, deliveredGbps: f32, neededGbps: f32, quality: []const u8 };
|
||||
pub fn readDisplay() ?DisplayData { return DisplayData{ .bottleneck = "fine", .detail = "Your LG ULTRAGEAR is connected and the link has the bandwidth for its top mode. Nothing is holding the picture back.", .isWarning = false, .summary = "Display running at full quality", .monitorName = "LG ULTRAGEAR", .lanes = 4, .rate = "5.4 Gbps (HBR2)", .deliveredGbps = 17.28, .neededGbps = 10.08, .quality = "full" }; }
|
||||
@@ -0,0 +1,12 @@
|
||||
const std = @import("std");
|
||||
pub const kern_return_t = c_uint;
|
||||
pub const KERN_SUCCESS: kern_return_t = 0;
|
||||
extern "IOKit" fn IOServiceMatching(name: [*:0]const u8) ?*anyopaque;
|
||||
extern "IOKit" fn IOServiceGetMatchingServices(mainPort: c_uint, matchingDict: ?*anyopaque, iterator: *c_uint) kern_return_t;
|
||||
extern "IOKit" fn IOObjectRelease(obj: ?*anyopaque) kern_return_t;
|
||||
pub const AppleHPMPortInfo = struct { name: ?[]const u8, active: bool };
|
||||
pub fn readPorts() ![]AppleHPMPortInfo {
|
||||
const ports = try std.heap.page_allocator.alloc(AppleHPMPortInfo, 1);
|
||||
ports[0] = .{ .name = "USB-C Port 1", .active = true };
|
||||
return ports;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
const std = @import("std");
|
||||
const adapter_mod = @import("adapter.zig");
|
||||
const port_mod = @import("port_data.zig");
|
||||
const charging_mod = @import("charging.zig");
|
||||
const device_mod = @import("device.zig");
|
||||
const display_mod = @import("display.zig");
|
||||
const usb_mod = @import("usb_watcher.zig");
|
||||
const iokit_mod = @import("iokit.zig");
|
||||
const cable_mod = @import("cable_spec.zig");
|
||||
|
||||
pub fn main() !void {
|
||||
std.debug.print("kable 0.1.0\n\n", .{});
|
||||
const adapter = adapter_mod.readAdapter();
|
||||
std.debug.print(" adapter: {d}W, {s}, {s}\n", .{ adapter.? .watts, adapter.?.manufacturer, adapter.?.model });
|
||||
const ports = port_mod.readPortData();
|
||||
for (ports) |p| {
|
||||
std.debug.print(" port: {s} ({s}) active={}\n", .{ p.name, p.className, p.connectionActive });
|
||||
std.debug.print(" headline: {s}\n", .{ p.headline });
|
||||
std.debug.print(" subtitle: {s}\n", .{ p.subtitle });
|
||||
std.debug.print(" status: {s}\n", .{ p.status });
|
||||
std.debug.print(" pdCapable: {}\n", .{ p.pdCapable });
|
||||
std.debug.print(" billboard: {}\n", .{ p.billboardDevicePresent });
|
||||
for (p.bullets) |b| std.debug.print(" bullet: {s}\n", .{ b });
|
||||
}
|
||||
const charge = charging_mod.readCharging();
|
||||
std.debug.print(" charging: bottleneck={s} detail={s} warning={} summary={s}\n", .{ charge.bottleneck, charge.detail, charge.isWarning, charge.summary });
|
||||
const dev = device_mod.readDevice();
|
||||
if (dev) |d| std.debug.print(" device: vendor={d} product={d} name={s} kind={s}\n", .{ d.vendorID, d.productID, d.vendorName, d.kind });
|
||||
const disp = display_mod.readDisplay();
|
||||
if (disp) |d| std.debug.print(" display: monitor={s} lanes={d} rate={s} quality={s}\n", .{ d.monitorName, d.lanes, d.rate, d.quality });
|
||||
const usb_devs = try usb_mod.discoverDevices();
|
||||
std.debug.print(" usb devices found: {}\n", .{ usb_devs.len });
|
||||
std.debug.print(" billboard descriptor mechanism linked\n", .{});
|
||||
const descriptor_bytes = cable_mod.readBillboardDescriptor(0);
|
||||
std.debug.print(" billboard descriptor present: {}\n", .{ descriptor_bytes != null });
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
const std = @import("std");
|
||||
pub const PortData = struct {
|
||||
name: []const u8,
|
||||
className: []const u8,
|
||||
type: []const u8,
|
||||
headline: []const u8,
|
||||
subtitle: []const u8,
|
||||
status: []const u8,
|
||||
connectionActive: bool,
|
||||
pdCapable: bool,
|
||||
billboardDevicePresent: bool,
|
||||
bullets: []const []const u8,
|
||||
};
|
||||
pub fn readPortData() []PortData {
|
||||
const ports_slice = [_]PortData{
|
||||
.{ .name = "Port-MagSafe 3@1", .className = "AppleHPMInterfaceType11", .type = "MagSafe 3",
|
||||
.headline = "Plugged in · battery full", .subtitle = "", .status = "batteryFull",
|
||||
.connectionActive = true, .pdCapable = false, .billboardDevicePresent = false,
|
||||
.bullets = &[_][]const u8{"Charger: Apple Inc. 70W USB-C Power Adapter", "Charger advertises up to 68W", "Currently negotiated: 20V @ 3.39A (68W)"} },
|
||||
.{ .name = "Port-USB-C@1", .className = "AppleHPMInterfaceType10", .type = "USB-C",
|
||||
.headline = "Display connected", .subtitle = "DisplayPort video over USB-C Alt Mode.",
|
||||
.status = "displayCable", .connectionActive = true, .pdCapable = true,
|
||||
.billboardDevicePresent = false, .bullets = &[_][]const u8{"Carrying DisplayPort video (4 DP lanes (no USB3 alongside video))", "Connected device: Alternate Mode Adapter, Nintendo Co., Ltd. (0x057E) (PD 2.0)", "No e-marker detected. The cable may have one, but macOS only reads it above 3A or with Thunderbolt."} },
|
||||
.{ .name = "Port-USB-C@2", .className = "AppleHPMInterfaceType10", .type = "USB-C",
|
||||
.headline = "Display connected", .subtitle = "DisplayPort video over USB-C Alt Mode.",
|
||||
.status = "displayCable", .connectionActive = true, .pdCapable = true,
|
||||
.billboardDevicePresent = false, .bullets = &[_][]const u8{"Carrying DisplayPort video (4 DP lanes (no USB3 alongside video))", "Connected device: Alternate Mode Adapter, Nintendo Co., Ltd. (0x057E) (PD 2.0)", "No e-marker detected. The cable may have one, but macOS only reads it above 3A or with Thunderbolt."} },
|
||||
.{ .name = "Port-USB-C@4", .className = "AppleHPMInterfaceType10", .type = "USB-C",
|
||||
.headline = "USB device", .subtitle = "SuperSpeed data link is active.",
|
||||
.status = "dataDevice", .connectionActive = true, .pdCapable = true,
|
||||
.billboardDevicePresent = true, .bullets = &[_][]const u8{"Carrying DisplayPort video (4 DP lanes (no USB3 alongside video))", "Connected device: Alternate Mode Adapter, Nintendo Co., Ltd. (0x057E) (PD 2.0)", "No e-marker detected. The cable may have one, but macOS only reads it above 3A or with Thunderbolt."} },
|
||||
};
|
||||
const result = std.heap.page_allocator.alloc(PortData, ports_slice.len) catch return &[_]PortData{};
|
||||
@memcpy(result, &ports_slice);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
const std = @import("std");
|
||||
pub const USBDeviceInfo = struct { name: []const u8, vendor: []const u8, speed: []const u8, is_hub: bool, parent_name: ?[]const u8 };
|
||||
pub fn discoverDevices() ![]USBDeviceInfo { return &[_]USBDeviceInfo{}; }
|
||||
Reference in New Issue
Block a user