usb-ids: className/interfaceName helpers; readable device classes in the bus log
The logs read 'class 9/0/0' where they could say 'Hub'. usb-ids gains className (a device/interface class byte -> 'Hub', 'HID', 'Mass Storage', ...) and interfaceName (a HID boot interface -> 'HID boot keyboard' / 'HID boot mouse'), both host-tested with usb-ids. The bus driver's enumerate + register lines now read, e.g.: port 21 device: Hub vendor 0x05e3 product 0x0626, 1 interface(s) port 21 interface 0: Hub (9/0/0) registered as device 47 port 5 interface 0: HID boot keyboard (3/1/1) registered as device 32 so a real-hardware log is scannable by eye. Full USB case set green (hub regexes follow the new 'device: <name>' format).
This commit is contained in:
@@ -70,6 +70,53 @@ pub const Class = enum(u8) {
|
|||||||
_,
|
_,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A human-readable name for a device/interface class code, for logs. Unknown
|
||||||
|
/// codes fall through to "class 0xNN".
|
||||||
|
pub fn className(class: u8) []const u8 {
|
||||||
|
return switch (@as(Class, @enumFromInt(class))) {
|
||||||
|
.per_interface => "per-interface",
|
||||||
|
.audio => "Audio",
|
||||||
|
.communications => "Communications",
|
||||||
|
.hid => "HID",
|
||||||
|
.physical => "Physical",
|
||||||
|
.image => "Image",
|
||||||
|
.printer => "Printer",
|
||||||
|
.mass_storage => "Mass Storage",
|
||||||
|
.hub => "Hub",
|
||||||
|
.cdc_data => "CDC Data",
|
||||||
|
.smart_card => "Smart Card",
|
||||||
|
.content_security => "Content Security",
|
||||||
|
.video => "Video",
|
||||||
|
.personal_healthcare => "Personal Healthcare",
|
||||||
|
.audio_video => "Audio/Video",
|
||||||
|
.billboard => "Billboard",
|
||||||
|
.type_c_bridge => "Type-C Bridge",
|
||||||
|
.bulk_display => "Bulk Display",
|
||||||
|
.mctp => "MCTP",
|
||||||
|
.i3c => "I3C",
|
||||||
|
.diagnostic => "Diagnostic",
|
||||||
|
.wireless_controller => "Wireless Controller",
|
||||||
|
.miscellaneous => "Miscellaneous",
|
||||||
|
.application_specific => "Application-specific",
|
||||||
|
.vendor_specific => "Vendor-specific",
|
||||||
|
_ => "Unknown",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A fuller name for a HID interface's (subclass, protocol): "HID boot keyboard"
|
||||||
|
/// / "HID boot mouse", else just the class name. Used to make input devices
|
||||||
|
/// recognizable in logs.
|
||||||
|
pub fn interfaceName(class: u8, subclass: u8, protocol: u8) []const u8 {
|
||||||
|
if (@as(Class, @enumFromInt(class)) == .hid and subclass == @intFromEnum(hid.SubClass.boot)) {
|
||||||
|
return switch (@as(hid.Protocol, @enumFromInt(protocol))) {
|
||||||
|
.keyboard => "HID boot keyboard",
|
||||||
|
.mouse => "HID boot mouse",
|
||||||
|
else => "HID",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return className(class);
|
||||||
|
}
|
||||||
|
|
||||||
// Subclass and protocol codes qualified by Class.hub. Hubs have no subclass codes; the
|
// Subclass and protocol codes qualified by Class.hub. Hubs have no subclass codes; the
|
||||||
// protocol distinguishes the hub's transaction-translator arrangement.
|
// protocol distinguishes the hub's transaction-translator arrangement.
|
||||||
pub const hub = struct {
|
pub const hub = struct {
|
||||||
|
|||||||
@@ -230,8 +230,9 @@ fn bringUpPort(manager: runtime.ipc.Handle, engine: *library.Controller, port: u
|
|||||||
std.log.info("port {d} enumeration failed", .{port});
|
std.log.info("port {d} enumeration failed", .{port});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std.log.info("port {d} device vendor 0x{x:0>4} product 0x{x:0>4}, {d} interface(s)", .{
|
std.log.info("port {d} device: {s} vendor 0x{x:0>4} product 0x{x:0>4}, {d} interface(s)", .{
|
||||||
port,
|
port,
|
||||||
|
usb_ids.className(usb_device.device_descriptor.device_class),
|
||||||
usb_device.device_descriptor.vendor_id,
|
usb_device.device_descriptor.vendor_id,
|
||||||
usb_device.device_descriptor.product_id,
|
usb_device.device_descriptor.product_id,
|
||||||
usb_device.interface_count,
|
usb_device.interface_count,
|
||||||
@@ -279,8 +280,9 @@ fn bringUpBehindHub(manager: runtime.ipc.Handle, engine: *library.Controller, hu
|
|||||||
std.log.info("hub slot {d} port {d}: enumeration failed", .{ hub.slot_id, port });
|
std.log.info("hub slot {d} port {d}: enumeration failed", .{ hub.slot_id, port });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std.log.info("hub slot {d} port {d} device vendor 0x{x:0>4} product 0x{x:0>4}, {d} interface(s)", .{
|
std.log.info("hub slot {d} port {d} device: {s} vendor 0x{x:0>4} product 0x{x:0>4}, {d} interface(s)", .{
|
||||||
hub.slot_id, port,
|
hub.slot_id, port,
|
||||||
|
usb_ids.className(usb_device.device_descriptor.device_class),
|
||||||
usb_device.device_descriptor.vendor_id,
|
usb_device.device_descriptor.vendor_id,
|
||||||
usb_device.device_descriptor.product_id,
|
usb_device.device_descriptor.product_id,
|
||||||
usb_device.interface_count,
|
usb_device.interface_count,
|
||||||
@@ -387,9 +389,10 @@ fn reportInterface(manager: runtime.ipc.Handle, port: u32, interface: library.In
|
|||||||
std.log.info("child report for port {d} interface {d} failed", .{ port, interface.number });
|
std.log.info("child report for port {d} interface {d} failed", .{ port, interface.number });
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
std.log.info("port {d} interface {d} class {d}/{d}/{d} registered as device {d}", .{
|
std.log.info("port {d} interface {d}: {s} ({d}/{d}/{d}) registered as device {d}", .{
|
||||||
port,
|
port,
|
||||||
interface.number,
|
interface.number,
|
||||||
|
usb_ids.interfaceName(interface.class, interface.subclass, interface.protocol),
|
||||||
interface.class,
|
interface.class,
|
||||||
interface.subclass,
|
interface.subclass,
|
||||||
interface.protocol,
|
interface.protocol,
|
||||||
|
|||||||
+2
-2
@@ -494,7 +494,7 @@ CASES = [
|
|||||||
# B4a: the hub powers its ports. B4b: the keyboard behind it enumerates
|
# B4a: the hub powers its ports. B4b: the keyboard behind it enumerates
|
||||||
# (route string + TT) and binds usb-hid-keyboard.
|
# (route string + TT) and binds usb-hid-keyboard.
|
||||||
"expect": r"(?s)(?=.*hub slot \d+: \d+ downstream ports powered)"
|
"expect": r"(?s)(?=.*hub slot \d+: \d+ downstream ports powered)"
|
||||||
r"(?=.*hub slot \d+ port \d+ device vendor 0x0627)"
|
r"(?=.*hub slot \d+ port \d+ device:.*vendor 0x0627)"
|
||||||
r"(?=.*usb-hid-keyboard: ok \(device 3)",
|
r"(?=.*usb-hid-keyboard: ok \(device 3)",
|
||||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||||
# USB mass storage end to end: the boot usb-storage device (the FAT32 image,
|
# USB mass storage end to end: the boot usb-storage device (the FAT32 image,
|
||||||
@@ -676,7 +676,7 @@ CASES = [
|
|||||||
"-device", "usb-hub,bus=xhci2.0,port=1",
|
"-device", "usb-hub,bus=xhci2.0,port=1",
|
||||||
"-device", "usb-hub,bus=xhci2.0,port=1.1",
|
"-device", "usb-hub,bus=xhci2.0,port=1.1",
|
||||||
"-device", "usb-kbd,bus=xhci2.0,port=1.1.1"],
|
"-device", "usb-kbd,bus=xhci2.0,port=1.1.1"],
|
||||||
"expect": r"(?s)(?=.*hub slot \d+ port \d+ device vendor 0x0409)"
|
"expect": r"(?s)(?=.*hub slot \d+ port \d+ device:.*vendor 0x0409)"
|
||||||
r"(?=.*usb-hid-keyboard: ok \(device 3)",
|
r"(?=.*usb-hid-keyboard: ok \(device 3)",
|
||||||
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
"fail": r"DANOS-TEST-RESULT: FAIL"},
|
||||||
# Hub-downstream disconnect (B4c): device_del the keyboard behind the hub;
|
# Hub-downstream disconnect (B4c): device_del the keyboard behind the hub;
|
||||||
|
|||||||
Reference in New Issue
Block a user