reorg: move the USB client to library/device/usb (drop runtime.usb)
The USB class-driver transfer client was library/runtime/usb.zig, re-exported as runtime.usb — which compiled the USB client and usb-transfer-protocol into every user binary (init, fat, the compositor…), none of which speak USB. It is bus-family logic, not core runtime. Move it to its domain home, library/device/usb/usb.zig (module "usb"), alongside the usb-abi and usb-ids data modules; fix its internal imports to go through the runtime module; and re-export usb.abi / usb.ids so a class driver reaches the whole USB domain through one import. runtime.usb and runtime's usb-transfer-protocol import are removed; the three class drivers (usb-hid keyboard/mouse, usb-storage) import module "usb" directly. zig build + test green; usb-hid, usb-storage pass.
This commit is contained in:
@@ -403,9 +403,6 @@ pub fn build(b: *std.Build) void {
|
|||||||
.root_source_file = b.path("system/services/device-manager/device-manager-protocol.zig"),
|
.root_source_file = b.path("system/services/device-manager/device-manager-protocol.zig"),
|
||||||
});
|
});
|
||||||
runtime_module.addImport("device-manager-protocol", device_manager_protocol_module);
|
runtime_module.addImport("device-manager-protocol", device_manager_protocol_module);
|
||||||
// The USB transfer protocol, so runtime.usb (the class-driver client) can speak
|
|
||||||
// it, the way runtime.input speaks the input protocol.
|
|
||||||
runtime_module.addImport("usb-transfer-protocol", usb_transfer_protocol_module);
|
|
||||||
// The block protocol, so runtime.block (the block-device client) can speak it.
|
// The block protocol, so runtime.block (the block-device client) can speak it.
|
||||||
runtime_module.addImport("block-protocol", block_protocol_module);
|
runtime_module.addImport("block-protocol", block_protocol_module);
|
||||||
|
|
||||||
@@ -449,6 +446,20 @@ pub fn build(b: *std.Build) void {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The USB class-driver transfer client (library/device/usb/usb.zig): open a device on
|
||||||
|
// the xHCI bus and drive it (control / interrupt / bulk). Bus-family logic a class
|
||||||
|
// driver imports directly — no longer funnelled through runtime. Re-exports usb-abi /
|
||||||
|
// usb-ids as usb.abi / usb.ids for a single USB import.
|
||||||
|
const usb_module = b.addModule("usb", .{
|
||||||
|
.root_source_file = b.path("library/device/usb/usb.zig"),
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "runtime", .module = runtime_module },
|
||||||
|
.{ .name = "usb-transfer-protocol", .module = usb_transfer_protocol_module },
|
||||||
|
.{ .name = "usb-abi", .module = usb_abi_module },
|
||||||
|
.{ .name = "usb-ids", .module = usb_ids_module },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// Keyboard layouts compiled from the X11 xkeyboard-config database into native Zig
|
// Keyboard layouts compiled from the X11 xkeyboard-config database into native Zig
|
||||||
// (keycode + modifiers -> keysym/character). The `layouts` tables are generated by
|
// (keycode + modifiers -> keysym/character). The `layouts` tables are generated by
|
||||||
// tools/make-xkeyboard-config.py; `xkeyboard-config` is the hand-written API over them.
|
// tools/make-xkeyboard-config.py; `xkeyboard-config` is the hand-written API over them.
|
||||||
@@ -548,12 +559,15 @@ pub fn build(b: *std.Build) void {
|
|||||||
// opens its device through runtime.usb (the transfer protocol) and publishes to
|
// opens its device through runtime.usb (the transfer protocol) and publishes to
|
||||||
// the input service. They build chapter-9 class requests from usb-abi.
|
// the input service. They build chapter-9 class requests from usb-abi.
|
||||||
const usb_hid_keyboard_exe = addUserBinary(b, kernel_target, runtime_module, mmio_module, xkeyboard_config_module, acpi_ids_module, "usb-hid-keyboard", "system/drivers/usb-hid/keyboard.zig");
|
const usb_hid_keyboard_exe = addUserBinary(b, kernel_target, runtime_module, mmio_module, xkeyboard_config_module, acpi_ids_module, "usb-hid-keyboard", "system/drivers/usb-hid/keyboard.zig");
|
||||||
|
programModule(usb_hid_keyboard_exe).addImport("usb", usb_module);
|
||||||
programModule(usb_hid_keyboard_exe).addImport("usb-abi", usb_abi_module);
|
programModule(usb_hid_keyboard_exe).addImport("usb-abi", usb_abi_module);
|
||||||
const usb_hid_mouse_exe = addUserBinary(b, kernel_target, runtime_module, mmio_module, xkeyboard_config_module, acpi_ids_module, "usb-hid-mouse", "system/drivers/usb-hid/mouse.zig");
|
const usb_hid_mouse_exe = addUserBinary(b, kernel_target, runtime_module, mmio_module, xkeyboard_config_module, acpi_ids_module, "usb-hid-mouse", "system/drivers/usb-hid/mouse.zig");
|
||||||
|
programModule(usb_hid_mouse_exe).addImport("usb", usb_module);
|
||||||
programModule(usb_hid_mouse_exe).addImport("usb-abi", usb_abi_module);
|
programModule(usb_hid_mouse_exe).addImport("usb-abi", usb_abi_module);
|
||||||
// The USB mass-storage class driver: opens its device via runtime.usb, drives it
|
// The USB mass-storage class driver: opens its device via runtime.usb, drives it
|
||||||
// with Bulk-Only Transport + SCSI, and serves the block protocol under `.block`.
|
// with Bulk-Only Transport + SCSI, and serves the block protocol under `.block`.
|
||||||
const usb_storage_exe = addUserBinary(b, kernel_target, runtime_module, mmio_module, xkeyboard_config_module, acpi_ids_module, "usb-storage", "system/drivers/usb-storage/usb-storage.zig");
|
const usb_storage_exe = addUserBinary(b, kernel_target, runtime_module, mmio_module, xkeyboard_config_module, acpi_ids_module, "usb-storage", "system/drivers/usb-storage/usb-storage.zig");
|
||||||
|
programModule(usb_storage_exe).addImport("usb", usb_module);
|
||||||
programModule(usb_storage_exe).addImport("block-protocol", block_protocol_module);
|
programModule(usb_storage_exe).addImport("block-protocol", block_protocol_module);
|
||||||
// The FAT filesystem server: mounts the block device and serves it into the VFS
|
// The FAT filesystem server: mounts the block device and serves it into the VFS
|
||||||
// at /mnt/usb. Its engine (engine.zig / on-disk.zig) is imported relatively.
|
// at /mnt/usb. Its engine (engine.zig / on-disk.zig) is imported relatively.
|
||||||
|
|||||||
@@ -16,10 +16,16 @@
|
|||||||
//! the service harness drops buffered-message payloads — see service.zig).
|
//! the service harness drops buffered-message payloads — see service.zig).
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ipc = @import("ipc.zig");
|
const runtime = @import("runtime");
|
||||||
const system = @import("system.zig");
|
const ipc = runtime.ipc;
|
||||||
|
const system = runtime.system;
|
||||||
const protocol = @import("usb-transfer-protocol");
|
const 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 Endpoint = protocol.Endpoint;
|
||||||
pub const InterruptReport = protocol.InterruptReport;
|
pub const InterruptReport = protocol.InterruptReport;
|
||||||
pub const max_report_data = protocol.max_report_data;
|
pub const max_report_data = protocol.max_report_data;
|
||||||
@@ -46,9 +46,9 @@ pub const dma = @import("dma.zig");
|
|||||||
/// and docs/display-v2.md.
|
/// and docs/display-v2.md.
|
||||||
pub const shared_memory = @import("shared-memory.zig");
|
pub const shared_memory = @import("shared-memory.zig");
|
||||||
|
|
||||||
/// USB class-driver client: open a device on the xHCI bus and drive it
|
// The USB class-driver client moved to its domain home, library/device/usb (module
|
||||||
/// (control / interrupt / bulk transfers). See library/runtime/usb.zig.
|
// "usb"): it is bus-family logic, not core runtime, and re-exporting it here compiled it
|
||||||
pub const usb = @import("usb.zig");
|
// into every binary. USB class drivers import it directly with @import("usb").
|
||||||
|
|
||||||
/// Block-device client: read/write a block device (a USB stick, via
|
/// Block-device client: read/write a block device (a USB stick, via
|
||||||
/// usb-storage). See library/runtime/block.zig.
|
/// usb-storage). See library/runtime/block.zig.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//! keyboard interface (class 3, subclass 1, protocol 1); its assigned device id
|
//! keyboard interface (class 3, subclass 1, protocol 1); its assigned device id
|
||||||
//! arrives as argv[1] and an optional layout name ("us", "gb", ...) as argv[2].
|
//! arrives as argv[1] and an optional layout name ("us", "gb", ...) as argv[2].
|
||||||
//! It owns no hardware: it opens its device through the USB transfer protocol
|
//! It owns no hardware: it opens its device through the USB transfer protocol
|
||||||
//! (`runtime.usb`), asks the device for the boot protocol, subscribes to its
|
//! (`usb`), asks the device for the boot protocol, subscribes to its
|
||||||
//! interrupt-IN endpoint, and turns each 8-byte boot report into input-protocol
|
//! interrupt-IN endpoint, and turns each 8-byte boot report into input-protocol
|
||||||
//! events, published to the input service — the USB analogue of ps2-bus/keyboard.
|
//! events, published to the input service — the USB analogue of ps2-bus/keyboard.
|
||||||
//!
|
//!
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const runtime = @import("runtime");
|
const runtime = @import("runtime");
|
||||||
|
const usb = @import("usb");
|
||||||
const usb_abi = @import("usb-abi");
|
const usb_abi = @import("usb-abi");
|
||||||
const xkb = @import("xkeyboard-config");
|
const xkb = @import("xkeyboard-config");
|
||||||
const hid = @import("hid-report.zig");
|
const hid = @import("hid-report.zig");
|
||||||
@@ -73,11 +74,11 @@ pub fn main(init: runtime.process.Init) void {
|
|||||||
|
|
||||||
// Hello the manager first (meet the spawn deadline), then open the device.
|
// Hello the manager first (meet the spawn deadline), then open the device.
|
||||||
if (runtime.device_manager.hello(.device, device_id) == null) return;
|
if (runtime.device_manager.hello(.device, device_id) == null) return;
|
||||||
var device = runtime.usb.open(device_id) orelse {
|
var device = usb.open(device_id) orelse {
|
||||||
std.log.info("could not open device {d}", .{device_id});
|
std.log.info("could not open device {d}", .{device_id});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
const endpoint = device.findEndpoint(runtime.usb.transfer_type_interrupt, true) orelse {
|
const endpoint = device.findEndpoint(usb.transfer_type_interrupt, true) orelse {
|
||||||
_ = runtime.system.write("/system/drivers/usb-hid/keyboard: no interrupt-IN endpoint\n");
|
_ = runtime.system.write("/system/drivers/usb-hid/keyboard: no interrupt-IN endpoint\n");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -108,9 +109,9 @@ pub fn main(init: runtime.process.Init) void {
|
|||||||
if (signals.has(.terminate)) return;
|
if (signals.has(.terminate)) return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!got.isMessage() or got.len < @sizeOf(runtime.usb.InterruptReport)) continue;
|
if (!got.isMessage() or got.len < @sizeOf(usb.InterruptReport)) continue;
|
||||||
|
|
||||||
const message = std.mem.bytesToValue(runtime.usb.InterruptReport, receive[0..@sizeOf(runtime.usb.InterruptReport)]);
|
const message = std.mem.bytesToValue(usb.InterruptReport, receive[0..@sizeOf(usb.InterruptReport)]);
|
||||||
if (message.length < @sizeOf(hid.KeyboardReport)) continue;
|
if (message.length < @sizeOf(hid.KeyboardReport)) continue;
|
||||||
const report = std.mem.bytesToValue(hid.KeyboardReport, message.data[0..@sizeOf(hid.KeyboardReport)]);
|
const report = std.mem.bytesToValue(hid.KeyboardReport, message.data[0..@sizeOf(hid.KeyboardReport)]);
|
||||||
const transitions = decoder.feed(report);
|
const transitions = decoder.feed(report);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! Spawned by the device manager when the xHCI bus driver reports a HID / boot /
|
//! Spawned by the device manager when the xHCI bus driver reports a HID / boot /
|
||||||
//! mouse interface (class 3, subclass 1, protocol 2); its assigned device id
|
//! mouse interface (class 3, subclass 1, protocol 2); its assigned device id
|
||||||
//! arrives as argv[1]. Like the keyboard driver it owns no hardware: it opens its
|
//! arrives as argv[1]. Like the keyboard driver it owns no hardware: it opens its
|
||||||
//! device through the USB transfer protocol (`runtime.usb`), asks for the boot
|
//! device through the USB transfer protocol (`usb`), asks for the boot
|
||||||
//! protocol, subscribes to its interrupt-IN endpoint, and turns each 3- or 4-byte
|
//! protocol, subscribes to its interrupt-IN endpoint, and turns each 3- or 4-byte
|
||||||
//! boot report into input-protocol mouse events published to the input service.
|
//! boot report into input-protocol mouse events published to the input service.
|
||||||
//!
|
//!
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const runtime = @import("runtime");
|
const runtime = @import("runtime");
|
||||||
|
const usb = @import("usb");
|
||||||
const usb_abi = @import("usb-abi");
|
const usb_abi = @import("usb-abi");
|
||||||
const hid = @import("hid-report.zig");
|
const hid = @import("hid-report.zig");
|
||||||
const ipc = runtime.ipc;
|
const ipc = runtime.ipc;
|
||||||
@@ -38,11 +39,11 @@ pub fn main(init: runtime.process.Init) void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (runtime.device_manager.hello(.device, device_id) == null) return;
|
if (runtime.device_manager.hello(.device, device_id) == null) return;
|
||||||
var device = runtime.usb.open(device_id) orelse {
|
var device = usb.open(device_id) orelse {
|
||||||
std.log.info("could not open device {d}", .{device_id});
|
std.log.info("could not open device {d}", .{device_id});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
const endpoint = device.findEndpoint(runtime.usb.transfer_type_interrupt, true) orelse {
|
const endpoint = device.findEndpoint(usb.transfer_type_interrupt, true) orelse {
|
||||||
_ = runtime.system.write("/system/drivers/usb-hid/mouse: no interrupt-IN endpoint\n");
|
_ = runtime.system.write("/system/drivers/usb-hid/mouse: no interrupt-IN endpoint\n");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -70,9 +71,9 @@ pub fn main(init: runtime.process.Init) void {
|
|||||||
if (signals.has(.terminate)) return;
|
if (signals.has(.terminate)) return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!got.isMessage() or got.len < @sizeOf(runtime.usb.InterruptReport)) continue;
|
if (!got.isMessage() or got.len < @sizeOf(usb.InterruptReport)) continue;
|
||||||
|
|
||||||
const message = std.mem.bytesToValue(runtime.usb.InterruptReport, receive[0..@sizeOf(runtime.usb.InterruptReport)]);
|
const message = std.mem.bytesToValue(usb.InterruptReport, receive[0..@sizeOf(usb.InterruptReport)]);
|
||||||
const length = @min(message.length, message.data.len);
|
const length = @min(message.length, message.data.len);
|
||||||
const report = hid.parseMouse(message.data[0..length]) orelse continue;
|
const report = hid.parseMouse(message.data[0..length]) orelse continue;
|
||||||
const mask = buttonMask(report.buttons);
|
const mask = buttonMask(report.buttons);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//! Spawned by the device manager when the xHCI bus driver reports a mass-storage
|
//! Spawned by the device manager when the xHCI bus driver reports a mass-storage
|
||||||
//! / SCSI / bulk-only interface (class 8, subclass 6, protocol 0x50); its device
|
//! / SCSI / bulk-only interface (class 8, subclass 6, protocol 0x50); its device
|
||||||
//! id arrives as argv[1]. It owns no hardware: it opens its device through the
|
//! id arrives as argv[1]. It owns no hardware: it opens its device through the
|
||||||
//! USB transfer protocol (`runtime.usb`), then drives it with the BOT command
|
//! USB transfer protocol (`usb`), then drives it with the BOT command
|
||||||
//! cycle — CBW out, an optional data stage, CSW in — carrying SCSI commands
|
//! cycle — CBW out, an optional data stage, CSW in — carrying SCSI commands
|
||||||
//! (READ CAPACITY, READ(10), WRITE(10)). Upward it is a block device: it serves
|
//! (READ CAPACITY, READ(10), WRITE(10)). Upward it is a block device: it serves
|
||||||
//! the block protocol under `.block`, the storage a FAT filesystem sits on.
|
//! the block protocol under `.block`, the storage a FAT filesystem sits on.
|
||||||
@@ -13,15 +13,16 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const runtime = @import("runtime");
|
const runtime = @import("runtime");
|
||||||
|
const usb = @import("usb");
|
||||||
const scsi = @import("scsi.zig");
|
const scsi = @import("scsi.zig");
|
||||||
const bot = @import("bulk-only-transport.zig");
|
const bot = @import("bulk-only-transport.zig");
|
||||||
const block_protocol = @import("block-protocol");
|
const block_protocol = @import("block-protocol");
|
||||||
const dma = runtime.dma;
|
const dma = runtime.dma;
|
||||||
|
|
||||||
var device_id: u64 = 0;
|
var device_id: u64 = 0;
|
||||||
var device: runtime.usb.Device = undefined;
|
var device: usb.Device = undefined;
|
||||||
var bulk_in: runtime.usb.Endpoint = undefined;
|
var bulk_in: usb.Endpoint = undefined;
|
||||||
var bulk_out: runtime.usb.Endpoint = undefined;
|
var bulk_out: usb.Endpoint = undefined;
|
||||||
|
|
||||||
// DMA buffers for the transport: the 31-byte CBW, the 13-byte CSW, and a page
|
// DMA buffers for the transport: the 31-byte CBW, the 13-byte CSW, and a page
|
||||||
// for the small command data (INQUIRY / READ CAPACITY / the self-check sector).
|
// for the small command data (INQUIRY / READ CAPACITY / the self-check sector).
|
||||||
@@ -70,16 +71,16 @@ var bring_up_failed = false;
|
|||||||
fn initialise(endpoint: runtime.ipc.Handle) bool {
|
fn initialise(endpoint: runtime.ipc.Handle) bool {
|
||||||
_ = endpoint;
|
_ = endpoint;
|
||||||
if (runtime.device_manager.hello(.device, device_id) == null) return false;
|
if (runtime.device_manager.hello(.device, device_id) == null) return false;
|
||||||
device = runtime.usb.open(device_id) orelse {
|
device = usb.open(device_id) orelse {
|
||||||
std.log.info("could not open device {d}", .{device_id});
|
std.log.info("could not open device {d}", .{device_id});
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
bulk_in = device.findEndpoint(runtime.usb.transfer_type_bulk, true) orelse {
|
bulk_in = device.findEndpoint(usb.transfer_type_bulk, true) orelse {
|
||||||
_ = runtime.system.write("/system/drivers/usb-storage: no bulk-IN endpoint\n");
|
_ = runtime.system.write("/system/drivers/usb-storage: no bulk-IN endpoint\n");
|
||||||
bring_up_failed = true;
|
bring_up_failed = true;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
bulk_out = device.findEndpoint(runtime.usb.transfer_type_bulk, false) orelse {
|
bulk_out = device.findEndpoint(usb.transfer_type_bulk, false) orelse {
|
||||||
_ = runtime.system.write("/system/drivers/usb-storage: no bulk-OUT endpoint\n");
|
_ = runtime.system.write("/system/drivers/usb-storage: no bulk-OUT endpoint\n");
|
||||||
bring_up_failed = true;
|
bring_up_failed = true;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user