reorg: normalise every protocol alias to its module name

Finish the direct-import convention: a protocol is now aliased to its module
name in snake_case in every file that imports one — consumers and the runtime
client wrappers alike. This kills the last of the alias variety (the generic
`protocol`, plus `power` and `transfer`), so `device_manager_protocol.Hello`
means the same thing everywhere and grepping a module name finds all its uses.

Pure rename (identifier uses only; prose references left untouched via a
guarded pattern). 14 files, 299/299 lines.

zig build + test green; 16 QEMU cases pass (smoke, device-manager,
driver-restart, device-list, pci-scan, usb-hid, usb-storage, display-service,
display-native, display-reattach, input, acpi-ps2, vfs, fat-mount,
power-button, orderly-shutdown).
This commit is contained in:
Daniel Samson
2026-07-22 21:17:54 +01:00
parent ac2d102878
commit 7d540c4b2f
14 changed files with 297 additions and 297 deletions
+22 -22
View File
@@ -19,16 +19,16 @@ const std = @import("std");
const runtime = @import("runtime");
const ipc = runtime.ipc;
const system = runtime.system;
const protocol = @import("usb-transfer-protocol");
const usb_transfer_protocol = @import("usb-transfer-protocol");
/// The USB chapter-9 wire ABI and the class taxonomy, re-exported so a class driver reaches
/// the whole USB domain through its one `usb` import (`usb.abi.getDescriptor`, `usb.ids.Class`).
pub const abi = @import("usb-abi");
pub const ids = @import("usb-ids");
pub const Endpoint = protocol.Endpoint;
pub const InterruptReport = protocol.InterruptReport;
pub const max_report_data = protocol.max_report_data;
pub const Endpoint = usb_transfer_protocol.Endpoint;
pub const InterruptReport = usb_transfer_protocol.InterruptReport;
pub const max_report_data = usb_transfer_protocol.max_report_data;
// Endpoint transfer types (EndpointDescriptor attributes), for `findEndpoint`.
pub const transfer_type_bulk: u8 = 2;
@@ -46,7 +46,7 @@ pub const Device = struct {
protocol_code: u8,
interface_number: u8,
endpoint_count: usize = 0,
endpoints: [protocol.max_reported_endpoints]Endpoint = undefined,
endpoints: [usb_transfer_protocol.max_reported_endpoints]Endpoint = undefined,
/// The interface's first endpoint of the given transfer type and direction
/// (`transfer_type_bulk` / `transfer_type_interrupt`), or null.
@@ -58,17 +58,17 @@ pub const Device = struct {
}
fn controlTransfer(self: *Device, setup: [8]u8, direction_in: bool, data: []u8) ?usize {
var request = protocol.ControlRequest{
var request = usb_transfer_protocol.ControlRequest{
.device_token = self.token,
.setup = setup,
.direction_in = @intFromBool(direction_in),
.data_length = @intCast(data.len),
};
if (!direction_in and data.len > 0) @memcpy(request.data[0..data.len], data);
var reply: [@sizeOf(protocol.ControlReply)]u8 = undefined;
var reply: [@sizeOf(usb_transfer_protocol.ControlReply)]u8 = undefined;
const length = ipc.call(self.bus, std.mem.asBytes(&request), &reply) catch return null;
if (length < @sizeOf(protocol.ControlReply)) return null;
const control_reply = std.mem.bytesToValue(protocol.ControlReply, reply[0..@sizeOf(protocol.ControlReply)]);
if (length < @sizeOf(usb_transfer_protocol.ControlReply)) return null;
const control_reply = std.mem.bytesToValue(usb_transfer_protocol.ControlReply, reply[0..@sizeOf(usb_transfer_protocol.ControlReply)]);
if (control_reply.status != 0) return null;
const actual = @min(control_reply.actual_length, data.len);
if (direction_in and actual > 0) @memcpy(data[0..actual], control_reply.data[0..actual]);
@@ -89,30 +89,30 @@ pub const Device = struct {
/// Begin periodic IN polling of an interrupt endpoint; reports flow back to
/// `self.endpoint` as asynchronous `InterruptReport` messages.
pub fn subscribeInterrupt(self: *Device, endpoint_address: u8, max_length: u16) bool {
var request = protocol.InterruptSubscribeRequest{
var request = usb_transfer_protocol.InterruptSubscribeRequest{
.device_token = self.token,
.endpoint_address = endpoint_address,
.max_length = max_length,
};
var reply: [@sizeOf(protocol.InterruptSubscribeReply)]u8 = undefined;
var reply: [@sizeOf(usb_transfer_protocol.InterruptSubscribeReply)]u8 = undefined;
const length = ipc.call(self.bus, std.mem.asBytes(&request), &reply) catch return false;
if (length < @sizeOf(protocol.InterruptSubscribeReply)) return false;
return std.mem.bytesToValue(protocol.InterruptSubscribeReply, reply[0..@sizeOf(protocol.InterruptSubscribeReply)]).status == 0;
if (length < @sizeOf(usb_transfer_protocol.InterruptSubscribeReply)) return false;
return std.mem.bytesToValue(usb_transfer_protocol.InterruptSubscribeReply, reply[0..@sizeOf(usb_transfer_protocol.InterruptSubscribeReply)]).status == 0;
}
/// One bulk transfer (IN or OUT per `endpoint_address`'s direction bit) to or
/// from the caller's own DMA buffer at `physical`. Returns the bytes moved.
pub fn bulk(self: *Device, endpoint_address: u8, physical: u64, length: u32) ?u32 {
var request = protocol.BulkRequest{
var request = usb_transfer_protocol.BulkRequest{
.device_token = self.token,
.physical_address = physical,
.length = length,
.endpoint_address = endpoint_address,
};
var reply: [@sizeOf(protocol.BulkReply)]u8 = undefined;
var reply: [@sizeOf(usb_transfer_protocol.BulkReply)]u8 = undefined;
const replied = ipc.call(self.bus, std.mem.asBytes(&request), &reply) catch return null;
if (replied < @sizeOf(protocol.BulkReply)) return null;
const bulk_reply = std.mem.bytesToValue(protocol.BulkReply, reply[0..@sizeOf(protocol.BulkReply)]);
if (replied < @sizeOf(usb_transfer_protocol.BulkReply)) return null;
const bulk_reply = std.mem.bytesToValue(usb_transfer_protocol.BulkReply, reply[0..@sizeOf(usb_transfer_protocol.BulkReply)]);
if (bulk_reply.status != 0) return null;
return bulk_reply.actual_length;
}
@@ -129,11 +129,11 @@ pub fn open(device_id: u64) ?Device {
} else return null;
const endpoint = ipc.createIpcEndpoint() orelse return null;
var request = protocol.OpenRequest{ .device_id = device_id };
var reply: [@sizeOf(protocol.OpenReply)]u8 = undefined;
var request = usb_transfer_protocol.OpenRequest{ .device_id = device_id };
var reply: [@sizeOf(usb_transfer_protocol.OpenReply)]u8 = undefined;
const result = ipc.callCap(bus, std.mem.asBytes(&request), &reply, endpoint) catch return null;
if (result.len < @sizeOf(protocol.OpenReply)) return null;
const open_reply = std.mem.bytesToValue(protocol.OpenReply, reply[0..@sizeOf(protocol.OpenReply)]);
if (result.len < @sizeOf(usb_transfer_protocol.OpenReply)) return null;
const open_reply = std.mem.bytesToValue(usb_transfer_protocol.OpenReply, reply[0..@sizeOf(usb_transfer_protocol.OpenReply)]);
if (open_reply.status != 0) return null;
var device = Device{
@@ -144,7 +144,7 @@ pub fn open(device_id: u64) ?Device {
.subclass = open_reply.interface_subclass,
.protocol_code = open_reply.interface_protocol,
.interface_number = open_reply.interface_number,
.endpoint_count = @min(open_reply.endpoint_count, protocol.max_reported_endpoints),
.endpoint_count = @min(open_reply.endpoint_count, usb_transfer_protocol.max_reported_endpoints),
};
for (0..device.endpoint_count) |index| device.endpoints[index] = open_reply.endpoints[index];
return device;
+10 -10
View File
@@ -10,7 +10,7 @@
const std = @import("std");
const ipc = @import("ipc.zig");
const system = @import("system.zig");
const protocol = @import("block-protocol");
const block_protocol = @import("block-protocol");
pub const Geometry = struct { block_size: u32, block_count: u64 };
@@ -19,11 +19,11 @@ pub const Device = struct {
/// The device's block size and total block count.
pub fn geometry(self: Device) ?Geometry {
var request = protocol.Request{ .operation = @intFromEnum(protocol.Operation.geometry), .lba = 0, .count = 0, .physical = 0 };
var reply: [protocol.reply_size]u8 = undefined;
var request = block_protocol.Request{ .operation = @intFromEnum(block_protocol.Operation.geometry), .lba = 0, .count = 0, .physical = 0 };
var reply: [block_protocol.reply_size]u8 = undefined;
const n = ipc.call(self.endpoint, std.mem.asBytes(&request), &reply) catch return null;
if (n < protocol.reply_size) return null;
const result = std.mem.bytesToValue(protocol.Reply, reply[0..protocol.reply_size]);
if (n < block_protocol.reply_size) return null;
const result = std.mem.bytesToValue(block_protocol.Reply, reply[0..block_protocol.reply_size]);
if (result.status != 0) return null;
return .{ .block_size = result.block_size, .block_count = result.block_count };
}
@@ -45,12 +45,12 @@ pub const Device = struct {
return self.transfer(.flush, 0, 0, 0);
}
fn transfer(self: Device, operation: protocol.Operation, lba: u64, count: u32, physical: u64) bool {
var request = protocol.Request{ .operation = @intFromEnum(operation), .lba = lba, .count = count, .physical = physical };
var reply: [protocol.reply_size]u8 = undefined;
fn transfer(self: Device, operation: block_protocol.Operation, lba: u64, count: u32, physical: u64) bool {
var request = block_protocol.Request{ .operation = @intFromEnum(operation), .lba = lba, .count = count, .physical = physical };
var reply: [block_protocol.reply_size]u8 = undefined;
const n = ipc.call(self.endpoint, std.mem.asBytes(&request), &reply) catch return false;
if (n < protocol.reply_size) return false;
return std.mem.bytesToValue(protocol.Reply, reply[0..protocol.reply_size]).status == 0;
if (n < block_protocol.reply_size) return false;
return std.mem.bytesToValue(block_protocol.Reply, reply[0..block_protocol.reply_size]).status == 0;
}
};
+6 -6
View File
@@ -12,11 +12,11 @@
const std = @import("std");
const ipc = @import("ipc.zig");
const system = @import("system.zig");
const protocol = @import("device-manager-protocol");
const device_manager_protocol = @import("device-manager-protocol");
/// What kind of driver is announcing itself (a bus that reports children, or a
/// leaf device). Re-exported so callers name it without importing the protocol.
pub const Role = protocol.Role;
pub const Role = device_manager_protocol.Role;
/// Endpoint lookups while the manager is still registering, and the pause
/// between them: 100 x 20 ms = ~2 s, comfortably inside the manager's 3 s hello
@@ -42,14 +42,14 @@ pub fn hello(role: Role, device_id: u64) ?ipc.Handle {
return null;
};
const message = protocol.Hello{ .role = @intFromEnum(role), .device_id = device_id };
var reply: [protocol.reply_size]u8 = undefined;
const message = device_manager_protocol.Hello{ .role = @intFromEnum(role), .device_id = device_id };
var reply: [device_manager_protocol.reply_size]u8 = undefined;
const length = ipc.call(manager, std.mem.asBytes(&message), &reply) catch {
std.log.info("hello call failed", .{});
return null;
};
if (length < protocol.reply_size or
std.mem.bytesToValue(protocol.HelloReply, reply[0..protocol.reply_size]).status != 0)
if (length < device_manager_protocol.reply_size or
std.mem.bytesToValue(device_manager_protocol.HelloReply, reply[0..device_manager_protocol.reply_size]).status != 0)
{
std.log.info("hello refused", .{});
return null;
+36 -36
View File
@@ -6,7 +6,7 @@
const std = @import("std");
const ipc = @import("ipc.zig");
const system = @import("system.zig");
const protocol = @import("display-protocol");
const display_protocol = @import("display-protocol");
/// The display's current mode, as `info()` reports it.
pub const Info = struct {
@@ -36,43 +36,43 @@ fn service() ?ipc.Handle {
/// Send one request, receive its reply; true on a zero status. `out` receives the reply
/// so callers can read `info`/`layer` fields on success.
fn transact(request: protocol.Request, out: *protocol.Reply) bool {
fn transact(request: display_protocol.Request, out: *display_protocol.Reply) bool {
const h = service() orelse return false;
var req = request;
var reply: [protocol.reply_size]u8 = undefined;
var reply: [display_protocol.reply_size]u8 = undefined;
const len = ipc.call(h, std.mem.asBytes(&req), &reply) catch return false;
if (len < protocol.reply_size) return false;
out.* = std.mem.bytesToValue(protocol.Reply, reply[0..protocol.reply_size]);
if (len < display_protocol.reply_size) return false;
out.* = std.mem.bytesToValue(display_protocol.Reply, reply[0..display_protocol.reply_size]);
return out.status == 0;
}
/// The display's current mode, or null if the service never came up.
pub fn info() ?Info {
var reply: protocol.Reply = undefined;
if (!transact(.{ .operation = @intFromEnum(protocol.Operation.info) }, &reply)) return null;
var reply: display_protocol.Reply = undefined;
if (!transact(.{ .operation = @intFromEnum(display_protocol.Operation.info) }, &reply)) return null;
return .{ .width = reply.width, .height = reply.height, .pitch = reply.pitch, .format = reply.format };
}
/// Composite the dirty layers and flush the frame to the screen.
pub fn present() bool {
var reply: protocol.Reply = undefined;
return transact(.{ .operation = @intFromEnum(protocol.Operation.present) }, &reply);
var reply: display_protocol.Reply = undefined;
return transact(.{ .operation = @intFromEnum(display_protocol.Operation.present) }, &reply);
}
/// One selectable display mode.
pub const Mode = protocol.Mode;
pub const Mode = display_protocol.Mode;
/// Fill `out` with the resolutions the display can switch to; returns how many were written
/// (zero on the GOP floor, or if the service never came up).
pub fn modes(out: []Mode) usize {
const h = service() orelse return 0;
var request = protocol.Request{ .operation = @intFromEnum(protocol.Operation.get_modes) };
var reply: [protocol.modes_reply_size]u8 = undefined;
var request = display_protocol.Request{ .operation = @intFromEnum(display_protocol.Operation.get_modes) };
var reply: [display_protocol.modes_reply_size]u8 = undefined;
const len = ipc.call(h, std.mem.asBytes(&request), &reply) catch return 0;
if (len < protocol.modes_reply_size) return 0;
const answer = std.mem.bytesToValue(protocol.ModesReply, reply[0..protocol.modes_reply_size]);
if (len < display_protocol.modes_reply_size) return 0;
const answer = std.mem.bytesToValue(display_protocol.ModesReply, reply[0..display_protocol.modes_reply_size]);
if (answer.status != 0) return 0;
const count = @min(@min(answer.count, protocol.max_modes), out.len);
const count = @min(@min(answer.count, display_protocol.max_modes), out.len);
for (0..count) |i| out[i] = answer.modes[i];
return count;
}
@@ -80,8 +80,8 @@ pub fn modes(out: []Mode) usize {
/// Change the display resolution. Only a native backend that supports mode-setting honours it
/// (on the GOP floor it returns false); on success the display's `info()` reports the new mode.
pub fn setMode(width: u32, height: u32) bool {
var reply: protocol.Reply = undefined;
const changed = transact(.{ .operation = @intFromEnum(protocol.Operation.set_mode), .width = width, .height = height }, &reply);
var reply: display_protocol.Reply = undefined;
const changed = transact(.{ .operation = @intFromEnum(display_protocol.Operation.set_mode), .width = width, .height = height }, &reply);
if (changed) mode = null; // the cached mode is stale now
return changed;
}
@@ -100,7 +100,7 @@ fn cachedInfo() ?Info {
/// client packs colours through this so it never has to know the byte order itself.
pub fn color(r: u8, g: u8, b: u8) u32 {
const format = if (cachedInfo()) |i| i.format else 0;
return protocol.pack(format, r, g, b);
return display_protocol.pack(format, r, g, b);
}
/// A handle to a server-owned layer: a positioned, z-ordered surface the client draws
@@ -111,9 +111,9 @@ pub const Layer = struct {
/// Fill a rectangle of this layer (layer-local coordinates) with a native `colour`.
pub fn fill(self: Layer, x: i32, y: i32, w: u32, h: u32, colour: u32) bool {
var reply: protocol.Reply = undefined;
var reply: display_protocol.Reply = undefined;
return transact(.{
.operation = @intFromEnum(protocol.Operation.fill_rect),
.operation = @intFromEnum(display_protocol.Operation.fill_rect),
.layer = self.id,
.x = @bitCast(x),
.y = @bitCast(y),
@@ -125,10 +125,10 @@ pub const Layer = struct {
/// Copy a `w`×`h` tile of native pixels (row-major, little-endian bytes) into this
/// layer at (`x`, `y`). The tile rides inline in the request, so `w*h*4` must fit
/// `protocol.maximum_payload`.
/// `display_protocol.maximum_payload`.
pub fn blitTile(self: Layer, x: i32, y: i32, w: u32, h: u32, pixels: []const u8) bool {
var request = protocol.Request{
.operation = @intFromEnum(protocol.Operation.blit_tile),
var request = display_protocol.Request{
.operation = @intFromEnum(display_protocol.Operation.blit_tile),
.layer = self.id,
.x = @bitCast(x),
.y = @bitCast(y),
@@ -136,22 +136,22 @@ pub const Layer = struct {
.height = h,
};
const header = std.mem.asBytes(&request);
if (header.len + pixels.len > protocol.message_maximum) return false;
var buffer: [protocol.message_maximum]u8 = undefined;
if (header.len + pixels.len > display_protocol.message_maximum) return false;
var buffer: [display_protocol.message_maximum]u8 = undefined;
@memcpy(buffer[0..header.len], header);
@memcpy(buffer[header.len..][0..pixels.len], pixels);
const h_svc = service() orelse return false;
var reply: [protocol.reply_size]u8 = undefined;
var reply: [display_protocol.reply_size]u8 = undefined;
const len = ipc.call(h_svc, buffer[0 .. header.len + pixels.len], &reply) catch return false;
if (len < protocol.reply_size) return false;
return std.mem.bytesToValue(protocol.Reply, reply[0..protocol.reply_size]).status == 0;
if (len < display_protocol.reply_size) return false;
return std.mem.bytesToValue(display_protocol.Reply, reply[0..display_protocol.reply_size]).status == 0;
}
/// Move / restack / show or hide the layer.
pub fn configure(self: Layer, x: i32, y: i32, z: u32, visible: bool) bool {
var reply: protocol.Reply = undefined;
var reply: display_protocol.Reply = undefined;
return transact(.{
.operation = @intFromEnum(protocol.Operation.configure_layer),
.operation = @intFromEnum(display_protocol.Operation.configure_layer),
.layer = self.id,
.x = @bitCast(x),
.y = @bitCast(y),
@@ -163,9 +163,9 @@ pub const Layer = struct {
/// Mark a rectangle of this layer (layer-local) dirty for the next present — for when
/// the layer's pixels changed without a drawing call the compositor already tracked.
pub fn damage(self: Layer, x: i32, y: i32, w: u32, h: u32) bool {
var reply: protocol.Reply = undefined;
var reply: display_protocol.Reply = undefined;
return transact(.{
.operation = @intFromEnum(protocol.Operation.damage),
.operation = @intFromEnum(display_protocol.Operation.damage),
.layer = self.id,
.x = @bitCast(x),
.y = @bitCast(y),
@@ -176,17 +176,17 @@ pub const Layer = struct {
/// Release the layer and its surface.
pub fn destroy(self: Layer) bool {
var reply: protocol.Reply = undefined;
return transact(.{ .operation = @intFromEnum(protocol.Operation.destroy_layer), .layer = self.id }, &reply);
var reply: display_protocol.Reply = undefined;
return transact(.{ .operation = @intFromEnum(display_protocol.Operation.destroy_layer), .layer = self.id }, &reply);
}
};
/// Create a server-owned layer of `w`×`h` pixels at screen (`x`, `y`) with stacking order
/// `z` (higher is nearer the front), initially visible. Returns a handle, or null.
pub fn createLayer(x: i32, y: i32, w: u32, h: u32, z: u32) ?Layer {
var reply: protocol.Reply = undefined;
var reply: display_protocol.Reply = undefined;
if (!transact(.{
.operation = @intFromEnum(protocol.Operation.create_layer),
.operation = @intFromEnum(display_protocol.Operation.create_layer),
.x = @bitCast(x),
.y = @bitCast(y),
.width = w,
+37 -37
View File
@@ -13,11 +13,11 @@
const std = @import("std");
const ipc = @import("ipc.zig");
const system = @import("system.zig");
const protocol = @import("vfs-protocol");
const vfs_protocol = @import("vfs-protocol");
/// The kind of a filesystem node — re-exported so a caller need not import the
/// wire protocol.
pub const Kind = protocol.NodeKind;
pub const Kind = vfs_protocol.NodeKind;
/// A node's metadata (the answer to a status request).
pub const Attributes = struct {
@@ -54,9 +54,9 @@ pub const OpenOptions = struct {
fn wireFlags(self: OpenOptions) u32 {
var f: u32 = 0;
if (self.create) f |= protocol.create;
if (self.directory) f |= protocol.directory;
if (self.truncate) f |= protocol.truncate;
if (self.create) f |= vfs_protocol.create;
if (self.directory) f |= vfs_protocol.directory;
if (self.truncate) f |= vfs_protocol.truncate;
return f;
}
};
@@ -87,22 +87,22 @@ fn resolve(path: []const u8, flags: usize) ?Route {
}
}
const Result = struct { reply: protocol.Reply, payload: []u8 };
const Result = struct { reply: vfs_protocol.Reply, payload: []u8 };
// One request/reply round trip: [Request header][send payload] -> backend ->
// [Reply header][receive payload]. The receive payload lands in `out`.
fn transact(h: ipc.Handle, request: protocol.Request, send: []const u8, out: []u8) ?Result {
var message: [protocol.message_maximum]u8 = undefined;
@memcpy(message[0..protocol.request_size], std.mem.asBytes(&request));
const slen = @min(send.len, protocol.maximum_payload);
@memcpy(message[protocol.request_size..][0..slen], send[0..slen]);
fn transact(h: ipc.Handle, request: vfs_protocol.Request, send: []const u8, out: []u8) ?Result {
var message: [vfs_protocol.message_maximum]u8 = undefined;
@memcpy(message[0..vfs_protocol.request_size], std.mem.asBytes(&request));
const slen = @min(send.len, vfs_protocol.maximum_payload);
@memcpy(message[vfs_protocol.request_size..][0..slen], send[0..slen]);
var rbuf: [protocol.message_maximum]u8 = undefined;
const n = ipc.call(h, message[0 .. protocol.request_size + slen], &rbuf) catch return null;
if (n < protocol.reply_size) return null;
const reply = std.mem.bytesToValue(protocol.Reply, rbuf[0..protocol.reply_size]);
const rpl = @min(n - protocol.reply_size, out.len);
@memcpy(out[0..rpl], rbuf[protocol.reply_size..][0..rpl]);
var rbuf: [vfs_protocol.message_maximum]u8 = undefined;
const n = ipc.call(h, message[0 .. vfs_protocol.request_size + slen], &rbuf) catch return null;
if (n < vfs_protocol.reply_size) return null;
const reply = std.mem.bytesToValue(vfs_protocol.Reply, rbuf[0..vfs_protocol.reply_size]);
const rpl = @min(n - vfs_protocol.reply_size, out.len);
@memcpy(out[0..rpl], rbuf[vfs_protocol.reply_size..][0..rpl]);
return .{ .reply = reply, .payload = out[0..rpl] };
}
@@ -122,8 +122,8 @@ pub const File = struct {
self.offset += n;
return n;
};
const want: u32 = @intCast(@min(buffer.len, protocol.maximum_payload));
const request = protocol.Request{ .operation = .read, .node = self.node, .offset = self.offset, .len = want, .flags = 0 };
const want: u32 = @intCast(@min(buffer.len, vfs_protocol.maximum_payload));
const request = vfs_protocol.Request{ .operation = .read, .node = self.node, .offset = self.offset, .len = want, .flags = 0 };
const r = transact(h, request, &.{}, buffer) orelse return null;
if (r.reply.status != 0) return null;
self.offset += r.reply.len;
@@ -136,8 +136,8 @@ pub const File = struct {
/// are read-only).
pub fn write(self: *File, data: []const u8) ?usize {
const h = self.backend orelse return null;
const want: u32 = @intCast(@min(data.len, protocol.maximum_payload));
const request = protocol.Request{ .operation = .write, .node = self.node, .offset = self.offset, .len = want, .flags = 0 };
const want: u32 = @intCast(@min(data.len, vfs_protocol.maximum_payload));
const request = vfs_protocol.Request{ .operation = .write, .node = self.node, .offset = self.offset, .len = want, .flags = 0 };
const r = transact(h, request, data[0..want], &.{}) orelse return null;
if (r.reply.status != 0) return null;
self.offset += r.reply.len;
@@ -167,11 +167,11 @@ pub const File = struct {
const a = system.fsNodeStatus(self.node) orelse return null;
return .{ .size = a.size, .kind = if (a.kind == system.file_kind_directory) .directory else .regular, .mtime = a.mtime };
};
const request = protocol.Request{ .operation = .status, .node = self.node, .offset = 0, .len = 0, .flags = 0 };
var buffer: [@sizeOf(protocol.FileStatus)]u8 = undefined;
const request = vfs_protocol.Request{ .operation = .status, .node = self.node, .offset = 0, .len = 0, .flags = 0 };
var buffer: [@sizeOf(vfs_protocol.FileStatus)]u8 = undefined;
const r = transact(h, request, &.{}, &buffer) orelse return null;
if (r.reply.status != 0 or r.payload.len < @sizeOf(protocol.FileStatus)) return null;
const status = std.mem.bytesToValue(protocol.FileStatus, buffer[0..@sizeOf(protocol.FileStatus)]);
if (r.reply.status != 0 or r.payload.len < @sizeOf(vfs_protocol.FileStatus)) return null;
const status = std.mem.bytesToValue(vfs_protocol.FileStatus, buffer[0..@sizeOf(vfs_protocol.FileStatus)]);
return .{ .size = status.size, .kind = kindFromWire(status.kind), .mtime = status.mtime };
}
@@ -179,7 +179,7 @@ pub const File = struct {
/// tokens are permanent — nothing to release.
pub fn close(self: *File) void {
const h = self.backend orelse return;
const request = protocol.Request{ .operation = .close, .node = self.node, .offset = 0, .len = 0, .flags = 0 };
const request = vfs_protocol.Request{ .operation = .close, .node = self.node, .offset = 0, .len = 0, .flags = 0 };
_ = transact(h, request, &.{}, &.{});
}
};
@@ -191,7 +191,7 @@ pub fn open(path: []const u8, options: OpenOptions) ?File {
.kernel => |token| return .{ .node = token, .backend = null },
.backend => |b| {
const relative = route.backendPath();
const request = protocol.Request{ .operation = .open, .node = 0, .offset = 0, .len = @intCast(relative.len), .flags = options.wireFlags() };
const request = vfs_protocol.Request{ .operation = .open, .node = 0, .offset = 0, .len = @intCast(relative.len), .flags = options.wireFlags() };
const r = transact(b.handle, request, relative, &.{}) orelse return null;
if (r.reply.status != 0) return null;
return .{ .node = r.reply.node, .backend = b.handle };
@@ -246,15 +246,15 @@ pub const Directory = struct {
self.cursor += 1;
return true;
};
const request = protocol.Request{ .operation = .readdir, .node = self.node, .offset = self.cursor, .len = 0, .flags = 0 };
var buffer: [protocol.message_maximum]u8 = undefined;
const request = vfs_protocol.Request{ .operation = .readdir, .node = self.node, .offset = self.cursor, .len = 0, .flags = 0 };
var buffer: [vfs_protocol.message_maximum]u8 = undefined;
const r = transact(h, request, &.{}, &buffer) orelse return false;
if (r.reply.status != 0 or r.reply.len == 0) return false; // error or EOF
if (r.payload.len < protocol.directory_entry_size) return false;
const header = std.mem.bytesToValue(protocol.DirectoryEntry, r.payload[0..protocol.directory_entry_size]);
if (r.payload.len < vfs_protocol.directory_entry_size) return false;
const header = std.mem.bytesToValue(vfs_protocol.DirectoryEntry, r.payload[0..vfs_protocol.directory_entry_size]);
entry.kind = kindFromWire(header.kind);
entry.size = header.size;
const source = r.payload[protocol.directory_entry_size..];
const source = r.payload[vfs_protocol.directory_entry_size..];
const nlen = @min(@min(@as(usize, header.name_len), source.len), entry.name_buffer.len);
@memcpy(entry.name_buffer[0..nlen], source[0..nlen]);
entry.name_len = nlen;
@@ -278,11 +278,11 @@ pub fn openDirectory(path: []const u8) ?Directory {
// A path-based request that returns only a status (mkdir, unlink). Kernel-served
// paths (the read-only /system) refuse mutation by construction: the resolve
// must land on a backend.
fn pathOperation(operation: protocol.Operation, path: []const u8) bool {
fn pathOperation(operation: vfs_protocol.Operation, path: []const u8) bool {
const route = resolve(path, 0) orelse return false;
if (route != .backend) return false;
const relative = route.backendPath();
const request = protocol.Request{ .operation = operation, .node = 0, .offset = 0, .len = @intCast(relative.len), .flags = 0 };
const request = vfs_protocol.Request{ .operation = operation, .node = 0, .offset = 0, .len = @intCast(relative.len), .flags = 0 };
const r = transact(route.backend.handle, request, relative, &.{}) orelse return false;
return r.reply.status == 0;
}
@@ -329,12 +329,12 @@ pub fn rename(old_path: []const u8, new_path: []const u8) bool {
const old_relative = old_route.backendPath();
const new_relative = new_route.backendPath();
const total = old_relative.len + 1 + new_relative.len;
if (total > protocol.maximum_payload) return false;
var payload: [protocol.maximum_payload]u8 = undefined;
if (total > vfs_protocol.maximum_payload) return false;
var payload: [vfs_protocol.maximum_payload]u8 = undefined;
@memcpy(payload[0..old_relative.len], old_relative);
payload[old_relative.len] = 0;
@memcpy(payload[old_relative.len + 1 ..][0..new_relative.len], new_relative);
const request = protocol.Request{ .operation = .rename, .node = 0, .offset = 0, .len = @intCast(total), .flags = 0 };
const request = vfs_protocol.Request{ .operation = .rename, .node = 0, .offset = 0, .len = @intCast(total), .flags = 0 };
const r = transact(old_route.backend.handle, request, payload[0..total], &.{}) orelse return false;
return r.reply.status == 0;
}
+27 -27
View File
@@ -25,24 +25,24 @@ const std = @import("std");
const abi = @import("abi");
const ipc = @import("ipc.zig");
const system = @import("system.zig");
const protocol = @import("input-protocol");
const input_protocol = @import("input-protocol");
pub const DeviceKind = protocol.DeviceKind;
pub const InputEvent = protocol.InputEvent;
pub const KeyEvent = protocol.KeyEvent;
pub const MouseEvent = protocol.MouseEvent;
pub const JoystickEvent = protocol.JoystickEvent;
pub const EventKind = protocol.EventKind;
pub const MouseEventKind = protocol.MouseEventKind;
pub const JoystickEventKind = protocol.JoystickEventKind;
pub const Keycode = protocol.Keycode;
pub const DeviceKind = input_protocol.DeviceKind;
pub const InputEvent = input_protocol.InputEvent;
pub const KeyEvent = input_protocol.KeyEvent;
pub const MouseEvent = input_protocol.MouseEvent;
pub const JoystickEvent = input_protocol.JoystickEvent;
pub const EventKind = input_protocol.EventKind;
pub const MouseEventKind = input_protocol.MouseEventKind;
pub const JoystickEventKind = input_protocol.JoystickEventKind;
pub const Keycode = input_protocol.Keycode;
/// Interest masks re-exported so a caller can `subscribe(input.device_keyboard |
/// input.device_mouse)`.
pub const device_keyboard = protocol.device_keyboard;
pub const device_mouse = protocol.device_mouse;
pub const device_joystick = protocol.device_joystick;
pub const device_all = protocol.device_all;
pub const device_keyboard = input_protocol.device_keyboard;
pub const device_mouse = input_protocol.device_mouse;
pub const device_joystick = input_protocol.device_joystick;
pub const device_all = input_protocol.device_all;
/// Look up the input service, retrying while it is still coming up. Both a subscriber and
/// a source race the service's registration at boot, so both wait for it here rather than
@@ -66,7 +66,7 @@ pub const Subscriber = struct {
/// The endpoint the service delivers events to (created and owned by us; its handle
/// was handed to the service as a capability at subscribe time).
endpoint: ipc.Handle,
receive: [protocol.event_size]u8 = undefined,
receive: [input_protocol.event_size]u8 = undefined,
/// Block until the next event is pushed, and return it. Events arrive as asynchronous
/// buffered messages (`ipc_send` from the service), so nothing is owed in reply — the
@@ -74,8 +74,8 @@ pub const Subscriber = struct {
/// (there should be none), so callers can loop.
pub fn next(self: *Subscriber) ?InputEvent {
const got = ipc.replyWait(self.endpoint, &.{}, &self.receive, null);
if (!got.isMessage() or got.len < protocol.event_size) return null;
return std.mem.bytesToValue(InputEvent, self.receive[0..protocol.event_size]);
if (!got.isMessage() or got.len < input_protocol.event_size) return null;
return std.mem.bytesToValue(InputEvent, self.receive[0..input_protocol.event_size]);
}
};
@@ -86,11 +86,11 @@ pub fn subscribe(device_mask: u32) ?Subscriber {
const service = lookupService() orelse return null;
const endpoint = ipc.createIpcEndpoint() orelse return null;
var request = protocol.Request{ .operation = @intFromEnum(protocol.Operation.subscribe), .device_mask = device_mask };
var reply: [protocol.reply_size]u8 = undefined;
var request = input_protocol.Request{ .operation = @intFromEnum(input_protocol.Operation.subscribe), .device_mask = device_mask };
var reply: [input_protocol.reply_size]u8 = undefined;
const result = ipc.callCap(service, std.mem.asBytes(&request), &reply, endpoint) catch return null;
if (result.len < protocol.reply_size) return null;
if (std.mem.bytesToValue(protocol.Reply, reply[0..protocol.reply_size]).status != 0) return null;
if (result.len < input_protocol.reply_size) return null;
if (std.mem.bytesToValue(input_protocol.Reply, reply[0..input_protocol.reply_size]).status != 0) return null;
return .{ .endpoint = endpoint };
}
@@ -149,11 +149,11 @@ pub const Publisher = struct {
service: ipc.Handle,
fn publish(self: Publisher, event: InputEvent) bool {
var request = protocol.Request{ .operation = @intFromEnum(protocol.Operation.publish), .event = event };
var reply: [protocol.reply_size]u8 = undefined;
var request = input_protocol.Request{ .operation = @intFromEnum(input_protocol.Operation.publish), .event = event };
var reply: [input_protocol.reply_size]u8 = undefined;
const len = ipc.call(self.service, std.mem.asBytes(&request), &reply) catch return false;
if (len < protocol.reply_size) return false;
return std.mem.bytesToValue(protocol.Reply, reply[0..protocol.reply_size]).status == 0;
if (len < input_protocol.reply_size) return false;
return std.mem.bytesToValue(input_protocol.Reply, reply[0..input_protocol.reply_size]).status == 0;
}
/// Broadcast a keyboard event to every subscriber that took keyboard events.
@@ -204,8 +204,8 @@ pub fn syntheticKeyEvent(step: usize) KeyEvent {
pub fn syntheticMouseEvent(step: usize) MouseEvent {
return switch (step % 3) {
0 => .{ .kind = @intFromEnum(MouseEventKind.motion), .button = 0, .dx = 1, .dy = 1, .scroll_x = 0, .scroll_y = 0, .buttons = 0 },
1 => .{ .kind = @intFromEnum(MouseEventKind.button_down), .button = protocol.mouse_button_left, .dx = 0, .dy = 0, .scroll_x = 0, .scroll_y = 0, .buttons = protocol.mouse_button_left },
else => .{ .kind = @intFromEnum(MouseEventKind.button_up), .button = protocol.mouse_button_left, .dx = 0, .dy = 0, .scroll_x = 0, .scroll_y = 0, .buttons = 0 },
1 => .{ .kind = @intFromEnum(MouseEventKind.button_down), .button = input_protocol.mouse_button_left, .dx = 0, .dy = 0, .scroll_x = 0, .scroll_y = 0, .buttons = input_protocol.mouse_button_left },
else => .{ .kind = @intFromEnum(MouseEventKind.button_up), .button = input_protocol.mouse_button_left, .dx = 0, .dy = 0, .scroll_x = 0, .scroll_y = 0, .buttons = 0 },
};
}
+5 -5
View File
@@ -12,7 +12,7 @@
const std = @import("std");
const runtime = @import("runtime");
const protocol = @import("device-manager-protocol");
const device_manager_protocol = @import("device-manager-protocol");
const device = runtime.device;
const pci_class = @import("pci-class");
@@ -32,7 +32,7 @@ fn logFunction(bus: u64, dev: u64, function: u64, class_triple: u32) void {
_ = runtime.system.write(text);
}
var bridge_id: u64 = protocol.no_device;
var bridge_id: u64 = device_manager_protocol.no_device;
var ecam_base: usize = 0;
var ecam_physical: u64 = 0;
var start_bus: u64 = 0;
@@ -209,13 +209,13 @@ fn registerAndReport(bus: u64, dev: u64, function: u64, class_triple: u32) void
std.log.info("register refused for {d}:{d}.{d}", .{ bus, dev, function });
return;
};
const report = protocol.ChildAdded{
const report = device_manager_protocol.ChildAdded{
.parent = bridge_id,
.bus_address = (bus << 8) | (dev << 3) | function,
.identity = class_triple,
.device_id = registered,
};
var reply: [protocol.message_maximum]u8 = undefined;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(manager_handle, std.mem.asBytes(&report), &reply) catch {
std.log.info("child report for {d}:{d}.{d} failed", .{ bus, dev, function });
};
@@ -235,7 +235,7 @@ pub fn main(init: runtime.process.Init) void {
std.log.info("malformed bridge device id '{s}'", .{argument});
return;
};
runtime.service.run(protocol.message_maximum, .{
runtime.service.run(device_manager_protocol.message_maximum, .{
.init = initialise,
.on_message = onMessage,
});
+43 -43
View File
@@ -15,11 +15,11 @@
const std = @import("std");
const runtime = @import("runtime");
const protocol = @import("device-manager-protocol");
const device_manager_protocol = @import("device-manager-protocol");
const device = runtime.device;
const usb_ids = @import("usb-ids");
const usb_abi = @import("usb-abi");
const transfer = @import("usb-transfer-protocol");
const usb_transfer_protocol = @import("usb-transfer-protocol");
const library = @import("usb-xhci-library.zig");
/// The controller engine (reset, rings, transfers), stood up in `initialise`.
@@ -64,7 +64,7 @@ fn reportEndpointFor(device_token: u64) ?usize {
return null;
}
var controller_id: u64 = protocol.no_device;
var controller_id: u64 = device_manager_protocol.no_device;
/// Claim the assigned controller, find its register window, and hello the
/// manager. Any failure returns false: the process exits cleanly, which the
@@ -300,11 +300,11 @@ fn tearDownHubDevice(manager: runtime.ipc.Handle, engine: *library.Controller, d
const key = hubPortKey(dev.parent_slot, dev.parent_port);
for (dev.interfaces[0..dev.interface_count]) |*interface| {
if (interface.registered_device_id == 0) continue;
const event = protocol.ChildRemoved{
const event = device_manager_protocol.ChildRemoved{
.parent = controller_id,
.bus_address = (@as(u64, key) << 8) | interface.number,
};
var reply: [protocol.message_maximum]u8 = undefined;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(manager, std.mem.asBytes(&event), &reply) catch {};
interface.registered_device_id = 0;
}
@@ -330,11 +330,11 @@ fn tearDownPort(manager: runtime.ipc.Handle, engine: *library.Controller, port:
std.log.info("port {d} disconnected", .{port});
for (usb_device.interfaces[0..usb_device.interface_count]) |*interface| {
if (interface.registered_device_id == 0) continue;
const event = protocol.ChildRemoved{
const event = device_manager_protocol.ChildRemoved{
.parent = controller_id,
.bus_address = (@as(u64, port) << 8) | interface.number,
};
var reply: [protocol.message_maximum]u8 = undefined;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(manager, std.mem.asBytes(&event), &reply) catch {
std.log.info("child-removed report for port {d} interface {d} failed", .{ port, interface.number });
};
@@ -371,13 +371,13 @@ fn reportInterface(manager: runtime.ipc.Handle, port: u32, interface: library.In
return null;
};
const report = protocol.ChildAdded{
const report = device_manager_protocol.ChildAdded{
.parent = controller_id,
.bus_address = (@as(u64, port) << 8) | interface.number,
.identity = identity,
.device_id = registered,
};
var reply: [protocol.message_maximum]u8 = undefined;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(manager, std.mem.asBytes(&report), &reply) catch {
std.log.info("child report for port {d} interface {d} failed", .{ port, interface.number });
return null;
@@ -401,10 +401,10 @@ fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime
if (message.len < 4) return 0;
const operation = std.mem.readInt(u32, message[0..4], .little);
return switch (operation) {
@intFromEnum(transfer.Operation.open) => handleOpen(message, reply, capability),
@intFromEnum(transfer.Operation.control) => handleControl(message, reply),
@intFromEnum(transfer.Operation.interrupt_subscribe) => handleSubscribe(message, reply),
@intFromEnum(transfer.Operation.bulk) => handleBulk(message, reply),
@intFromEnum(usb_transfer_protocol.Operation.open) => handleOpen(message, reply, capability),
@intFromEnum(usb_transfer_protocol.Operation.control) => handleControl(message, reply),
@intFromEnum(usb_transfer_protocol.Operation.interrupt_subscribe) => handleSubscribe(message, reply),
@intFromEnum(usb_transfer_protocol.Operation.bulk) => handleBulk(message, reply),
else => 0,
};
}
@@ -419,14 +419,14 @@ fn writeReply(reply: []u8, value: anytype) usize {
/// endpoint (for interrupt reports), and answer with a device token + the
/// interface's endpoints so the class driver need not re-read the config.
fn handleOpen(message: []const u8, reply: []u8, capability: ?runtime.ipc.Handle) usize {
if (message.len < @sizeOf(transfer.OpenRequest)) return writeReply(reply, transfer.OpenReply{ .status = -1, .endpoint_count = 0, .device_token = 0, .interface_class = 0, .interface_subclass = 0, .interface_protocol = 0, .interface_number = 0 });
const request = std.mem.bytesToValue(transfer.OpenRequest, message[0..@sizeOf(transfer.OpenRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, transfer.OpenReply{ .status = -1, .endpoint_count = 0, .device_token = 0, .interface_class = 0, .interface_subclass = 0, .interface_protocol = 0, .interface_number = 0 });
const found = engine.findInterface(request.device_id) orelse return writeReply(reply, transfer.OpenReply{ .status = -1, .endpoint_count = 0, .device_token = 0, .interface_class = 0, .interface_subclass = 0, .interface_protocol = 0, .interface_number = 0 });
if (message.len < @sizeOf(usb_transfer_protocol.OpenRequest)) return writeReply(reply, usb_transfer_protocol.OpenReply{ .status = -1, .endpoint_count = 0, .device_token = 0, .interface_class = 0, .interface_subclass = 0, .interface_protocol = 0, .interface_number = 0 });
const request = std.mem.bytesToValue(usb_transfer_protocol.OpenRequest, message[0..@sizeOf(usb_transfer_protocol.OpenRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, usb_transfer_protocol.OpenReply{ .status = -1, .endpoint_count = 0, .device_token = 0, .interface_class = 0, .interface_subclass = 0, .interface_protocol = 0, .interface_number = 0 });
const found = engine.findInterface(request.device_id) orelse return writeReply(reply, usb_transfer_protocol.OpenReply{ .status = -1, .endpoint_count = 0, .device_token = 0, .interface_class = 0, .interface_subclass = 0, .interface_protocol = 0, .interface_number = 0 });
if (capability) |endpoint| recordOpen(request.device_id, endpoint);
var open_reply = transfer.OpenReply{
var open_reply = usb_transfer_protocol.OpenReply{
.status = 0,
.endpoint_count = found.interface.endpoint_count,
.device_token = request.device_id,
@@ -435,7 +435,7 @@ fn handleOpen(message: []const u8, reply: []u8, capability: ?runtime.ipc.Handle)
.interface_protocol = found.interface.protocol,
.interface_number = found.interface.number,
};
const count = @min(found.interface.endpoint_count, transfer.max_reported_endpoints);
const count = @min(found.interface.endpoint_count, usb_transfer_protocol.max_reported_endpoints);
for (found.interface.endpoints[0..count], 0..) |endpoint, index| {
open_reply.endpoints[index] = .{
.address = endpoint.address,
@@ -449,45 +449,45 @@ fn handleOpen(message: []const u8, reply: []u8, capability: ?runtime.ipc.Handle)
/// control: one EP0 control transfer, small data inline both ways.
fn handleControl(message: []const u8, reply: []u8) usize {
if (message.len < @sizeOf(transfer.ControlRequest)) return writeReply(reply, transfer.ControlReply{ .status = -1, .actual_length = 0 });
const request = std.mem.bytesToValue(transfer.ControlRequest, message[0..@sizeOf(transfer.ControlRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, transfer.ControlReply{ .status = -1, .actual_length = 0 });
const found = engine.findInterface(request.device_token) orelse return writeReply(reply, transfer.ControlReply{ .status = -1, .actual_length = 0 });
if (message.len < @sizeOf(usb_transfer_protocol.ControlRequest)) return writeReply(reply, usb_transfer_protocol.ControlReply{ .status = -1, .actual_length = 0 });
const request = std.mem.bytesToValue(usb_transfer_protocol.ControlRequest, message[0..@sizeOf(usb_transfer_protocol.ControlRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, usb_transfer_protocol.ControlReply{ .status = -1, .actual_length = 0 });
const found = engine.findInterface(request.device_token) orelse return writeReply(reply, usb_transfer_protocol.ControlReply{ .status = -1, .actual_length = 0 });
const setup = std.mem.bytesToValue(usb_abi.Request, &request.setup);
const direction_in = request.direction_in != 0;
const data_length = @min(request.data_length, transfer.max_inline_data);
var data: [transfer.max_inline_data]u8 = undefined;
const data_length = @min(request.data_length, usb_transfer_protocol.max_inline_data);
var data: [usb_transfer_protocol.max_inline_data]u8 = undefined;
if (!direction_in) @memcpy(data[0..data_length], request.data[0..data_length]);
const ok = engine.controlTransfer(found.device, setup, data[0..data_length], direction_in);
var control_reply = transfer.ControlReply{ .status = if (ok) 0 else -1, .actual_length = if (ok) data_length else 0 };
var control_reply = usb_transfer_protocol.ControlReply{ .status = if (ok) 0 else -1, .actual_length = if (ok) data_length else 0 };
if (ok and direction_in) @memcpy(control_reply.data[0..data_length], data[0..data_length]);
return writeReply(reply, control_reply);
}
/// interrupt_subscribe: arm periodic IN polling; reports flow back asynchronously.
fn handleSubscribe(message: []const u8, reply: []u8) usize {
if (message.len < @sizeOf(transfer.InterruptSubscribeRequest)) return writeReply(reply, transfer.InterruptSubscribeReply{ .status = -1 });
const request = std.mem.bytesToValue(transfer.InterruptSubscribeRequest, message[0..@sizeOf(transfer.InterruptSubscribeRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, transfer.InterruptSubscribeReply{ .status = -1 });
const found = engine.findInterface(request.device_token) orelse return writeReply(reply, transfer.InterruptSubscribeReply{ .status = -1 });
const endpoint = library.Controller.endpointForAddress(found.interface, request.endpoint_address) orelse return writeReply(reply, transfer.InterruptSubscribeReply{ .status = -1 });
const report_endpoint = reportEndpointFor(request.device_token) orelse return writeReply(reply, transfer.InterruptSubscribeReply{ .status = -1 });
if (message.len < @sizeOf(usb_transfer_protocol.InterruptSubscribeRequest)) return writeReply(reply, usb_transfer_protocol.InterruptSubscribeReply{ .status = -1 });
const request = std.mem.bytesToValue(usb_transfer_protocol.InterruptSubscribeRequest, message[0..@sizeOf(usb_transfer_protocol.InterruptSubscribeRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, usb_transfer_protocol.InterruptSubscribeReply{ .status = -1 });
const found = engine.findInterface(request.device_token) orelse return writeReply(reply, usb_transfer_protocol.InterruptSubscribeReply{ .status = -1 });
const endpoint = library.Controller.endpointForAddress(found.interface, request.endpoint_address) orelse return writeReply(reply, usb_transfer_protocol.InterruptSubscribeReply{ .status = -1 });
const report_endpoint = reportEndpointFor(request.device_token) orelse return writeReply(reply, usb_transfer_protocol.InterruptSubscribeReply{ .status = -1 });
const ok = engine.subscribeInterrupt(found.device, endpoint, request.device_token, report_endpoint);
return writeReply(reply, transfer.InterruptSubscribeReply{ .status = if (ok) 0 else -1 });
return writeReply(reply, usb_transfer_protocol.InterruptSubscribeReply{ .status = if (ok) 0 else -1 });
}
/// bulk: one bulk transfer to/from the class driver's own DMA buffer (by physical
/// address), so sector-sized data never crosses IPC.
fn handleBulk(message: []const u8, reply: []u8) usize {
if (message.len < @sizeOf(transfer.BulkRequest)) return writeReply(reply, transfer.BulkReply{ .status = -1, .actual_length = 0 });
const request = std.mem.bytesToValue(transfer.BulkRequest, message[0..@sizeOf(transfer.BulkRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, transfer.BulkReply{ .status = -1, .actual_length = 0 });
const found = engine.findInterface(request.device_token) orelse return writeReply(reply, transfer.BulkReply{ .status = -1, .actual_length = 0 });
const endpoint = library.Controller.endpointForAddress(found.interface, request.endpoint_address) orelse return writeReply(reply, transfer.BulkReply{ .status = -1, .actual_length = 0 });
if (message.len < @sizeOf(usb_transfer_protocol.BulkRequest)) return writeReply(reply, usb_transfer_protocol.BulkReply{ .status = -1, .actual_length = 0 });
const request = std.mem.bytesToValue(usb_transfer_protocol.BulkRequest, message[0..@sizeOf(usb_transfer_protocol.BulkRequest)]);
const engine = if (controller) |*c| c else return writeReply(reply, usb_transfer_protocol.BulkReply{ .status = -1, .actual_length = 0 });
const found = engine.findInterface(request.device_token) orelse return writeReply(reply, usb_transfer_protocol.BulkReply{ .status = -1, .actual_length = 0 });
const endpoint = library.Controller.endpointForAddress(found.interface, request.endpoint_address) orelse return writeReply(reply, usb_transfer_protocol.BulkReply{ .status = -1, .actual_length = 0 });
const transferred = engine.bulkTransfer(found.device, endpoint, request.physical_address, request.length);
return writeReply(reply, transfer.BulkReply{ .status = if (transferred != null) 0 else -1, .actual_length = transferred orelse 0 });
return writeReply(reply, usb_transfer_protocol.BulkReply{ .status = if (transferred != null) 0 else -1, .actual_length = transferred orelse 0 });
}
/// The poll timer landed: drain any interrupt reports off the event ring and push
@@ -543,12 +543,12 @@ fn onNotification(badge: u64) void {
if (serviced >= 32) break;
}
while (engine.takeReport()) |report| {
var message = transfer.InterruptReport{
var message = usb_transfer_protocol.InterruptReport{
.device_token = report.device_token,
.endpoint_address = report.endpoint_address,
.length = @intCast(@min(report.length, transfer.max_report_data)),
.length = @intCast(@min(report.length, usb_transfer_protocol.max_report_data)),
};
const n = @min(report.length, transfer.max_report_data);
const n = @min(report.length, usb_transfer_protocol.max_report_data);
@memcpy(message.data[0..n], report.data[0..n]);
_ = runtime.ipc.send(report.report_endpoint, std.mem.asBytes(&message));
}
@@ -565,7 +565,7 @@ pub fn main(init: runtime.process.Init) void {
std.log.info("malformed controller device id '{s}'", .{argument});
return;
};
runtime.service.run(transfer.message_maximum, .{
runtime.service.run(usb_transfer_protocol.message_maximum, .{
.service = .usb_bus,
.init = initialise,
.on_message = onMessage,
+16 -16
View File
@@ -15,8 +15,8 @@ const runtime = @import("runtime");
const aml = @import("aml");
const acpi_ids = @import("acpi-ids");
const device = runtime.device;
const protocol = @import("device-manager-protocol");
const power = @import("power-protocol");
const device_manager_protocol = @import("device-manager-protocol");
const power_protocol = @import("power-protocol");
/// AML opcode/prefix bytes by name (`zero_opcode`, `byte_prefix`, …) — so the `_HID`
/// integer decode names the opcodes instead of bare 0x0A/0x0B/… (docs/coding-standards.md).
const opcodes = aml.opcodes;
@@ -184,7 +184,7 @@ pub fn main(init: runtime.process.Init) void {
readFadt(fadt);
s5_valid = readSleepS5(&persistent_namespace);
runtime.service.run(power.message_maximum, .{
runtime.service.run(power_protocol.message_maximum, .{
.service = .power,
.init = onInit,
.on_message = onMessage,
@@ -215,9 +215,9 @@ fn onInit(endpoint: runtime.ipc.Handle) bool {
else
std.log.info("reported {s} (device {d}, {d} resources)", .{ hid, entry.device_id, entry.resource_count });
if (manager) |h| {
var report = protocol.ChildAdded{ .parent = node_id, .bus_address = entry.device_id, .identity = 0, .device_id = entry.device_id };
var report = device_manager_protocol.ChildAdded{ .parent = node_id, .bus_address = entry.device_id, .identity = 0, .device_id = entry.device_id };
@memcpy(report.hid[0..entry.hid_len], entry.hid[0..entry.hid_len]);
var reply: [protocol.message_maximum]u8 = undefined;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(h, std.mem.asBytes(&report), &reply) catch {};
}
}
@@ -365,8 +365,8 @@ fn publishNotify(node: *aml.Node, code: u64) void {
// Map the notified device's _HID to a domain event where we recognize it.
var hid: [8]u8 = .{0} ** 8;
if (readHid(node, &global_interpreter)) |h| hid = h;
const which: power.Event = if (std.mem.eql(u8, hid[0..7], "PNP0C0A")) .battery else if (std.mem.eql(u8, hid[0..7], "ACPI0003")) .ac else if (std.mem.eql(u8, hid[0..7], "PNP0C0D")) .lid else .notify;
var event = power.EventMessage{ .event = @intFromEnum(which), .code = @truncate(code) };
const which: power_protocol.Event = if (std.mem.eql(u8, hid[0..7], "PNP0C0A")) .battery else if (std.mem.eql(u8, hid[0..7], "ACPI0003")) .ac else if (std.mem.eql(u8, hid[0..7], "PNP0C0D")) .lid else .notify;
var event = power_protocol.EventMessage{ .event = @intFromEnum(which), .code = @truncate(code) };
event.hid = hid;
std.log.info("power: notify {s} code {d}", .{ hid[0..7], code });
publishEvent(std.mem.asBytes(&event));
@@ -380,7 +380,7 @@ fn writeHex2(out: []u8, n: u32) void {
}
fn publishButton() void {
const event = power.EventMessage{ .event = @intFromEnum(power.Event.power_button) };
const event = power_protocol.EventMessage{ .event = @intFromEnum(power_protocol.Event.power_button) };
publishEvent(std.mem.asBytes(&event));
}
@@ -429,7 +429,7 @@ fn onNotification(badge: u64) void {
fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime.ipc.Handle) usize {
if (message.len < 1) return 0;
switch (message[0]) {
@intFromEnum(power.Operation.subscribe) => {
@intFromEnum(power_protocol.Operation.subscribe) => {
var status: i32 = -1;
if (capability) |handle| {
for (&subscribers, 0..) |*slot, si| {
@@ -441,20 +441,20 @@ fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime
}
}
}
const r = power.Reply{ .status = status };
@memcpy(reply[0..@sizeOf(power.Reply)], std.mem.asBytes(&r));
return @sizeOf(power.Reply);
const r = power_protocol.Reply{ .status = status };
@memcpy(reply[0..@sizeOf(power_protocol.Reply)], std.mem.asBytes(&r));
return @sizeOf(power_protocol.Reply);
},
@intFromEnum(power.Operation.shutdown) => {
@intFromEnum(power_protocol.Operation.shutdown) => {
// Honored only from a power subscriber — init, which has already run
// the stop sequence over everything else. The power service is
// mechanism (write S5); deciding *when* to shut down and stopping
// the rest of the system first is init's policy.
const allowed = isSubscriber(sender);
const r = power.Reply{ .status = if (allowed) 0 else -1 };
@memcpy(reply[0..@sizeOf(power.Reply)], std.mem.asBytes(&r));
const r = power_protocol.Reply{ .status = if (allowed) 0 else -1 };
@memcpy(reply[0..@sizeOf(power_protocol.Reply)], std.mem.asBytes(&r));
if (allowed) enterS5();
return @sizeOf(power.Reply);
return @sizeOf(power_protocol.Reply);
},
else => return 0,
}
+3 -3
View File
@@ -8,7 +8,7 @@
const std = @import("std");
const runtime = @import("runtime");
const protocol = @import("device-manager-protocol");
const device_manager_protocol = @import("device-manager-protocol");
pub fn main(init: runtime.process.Init) void {
const argument = init.arguments.get(1) orelse return; // bare: stay silent
@@ -29,8 +29,8 @@ pub fn main(init: runtime.process.Init) void {
if (manager == null) runtime.system.sleep(20);
}
const h = manager orelse return;
const hello = protocol.Hello{ .role = @intFromEnum(protocol.Role.device), .device_id = assigned };
var reply: [protocol.message_maximum]u8 = undefined;
const hello = device_manager_protocol.Hello{ .role = @intFromEnum(device_manager_protocol.Role.device), .device_id = assigned };
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(h, std.mem.asBytes(&hello), &reply) catch return;
_ = runtime.system.write("crash-test: faulting now\n");
+17 -17
View File
@@ -6,7 +6,7 @@
const std = @import("std");
const runtime = @import("runtime");
const protocol = @import("device-manager-protocol");
const device_manager_protocol = @import("device-manager-protocol");
fn writeLine(comptime fmt: []const u8, arguments: anytype) void {
var line: [96]u8 = undefined;
@@ -27,26 +27,26 @@ pub fn main() void {
// The snapshot — polled briefly, because at boot the bus drivers may still
// be scanning: an empty first answer usually just means "too early".
var reply: [protocol.message_maximum]u8 = undefined;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
var count: u32 = 0;
var length: usize = 0;
tries = 0;
while (tries < 20) : (tries += 1) {
const request = protocol.Enumerate{};
const request = device_manager_protocol.Enumerate{};
length = runtime.ipc.call(h, std.mem.asBytes(&request), &reply) catch 0;
if (length >= @sizeOf(protocol.EnumerateReply)) {
count = std.mem.bytesToValue(protocol.EnumerateReply, reply[0..@sizeOf(protocol.EnumerateReply)]).count;
if (length >= @sizeOf(device_manager_protocol.EnumerateReply)) {
count = std.mem.bytesToValue(device_manager_protocol.EnumerateReply, reply[0..@sizeOf(device_manager_protocol.EnumerateReply)]).count;
if (count != 0) break;
}
runtime.system.sleep(100);
}
writeLine("device-list: {d} devices\n", .{count});
var offset: usize = @sizeOf(protocol.EnumerateReply);
var offset: usize = @sizeOf(device_manager_protocol.EnumerateReply);
var index: u32 = 0;
while (index < count and offset + @sizeOf(protocol.ChildEntry) <= length) : (index += 1) {
const entry = std.mem.bytesToValue(protocol.ChildEntry, reply[offset..][0..@sizeOf(protocol.ChildEntry)]);
while (index < count and offset + @sizeOf(device_manager_protocol.ChildEntry) <= length) : (index += 1) {
const entry = std.mem.bytesToValue(device_manager_protocol.ChildEntry, reply[offset..][0..@sizeOf(device_manager_protocol.ChildEntry)]);
writeLine("device-list: device {d} port {d} identity {d}\n", .{ entry.parent, entry.bus_address, entry.identity });
offset += @sizeOf(protocol.ChildEntry);
offset += @sizeOf(device_manager_protocol.ChildEntry);
}
// The subscription: our endpoint rides as the call's capability; events
@@ -55,26 +55,26 @@ pub fn main() void {
_ = runtime.system.write("device-list: no endpoint\n");
return;
};
const subscribe = protocol.Subscribe{};
const subscribe = device_manager_protocol.Subscribe{};
_ = runtime.ipc.callCap(h, std.mem.asBytes(&subscribe), &reply, endpoint) catch {
_ = runtime.system.write("device-list: subscribe failed\n");
return;
};
_ = runtime.system.write("device-list: subscribed\n");
var receive: [protocol.message_maximum]u8 = undefined;
var receive: [device_manager_protocol.message_maximum]u8 = undefined;
while (true) {
const got = runtime.ipc.replyWait(endpoint, &.{}, &receive, null);
if (!got.isMessage() or got.len < 1) continue;
switch (receive[0]) {
@intFromEnum(protocol.Operation.child_added) => {
if (got.len < protocol.child_added_size) continue;
const event = std.mem.bytesToValue(protocol.ChildAdded, receive[0..protocol.child_added_size]);
@intFromEnum(device_manager_protocol.Operation.child_added) => {
if (got.len < device_manager_protocol.child_added_size) continue;
const event = std.mem.bytesToValue(device_manager_protocol.ChildAdded, receive[0..device_manager_protocol.child_added_size]);
writeLine("device-list: added (device {d} port {d})\n", .{ event.parent, event.bus_address });
},
@intFromEnum(protocol.Operation.child_removed) => {
if (got.len < protocol.child_removed_size) continue;
const event = std.mem.bytesToValue(protocol.ChildRemoved, receive[0..protocol.child_removed_size]);
@intFromEnum(device_manager_protocol.Operation.child_removed) => {
if (got.len < device_manager_protocol.child_removed_size) continue;
const event = std.mem.bytesToValue(device_manager_protocol.ChildRemoved, receive[0..device_manager_protocol.child_removed_size]);
writeLine("device-list: removed (device {d} port {d})\n", .{ event.parent, event.bus_address });
},
else => {},
@@ -20,7 +20,7 @@ const runtime = @import("runtime");
const acpi_ids = @import("acpi-ids");
const pci_class = @import("pci-class");
const usb_ids = @import("usb-ids");
const protocol = @import("device-manager-protocol");
const device_manager_protocol = @import("device-manager-protocol");
const device = runtime.device;
const system = runtime.system;
@@ -134,8 +134,8 @@ const Driver = struct {
used: bool = false,
name_buffer: [64]u8 = undefined, // fits a full binary path (abi.maximum_process_name)
name_len: usize = 0,
// The assigned device id (becomes argv[1]), or protocol.no_device.
device_id: u64 = protocol.no_device,
// The assigned device id (becomes argv[1]), or device_manager_protocol.no_device.
device_id: u64 = device_manager_protocol.no_device,
// Whether this driver speaks the protocol (hello expected, deadline
// enforced). Legacy drivers (e.g. ps2-bus) are supervised and restarted
// but not yet required to hello.
@@ -189,7 +189,7 @@ const Child = struct {
parent: u64 = 0,
bus_address: u64 = 0,
identity: u64 = 0,
// The kernel device id (registered by the reporter), or protocol.no_device.
// The kernel device id (registered by the reporter), or device_manager_protocol.no_device.
device_id: u64 = 0,
reporter: u32 = 0, // the reporting driver instance's process id
};
@@ -225,7 +225,7 @@ fn pruneChildrenOf(reporter: u32) void {
if (child.used and child.reporter == reporter) {
std.log.info("child removed (device {d} port {d})", .{ child.parent, child.bus_address });
child.used = false;
const event = protocol.ChildRemoved{ .parent = child.parent, .bus_address = child.bus_address };
const event = device_manager_protocol.ChildRemoved{ .parent = child.parent, .bus_address = child.bus_address };
publishEvent(std.mem.asBytes(&event));
}
}
@@ -280,7 +280,7 @@ fn spawnDriver(driver: *Driver) void {
var id_text: [20]u8 = undefined;
var arguments: [1][]const u8 = undefined;
var argument_count: usize = 0;
if (driver.device_id != protocol.no_device) {
if (driver.device_id != device_manager_protocol.no_device) {
arguments[0] = std.fmt.bufPrint(&id_text, "{d}", .{driver.device_id}) catch return;
argument_count = 1;
}
@@ -298,7 +298,7 @@ fn spawnDriver(driver: *Driver) void {
} else {
driver.state = .running;
}
if (driver.device_id != protocol.no_device) {
if (driver.device_id != device_manager_protocol.no_device) {
std.log.info("spawned {s} for device {d}", .{ driver.name(), driver.device_id });
} else {
std.log.info("spawned {s}", .{driver.name()});
@@ -390,7 +390,7 @@ fn initialise(endpoint: runtime.ipc.Handle) bool {
// under the neutral name "discovery", spawned once at startup. It finds and
// claims the acpi-tables (or devicetree-blob) node itself. Not a per-device
// match — it is the discoverer, not a driver bound to one device.
addDriver("discovery", protocol.no_device, false);
addDriver("discovery", device_manager_protocol.no_device, false);
if (test_restart_mode) {
// The driver-restart scenario's fixture: claims device 0 (the tree
@@ -410,18 +410,18 @@ fn initialise(endpoint: runtime.ipc.Handle) bool {
fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime.ipc.Handle) usize {
if (message.len < 1) return 0;
switch (message[0]) {
@intFromEnum(protocol.Operation.child_added) => return onChildAdded(message, reply, sender),
@intFromEnum(protocol.Operation.child_removed) => return onChildRemoved(message, reply, sender),
@intFromEnum(protocol.Operation.enumerate) => return onEnumerate(reply),
@intFromEnum(protocol.Operation.subscribe) => return onSubscribe(reply, capability),
@intFromEnum(protocol.Operation.hello) => {},
@intFromEnum(device_manager_protocol.Operation.child_added) => return onChildAdded(message, reply, sender),
@intFromEnum(device_manager_protocol.Operation.child_removed) => return onChildRemoved(message, reply, sender),
@intFromEnum(device_manager_protocol.Operation.enumerate) => return onEnumerate(reply),
@intFromEnum(device_manager_protocol.Operation.subscribe) => return onSubscribe(reply, capability),
@intFromEnum(device_manager_protocol.Operation.hello) => {},
else => return 0,
}
if (message.len < protocol.hello_size) return 0;
const hello = std.mem.bytesToValue(protocol.Hello, message[0..protocol.hello_size]);
if (message.len < device_manager_protocol.hello_size) return 0;
const hello = std.mem.bytesToValue(device_manager_protocol.Hello, message[0..device_manager_protocol.hello_size]);
var status: i32 = 0;
if (hello.version != protocol.version) {
if (hello.version != device_manager_protocol.version) {
status = -1;
std.log.info("refused hello (version {d}) from process {d}", .{ hello.version, sender });
} else if (driverByProcess(sender)) |driver| {
@@ -439,26 +439,26 @@ fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime
status = -1;
std.log.info("hello from unknown process {d}", .{sender});
}
const hello_reply = protocol.HelloReply{ .status = status };
@memcpy(reply[0..protocol.reply_size], std.mem.asBytes(&hello_reply));
return protocol.reply_size;
const hello_reply = device_manager_protocol.HelloReply{ .status = status };
@memcpy(reply[0..device_manager_protocol.reply_size], std.mem.asBytes(&hello_reply));
return device_manager_protocol.reply_size;
}
/// A bus driver reported a discovered device: mirror it, and in
/// test-usb-restart mode kill the reporter once after its second child — the
/// deterministic trigger for prune -> backoff -> respawn -> re-report.
fn onChildAdded(message: []const u8, reply: []u8, sender: u32) usize {
if (message.len < protocol.child_added_size) return 0;
const report = std.mem.bytesToValue(protocol.ChildAdded, message[0..protocol.child_added_size]);
if (message.len < device_manager_protocol.child_added_size) return 0;
const report = std.mem.bytesToValue(device_manager_protocol.ChildAdded, message[0..device_manager_protocol.child_added_size]);
var status: i32 = 0;
if (driverByProcess(sender)) |driver| {
if (!addChild(report.parent, report.bus_address, report.identity, report.device_id, sender)) status = -1;
std.log.info("child added (device {d} port {d}, identity {d}) by {s}", .{ report.parent, report.bus_address, report.identity, driver.name() });
if (status == 0) publishEvent(message[0..protocol.child_added_size]);
if (status == 0) publishEvent(message[0..device_manager_protocol.child_added_size]);
// Matching from reports (M19.3): a registered child whose identity
// names a driver gets one, once — re-reports after a bus restart
// dedupe on the registered id, exactly like the registrations do.
if (status == 0 and report.device_id != protocol.no_device) {
if (status == 0 and report.device_id != device_manager_protocol.no_device) {
if (pciDriverForIdentity(report.identity)) |child_driver| {
if (!driverForDevice(report.device_id)) addDriver(child_driver, report.device_id, true);
}
@@ -472,15 +472,15 @@ fn onChildAdded(message: []const u8, reply: []u8, sender: u32) usize {
const hid_len = std.mem.indexOfScalar(u8, &report.hid, 0) orelse report.hid.len;
if (hid_len != 0) {
if (hidDriverFor(report.hid[0..hid_len])) |hid_driver| {
if (!alreadySupervised(hid_driver)) addDriver(hid_driver, protocol.no_device, false);
if (!alreadySupervised(hid_driver)) addDriver(hid_driver, device_manager_protocol.no_device, false);
}
}
}
} else {
status = -1;
}
const report_reply = protocol.ReportReply{ .status = status };
@memcpy(reply[0..@sizeOf(protocol.ReportReply)], std.mem.asBytes(&report_reply));
const report_reply = device_manager_protocol.ReportReply{ .status = status };
@memcpy(reply[0..@sizeOf(device_manager_protocol.ReportReply)], std.mem.asBytes(&report_reply));
if (test_pci_restart_mode and !test_usb_killed) {
if (driverByProcess(sender)) |driver| {
if (std.mem.eql(u8, driver.name(), "pci-bus") and childCountOf(sender) >= 3) {
@@ -508,14 +508,14 @@ fn onChildAdded(message: []const u8, reply: []u8, sender: u32) usize {
}
}
}
return @sizeOf(protocol.ReportReply);
return @sizeOf(device_manager_protocol.ReportReply);
}
/// A bus driver reported a device gone (hot-unplug; no sender exists yet, but
/// the handler is protocol-complete — death-pruning covers removal until then).
fn onChildRemoved(message: []const u8, reply: []u8, sender: u32) usize {
if (message.len < protocol.child_removed_size) return 0;
const report = std.mem.bytesToValue(protocol.ChildRemoved, message[0..protocol.child_removed_size]);
if (message.len < device_manager_protocol.child_removed_size) return 0;
const report = std.mem.bytesToValue(device_manager_protocol.ChildRemoved, message[0..device_manager_protocol.child_removed_size]);
var status: i32 = -1;
for (&children) |*child| {
if (child.used and child.parent == report.parent and child.bus_address == report.bus_address and child.reporter == sender) {
@@ -524,25 +524,25 @@ fn onChildRemoved(message: []const u8, reply: []u8, sender: u32) usize {
status = 0;
}
}
const report_reply = protocol.ReportReply{ .status = status };
@memcpy(reply[0..@sizeOf(protocol.ReportReply)], std.mem.asBytes(&report_reply));
return @sizeOf(protocol.ReportReply);
const report_reply = device_manager_protocol.ReportReply{ .status = status };
@memcpy(reply[0..@sizeOf(device_manager_protocol.ReportReply)], std.mem.asBytes(&report_reply));
return @sizeOf(device_manager_protocol.ReportReply);
}
/// An application asked for the tree: the mirror, as a header plus entries.
fn onEnumerate(reply: []u8) usize {
var count: u32 = 0;
var offset: usize = @sizeOf(protocol.EnumerateReply);
var offset: usize = @sizeOf(device_manager_protocol.EnumerateReply);
for (&children) |*child| {
if (!child.used) continue;
if (offset + @sizeOf(protocol.ChildEntry) > reply.len) break;
const entry = protocol.ChildEntry{ .parent = child.parent, .bus_address = child.bus_address, .identity = child.identity };
@memcpy(reply[offset..][0..@sizeOf(protocol.ChildEntry)], std.mem.asBytes(&entry));
offset += @sizeOf(protocol.ChildEntry);
if (offset + @sizeOf(device_manager_protocol.ChildEntry) > reply.len) break;
const entry = device_manager_protocol.ChildEntry{ .parent = child.parent, .bus_address = child.bus_address, .identity = child.identity };
@memcpy(reply[offset..][0..@sizeOf(device_manager_protocol.ChildEntry)], std.mem.asBytes(&entry));
offset += @sizeOf(device_manager_protocol.ChildEntry);
count += 1;
}
const header = protocol.EnumerateReply{ .status = 0, .count = count };
@memcpy(reply[0..@sizeOf(protocol.EnumerateReply)], std.mem.asBytes(&header));
const header = device_manager_protocol.EnumerateReply{ .status = 0, .count = count };
@memcpy(reply[0..@sizeOf(device_manager_protocol.EnumerateReply)], std.mem.asBytes(&header));
return offset;
}
@@ -558,9 +558,9 @@ fn onSubscribe(reply: []u8, capability: ?runtime.ipc.Handle) usize {
}
}
}
const report_reply = protocol.ReportReply{ .status = status };
@memcpy(reply[0..@sizeOf(protocol.ReportReply)], std.mem.asBytes(&report_reply));
return @sizeOf(protocol.ReportReply);
const report_reply = device_manager_protocol.ReportReply{ .status = status };
@memcpy(reply[0..@sizeOf(device_manager_protocol.ReportReply)], std.mem.asBytes(&report_reply));
return @sizeOf(device_manager_protocol.ReportReply);
}
fn onNotification(badge: u64) void {
@@ -579,7 +579,7 @@ pub fn main(init: runtime.process.Init) void {
test_pci_restart_mode = std.mem.eql(u8, mode, "test-pci-restart");
test_scanout_restart_mode = std.mem.eql(u8, mode, "test-scanout-restart");
}
runtime.service.run(protocol.message_maximum, .{
runtime.service.run(device_manager_protocol.message_maximum, .{
.service = .device_manager,
.init = initialise,
.on_message = onMessage,
+24 -24
View File
@@ -20,7 +20,7 @@ const runtime = @import("runtime");
const compositor = @import("compositor.zig");
const backend_mod = @import("backend.zig");
const protocol = @import("display-protocol");
const display_protocol = @import("display-protocol");
const ipc = runtime.ipc;
const system = runtime.system;
const input = runtime.input;
@@ -326,7 +326,7 @@ fn attachScanout(stride: u32, width: u32, height: u32, format: u32, refresh_hz:
.refresh_hz = refresh_hz,
.scanout = scanout,
} };
background = protocol.pack(format, 0x20, 0x30, 0x48); // re-pack the wallpaper for the mode
background = display_protocol.pack(format, 0x20, 0x30, 0x48); // re-pack the wallpaper for the mode
updateFrameClock(); // the GOP floor's clock dies here — pace by the GPU's EDID now
addDamage(screenRect()); // the whole new surface must be painted
pending_native_verify = true;
@@ -389,8 +389,8 @@ fn modesetSelfCheck() void {
/// backend surface — and reads the composited result back. Cleans up after itself.
fn selfCheck() void {
const format = backend.info().format;
const red = protocol.pack(format, 0xC0, 0x20, 0x20);
const green = protocol.pack(format, 0x20, 0xC0, 0x20);
const red = display_protocol.pack(format, 0xC0, 0x20, 0x20);
const green = display_protocol.pack(format, 0x20, 0xC0, 0x20);
const bottom = createLayer(100, 100, 80, 80, 0, true) orelse return fail_check("create");
const top = createLayer(140, 140, 80, 80, 1, true) orelse return fail_check("create");
_ = fillLayer(bottom, Rect.init(0, 0, 80, 80), red);
@@ -559,7 +559,7 @@ fn startCursorTracking() void {
return;
};
cursor_layer = id;
_ = fillLayer(id, Rect.init(0, 0, cursor_size, cursor_size), protocol.pack(mode.format, 0xF0, 0xF0, 0xF0));
_ = fillLayer(id, Rect.init(0, 0, cursor_size, cursor_size), display_protocol.pack(mode.format, 0xF0, 0xF0, 0xF0));
present(); // show the cursor at its start position
_ = Thread.spawn(.{}, mouseListener, .{ mode.width, mode.height }) catch {
@@ -575,7 +575,7 @@ fn initialise(endpoint: ipc.Handle) bool {
// Pick the scanout backend (GOP today). It logs the reason on failure.
backend = backend_mod.select() orelse return false;
const mode = backend.info();
background = protocol.pack(mode.format, 0x20, 0x30, 0x48); // a dark slate wallpaper
background = display_protocol.pack(mode.format, 0x20, 0x30, 0x48); // a dark slate wallpaper
// Clear the whole screen through the compose surface → present path (double buffering:
// no direct-to-scanout drawing).
@@ -596,7 +596,7 @@ fn initialise(endpoint: ipc.Handle) bool {
return true;
}
fn writeReply(reply: []u8, value: protocol.Reply) usize {
fn writeReply(reply: []u8, value: display_protocol.Reply) usize {
const bytes = std.mem.asBytes(&value);
@memcpy(reply[0..bytes.len], bytes);
return bytes.len;
@@ -612,61 +612,61 @@ fn fail(reply: []u8) usize {
fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?ipc.Handle) usize {
_ = sender;
if (message.len < protocol.request_size) return fail(reply);
const request = std.mem.bytesToValue(protocol.Request, message[0..protocol.request_size]);
const payload = message[protocol.request_size..];
if (message.len < display_protocol.request_size) return fail(reply);
const request = std.mem.bytesToValue(display_protocol.Request, message[0..display_protocol.request_size]);
const payload = message[display_protocol.request_size..];
// Switch on the raw operation value — an out-of-range one must fail cleanly, not
// panic an `@enumFromInt`.
switch (request.operation) {
@intFromEnum(protocol.Operation.info) => {
@intFromEnum(display_protocol.Operation.info) => {
const m = backend.info();
return writeReply(reply, .{ .status = 0, .width = m.width, .height = m.height, .pitch = m.pitch, .format = m.format });
},
@intFromEnum(protocol.Operation.create_layer) => {
@intFromEnum(display_protocol.Operation.create_layer) => {
// x/y are signed coordinates carried in the u32 wire fields — reinterpret the
// bits (@bitCast), don't range-check (@intCast) which a negative would fail.
const slot = createLayer(@bitCast(request.x), @bitCast(request.y), request.width, request.height, request.z, request.visible != 0) orelse return fail(reply);
return writeReply(reply, .{ .status = 0, .layer = slot });
},
@intFromEnum(protocol.Operation.configure_layer) => {
@intFromEnum(display_protocol.Operation.configure_layer) => {
return if (configureLayer(request.layer, @bitCast(request.x), @bitCast(request.y), request.z, request.visible != 0)) ok(reply) else fail(reply);
},
@intFromEnum(protocol.Operation.destroy_layer) => {
@intFromEnum(display_protocol.Operation.destroy_layer) => {
return if (destroyLayer(request.layer)) ok(reply) else fail(reply);
},
@intFromEnum(protocol.Operation.fill_rect) => {
@intFromEnum(display_protocol.Operation.fill_rect) => {
const local = Rect.init(@bitCast(request.x), @bitCast(request.y), @intCast(request.width), @intCast(request.height));
return if (fillLayer(request.layer, local, request.colour)) ok(reply) else fail(reply);
},
@intFromEnum(protocol.Operation.blit_tile) => {
@intFromEnum(display_protocol.Operation.blit_tile) => {
return if (blitLayer(request.layer, @bitCast(request.x), @bitCast(request.y), request.width, request.height, payload)) ok(reply) else fail(reply);
},
@intFromEnum(protocol.Operation.damage) => {
@intFromEnum(display_protocol.Operation.damage) => {
const l = layerAt(request.layer) orelse return fail(reply);
const screen = Rect{ .x = l.x + @as(i32, @bitCast(request.x)), .y = l.y + @as(i32, @bitCast(request.y)), .w = @intCast(request.width), .h = @intCast(request.height) };
addDamage(screen.intersect(layerScreenRect(l)));
return ok(reply);
},
@intFromEnum(protocol.Operation.present) => {
@intFromEnum(display_protocol.Operation.present) => {
// Scheduled, not immediate: the frame clock composites the accumulated damage
// at the next tick, so back-to-back client presents coalesce into one frame.
schedulePresent();
return ok(reply);
},
@intFromEnum(protocol.Operation.attach_scanout) => {
@intFromEnum(display_protocol.Operation.attach_scanout) => {
return attachScanout(request.x, request.width, request.height, request.colour, request.y, capability, reply);
},
@intFromEnum(protocol.Operation.set_mode) => {
@intFromEnum(display_protocol.Operation.set_mode) => {
if (!backend.setMode(request.width, request.height)) return fail(reply);
addDamage(screenRect()); // repaint the whole screen at the new resolution
present();
return ok(reply);
},
@intFromEnum(protocol.Operation.get_modes) => {
@intFromEnum(display_protocol.Operation.get_modes) => {
var list: [4]backend_mod.Mode = undefined;
const count = backend.modes(&list);
var response = protocol.ModesReply{ .status = 0, .count = @intCast(count), .modes = undefined };
for (0..protocol.max_modes) |i| {
var response = display_protocol.ModesReply{ .status = 0, .count = @intCast(count), .modes = undefined };
for (0..display_protocol.max_modes) |i| {
response.modes[i] = if (i < count)
.{ .width = list[i].width, .height = list[i].height }
else
@@ -692,7 +692,7 @@ fn onNotification(badge: u64) void {
}
pub fn main() void {
runtime.service.run(protocol.message_maximum, .{
runtime.service.run(display_protocol.message_maximum, .{
.service = .display,
.init = initialise,
.on_message = onMessage,
+8 -8
View File
@@ -19,7 +19,7 @@
const std = @import("std");
const runtime = @import("runtime");
const power = @import("power-protocol");
const power_protocol = @import("power-protocol");
const build_options = @import("build_options");
/// The system services init brings up at boot, in order, by binary path. This is
@@ -105,7 +105,7 @@ pub fn main() void {
// and the handler below — folds away entirely when serial is off.
if (build_options.serial) _ = runtime.system.timerOnce(supervision_endpoint, 1000);
var receive: [power.message_maximum]u8 = undefined;
var receive: [power_protocol.message_maximum]u8 = undefined;
while (true) {
const got = runtime.ipc.replyWait(supervision_endpoint, &.{}, &receive, null);
if (runtime.process.signalsFrom(got.badge)) |signals| {
@@ -117,9 +117,9 @@ pub fn main() void {
_ = runtime.system.timerOnce(supervision_endpoint, 1000);
continue;
}
if (got.isMessage() and got.len >= 2 and receive[0] == @intFromEnum(power.Operation.event)) {
if (got.isMessage() and got.len >= 2 and receive[0] == @intFromEnum(power_protocol.Operation.event)) {
// A power event (the only buffered messages init receives).
if (receive[1] == @intFromEnum(power.Event.power_button)) shutDown();
if (receive[1] == @intFromEnum(power_protocol.Event.power_button)) shutDown();
continue;
}
if (got.isChildExit()) {
@@ -171,8 +171,8 @@ fn subscribePower() void {
// a `terminate` signal still drives shutdown. Silent so the no-ramdisk init
// test's heartbeat marker is the next line written.
const h = handle orelse return;
const request = power.Subscribe{};
var reply: [power.message_maximum]u8 = undefined;
const request = power_protocol.Subscribe{};
var reply: [power_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.callCap(h, std.mem.asBytes(&request), &reply, supervision_endpoint) catch {};
}
@@ -192,8 +192,8 @@ fn shutDown() void {
if (child_ids[i] != 0) runtime.process.stop(child_ids[i], 2000, supervision_endpoint);
}
if (runtime.ipc.lookup(.power)) |h| {
const request = power.Shutdown{};
var reply: [power.message_maximum]u8 = undefined;
const request = power_protocol.Shutdown{};
var reply: [power_protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(h, std.mem.asBytes(&request), &reply) catch {};
}
// If S5 did not take, init has nothing left to do but idle.