Skip to content

Commit

Permalink
feat: better usb detection
Browse files Browse the repository at this point in the history
Integrates changes from hwinfo and includes fields for Interface Association Descriptors.

Signed-off-by: Brian McGee <brian@bmcgee.ie>
  • Loading branch information
brianmcgee authored and mergify[bot] committed Sep 26, 2024
1 parent 4a180aa commit 53cbb6b
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 90 deletions.
3 changes: 1 addition & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ var (
scanner = facter.Scanner{}
)


func init() {
// Define flags
flag.StringVar(&outputPath, "output", "", "path to write the report")
Expand Down Expand Up @@ -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:
Expand Down
30 changes: 15 additions & 15 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions pkg/ephem/ephem.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
package ephem

import (
"log/slog"
"os"
"path/filepath"
"strings"

"log/slog"
)

var deviceGlobs = []string{
Expand Down
128 changes: 67 additions & 61 deletions pkg/hwinfo/detail_usb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
6 changes: 5 additions & 1 deletion pkg/hwinfo/hardware.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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),
Expand Down
3 changes: 1 addition & 2 deletions pkg/virt/detect_vm_device_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
package virt

import (
"log/slog"
"os"
"strings"

"log/slog"
)

func init() {
Expand Down
3 changes: 1 addition & 2 deletions pkg/virt/detect_vm_dmi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
package virt

import (
"log/slog"
"os"
"strings"

"log/slog"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion pkg/virt/detect_vm_hypervisor.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package virt

import (
"os"
"log/slog"
"os"
)

func detectHypervisor() (Type, error) {
Expand Down
3 changes: 1 addition & 2 deletions pkg/virt/detect_vm_uml.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package virt

import (
"log/slog"
"os"
"strings"

"log/slog"
)

func detectUml() (Type, error) {
Expand Down
3 changes: 1 addition & 2 deletions pkg/virt/detect_vm_xen.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ package virt

import (
"fmt"
"log/slog"
"os"
"strconv"
"strings"

"log/slog"
)

func detectXen() (Type, error) {
Expand Down

0 comments on commit 53cbb6b

Please sign in to comment.