From 53cbb6b281c3973faa3c05d1a5a9f957e2cc8187 Mon Sep 17 00:00:00 2001 From: Brian McGee Date: Thu, 26 Sep 2024 12:38:31 +0100 Subject: [PATCH] feat: better usb detection Integrates changes from hwinfo and includes fields for Interface Association Descriptors. Signed-off-by: Brian McGee --- cmd/root.go | 3 +- flake.lock | 30 +++---- pkg/ephem/ephem.go | 3 +- pkg/hwinfo/detail_usb.go | 128 ++++++++++++++++-------------- pkg/hwinfo/hardware.go | 6 +- pkg/virt/detect_vm_device_tree.go | 3 +- pkg/virt/detect_vm_dmi.go | 3 +- pkg/virt/detect_vm_hypervisor.go | 2 +- pkg/virt/detect_vm_uml.go | 3 +- pkg/virt/detect_vm_xen.go | 3 +- 10 files changed, 94 insertions(+), 90 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index a3a121a..77d5bec 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,7 +20,6 @@ var ( scanner = facter.Scanner{} ) - func init() { // Define flags flag.StringVar(&outputPath, "output", "", "path to write the report") @@ -50,7 +49,7 @@ func init() { }) possibleValues := strings.Join(filteredFeatures, ",") defaultValues := strings.Join(defaultFeatures, ",") - const usage = `nixos-facter [flags] + const usage = `nixos-facter [flags] Hardware report generator Usage: diff --git a/flake.lock b/flake.lock index fc907a1..aec4646 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ ] }, "locked": { - "lastModified": 1726602501, - "narHash": "sha256-CjR5wLjo8+zE7WqSVfHS+NOiyFW6HMFMFONa6B8lYR8=", + "lastModified": 1727084436, + "narHash": "sha256-H5rbzYDlQD/lmTKvvfyohnhB+zdoZfykghjFHi2rS7o=", "owner": "numtide", "repo": "blueprint", - "rev": "8d92ba0316f78a88bbc6ed3fda445f5699ad827e", + "rev": "77e32417d97959e3d81d22211cba7c8ba44c0079", "type": "github" }, "original": { @@ -30,11 +30,11 @@ ] }, "locked": { - "lastModified": 1726842196, - "narHash": "sha256-u9h03JQUuQJ607xmti9F9Eh6E96kKUAGP+aXWgwm70o=", + "lastModified": 1727347829, + "narHash": "sha256-y7cW6TjJKy+tu7efxeWI6lyg4VVx/9whx+OmrhmRShU=", "owner": "nix-community", "repo": "disko", - "rev": "51994df8ba24d5db5459ccf17b6494643301ad28", + "rev": "1879e48907c14a70302ff5d0539c3b9b6f97feaa", "type": "github" }, "original": { @@ -176,11 +176,11 @@ ] }, "locked": { - "lastModified": 1725441180, - "narHash": "sha256-OXbGF8M1r8GSgqeY4TqfjF+IO0SXXB/dX2jE2JtkPUk=", + "lastModified": 1727361527, + "narHash": "sha256-3abkWPr98qXXQ17r1Z43gh2M5hl/DHjW2hfeWl+GSAs=", "owner": "numtide", "repo": "hwinfo", - "rev": "42b014495b2de8735eeec950bc2d3afbefc65ec4", + "rev": "a559f34934098d54096ed2078e750a8245ae4044", "type": "github" }, "original": { @@ -191,11 +191,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726755586, - "narHash": "sha256-PmUr/2GQGvFTIJ6/Tvsins7Q43KTMvMFhvG6oaYK+Wk=", + "lastModified": 1727122398, + "narHash": "sha256-o8VBeCWHBxGd4kVMceIayf5GApqTavJbTa44Xcg5Rrk=", "owner": "nixos", "repo": "nixpkgs", - "rev": "c04d5652cfa9742b1d519688f65d1bbccea9eb7e", + "rev": "30439d93eb8b19861ccbe3e581abf97bdc91b093", "type": "github" }, "original": { @@ -240,11 +240,11 @@ ] }, "locked": { - "lastModified": 1726734507, - "narHash": "sha256-VUH5O5AcOSxb0uL/m34dDkxFKP6WLQ6y4I1B4+N3L2w=", + "lastModified": 1727252110, + "narHash": "sha256-3O7RWiXpvqBcCl84Mvqa8dXudZ1Bol1ubNdSmQt7nF4=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "ee41a466c2255a3abe6bc50fc6be927cdee57a9f", + "rev": "1bff2ba6ec22bc90e9ad3f7e94cca0d37870afa3", "type": "github" }, "original": { diff --git a/pkg/ephem/ephem.go b/pkg/ephem/ephem.go index f4f45f9..99476d9 100644 --- a/pkg/ephem/ephem.go +++ b/pkg/ephem/ephem.go @@ -5,11 +5,10 @@ package ephem import ( + "log/slog" "os" "path/filepath" "strings" - - "log/slog" ) var deviceGlobs = []string{ diff --git a/pkg/hwinfo/detail_usb.go b/pkg/hwinfo/detail_usb.go index 51ed3f7..5a468cf 100644 --- a/pkg/hwinfo/detail_usb.go +++ b/pkg/hwinfo/detail_usb.go @@ -36,43 +36,27 @@ const ( ) type DetailUsb struct { - Type DetailType `json:"-"` - Bus int `json:"bus"` - DeviceNumber int `json:"device_number"` - Lev int `json:"lev"` // TODO what is lev short for? - Parent int `json:"parent"` - Port int `json:"port"` - Count int `json:"count"` - Connections int `json:"connections"` - UsedConnections int `json:"used_connections"` - InterfaceDescriptor int `json:"interface_descriptor"` - Speed uint `json:"speed"` + Type DetailType `json:"-"` - Manufacturer string `json:"manufacturer,omitempty"` - Product string `json:"product,omitempty"` + DeviceClass Id `json:"device_class"` + DeviceSubclass Id `json:"device_subclass"` + DeviceProtocol int `json:"device_protocol"` - Driver string `json:"driver,omitempty"` + InterfaceClass Id `json:"interface_class"` + InterfaceSubclass Id `json:"interface_subclass"` + InterfaceProtocol int `json:"interface_protocol"` + InterfaceNumber int `json:"interface_number"` + InterfaceAlternateSetting int `json:"interface_alternate_setting"` - DeviceClass UsbClass `json:"device_class,omitempty"` - DeviceSubclass int `json:"device_subclass,omitempty"` - DeviceProtocol int `json:"device_protocol,omitempty"` - - InterfaceClass UsbClass `json:"interface_class,omitempty"` - InterfaceSubclass int `json:"interface_subclass,omitempty"` - InterfaceProtocol int `json:"interface_protocol,omitempty"` - - Country uint `json:"country"` - - // already included in the parent model, so we omit from JSON output - Vendor uint `json:"-"` - Device uint `json:"-"` - Revision uint `json:"-"` - - // Seems empty and not really needed, omit for now - RawDescriptor MemoryRange `json:"-"` + InterfaceAssociation *DetailUsbInterfaceAssociation `json:"interface_association,omitempty"` +} - // Sensitive, omit from JSON output - Serial string `json:"-"` +type DetailUsbInterfaceAssociation struct { + FunctionClass Id `json:"function_class"` + FunctionSubclass Id `json:"function_subclass"` + FunctionProtocol int `json:"function_protocol"` + InterfaceCount int `json:"interface_count"` + FirstInterface int `json:"first_interface"` } func (d DetailUsb) DetailType() DetailType { @@ -86,32 +70,54 @@ func NewDetailUsb(usb C.hd_detail_usb_t) (Detail, error) { println("usb next is not nil") } - return DetailUsb{ - Type: DetailTypeUsb, - Bus: int(data.bus), - DeviceNumber: int(data.dev_nr), - Lev: int(data.lev), - Parent: int(data.parent), - Port: int(data.port), - Count: int(data.count), - Connections: int(data.conns), - UsedConnections: int(data.used_conns), - InterfaceDescriptor: int(data.ifdescr), - Speed: uint(data.speed), - Vendor: uint(data.vendor), - Device: uint(data.device), - Revision: uint(data.rev), - Manufacturer: C.GoString(data.manufact), - Product: C.GoString(data.product), - Serial: C.GoString(data.serial), - Driver: C.GoString(data.driver), - RawDescriptor: NewMemoryRange(data.raw_descr), - DeviceClass: UsbClass(data.d_cls), - DeviceSubclass: int(data.d_sub), - DeviceProtocol: int(data.d_prot), - // todo data.i_alt?? - InterfaceClass: UsbClass(data.i_cls), - InterfaceSubclass: int(data.i_sub), - InterfaceProtocol: int(data.i_prot), - }, nil + detail := DetailUsb{ + Type: DetailTypeUsb, + DeviceClass: Id{ + Type: IdTagUsb, + Value: uint16(data.d_cls), + Name: UsbClass(data.d_cls).String(), + }, + DeviceSubclass: Id{ + Type: IdTagUsb, + Value: uint16(data.d_sub), + Name: UsbClass(data.d_sub).String(), + }, + DeviceProtocol: int(data.d_prot), + InterfaceClass: Id{ + Type: IdTagUsb, + Value: uint16(data.i_cls), + Name: UsbClass(data.i_cls).String(), + }, + InterfaceSubclass: Id{ + Type: IdTagUsb, + Value: uint16(data.i_sub), + Name: UsbClass(data.i_sub).String(), + }, + InterfaceProtocol: int(data.i_prot), + InterfaceNumber: int(data.ifdescr), + InterfaceAlternateSetting: int(data.i_alt), + } + + // The Interface Association Descriptor groups multiple interfaces that are part of a single functional device. + // For instance, a USB webcam with an integrated microphone would use an IAD to group the video input interface and + // the audio input interface together. + if data.iad_i_count > 0 { + detail.InterfaceAssociation = &DetailUsbInterfaceAssociation{ + FunctionClass: Id{ + Type: IdTagUsb, + Value: uint16(data.iad_f_cls), + Name: UsbClass(data.iad_f_cls).String(), + }, + FunctionSubclass: Id{ + Type: IdTagUsb, + Value: uint16(data.iad_f_sub), + Name: UsbClass(data.iad_f_sub).String(), + }, + FunctionProtocol: int(data.iad_f_prot), + FirstInterface: int(data.iad_i_first), + InterfaceCount: int(data.iad_i_count), + } + } + + return detail, nil } diff --git a/pkg/hwinfo/hardware.go b/pkg/hwinfo/hardware.go index 6fe62fd..7a12aba 100644 --- a/pkg/hwinfo/hardware.go +++ b/pkg/hwinfo/hardware.go @@ -266,7 +266,10 @@ type HardwareDevice struct { Class HardwareClass `json:"-"` // Index is a unique index provided by hwinfo, starting at 1 - Index uint `json:"-"` + Index uint `json:"index"` + + // AttachedTo is the index of the hardware device this is attached to + AttachedTo uint `json:"attached_to"` // BusType represents the type of bus to which the hardware device is connected. BusType *Id `json:"bus_type,omitempty"` @@ -426,6 +429,7 @@ func NewHardwareDevice(hd *C.hd_t) (*HardwareDevice, error) { result := &HardwareDevice{ Index: uint(hd.idx), + AttachedTo: uint(hd.attached_to), BusType: NewId(hd.bus), BaseClass: NewId(hd.base_class), SubClass: NewId(hd.sub_class), diff --git a/pkg/virt/detect_vm_device_tree.go b/pkg/virt/detect_vm_device_tree.go index 1490f9f..1a0af7c 100644 --- a/pkg/virt/detect_vm_device_tree.go +++ b/pkg/virt/detect_vm_device_tree.go @@ -3,10 +3,9 @@ package virt import ( + "log/slog" "os" "strings" - - "log/slog" ) func init() { diff --git a/pkg/virt/detect_vm_dmi.go b/pkg/virt/detect_vm_dmi.go index 48697b7..1f00bf8 100644 --- a/pkg/virt/detect_vm_dmi.go +++ b/pkg/virt/detect_vm_dmi.go @@ -3,10 +3,9 @@ package virt import ( + "log/slog" "os" "strings" - - "log/slog" ) var ( diff --git a/pkg/virt/detect_vm_hypervisor.go b/pkg/virt/detect_vm_hypervisor.go index a1b2136..5d6f9b2 100644 --- a/pkg/virt/detect_vm_hypervisor.go +++ b/pkg/virt/detect_vm_hypervisor.go @@ -1,8 +1,8 @@ package virt import ( - "os" "log/slog" + "os" ) func detectHypervisor() (Type, error) { diff --git a/pkg/virt/detect_vm_uml.go b/pkg/virt/detect_vm_uml.go index 72a2640..6c80d84 100644 --- a/pkg/virt/detect_vm_uml.go +++ b/pkg/virt/detect_vm_uml.go @@ -1,10 +1,9 @@ package virt import ( + "log/slog" "os" "strings" - - "log/slog" ) func detectUml() (Type, error) { diff --git a/pkg/virt/detect_vm_xen.go b/pkg/virt/detect_vm_xen.go index 3bb47af..e316583 100644 --- a/pkg/virt/detect_vm_xen.go +++ b/pkg/virt/detect_vm_xen.go @@ -2,11 +2,10 @@ package virt import ( "fmt" + "log/slog" "os" "strconv" "strings" - - "log/slog" ) func detectXen() (Type, error) {