Skip to content

Commit fcf899d

Browse files
christoph-zededaeriknordmark
authored andcommitted
pillar/usbmanager: use ghw library
the jaypipes/ghw (zededa/ghw) library has been introduced for sending hardware inventory to the controller as of this our own implementation for scanning for USB devices is not needed anymore Signed-off-by: Christoph Ostarek <christoph@zededa.com>
1 parent b92d1ff commit fcf899d

File tree

2 files changed

+268
-116
lines changed

2 files changed

+268
-116
lines changed

pkg/pillar/cmd/usbmanager/scanusb.go

Lines changed: 45 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
package usbmanager
44

55
import (
6-
"bufio"
7-
"fmt"
8-
"io"
9-
"os"
10-
"path/filepath"
116
"regexp"
127
"strconv"
138
"strings"
149

1510
"github.com/lf-edge/eve/pkg/pillar/types"
11+
"github.com/zededa/ghw"
12+
"github.com/zededa/ghw/pkg/option"
13+
"github.com/zededa/ghw/pkg/usb"
1614
)
1715

1816
func trimSysPath(path string) string {
@@ -47,139 +45,73 @@ func extractUSBPort(path string) string {
4745
func walkUSBPorts() []*usbdevice {
4846
uds := make([]*usbdevice, 0)
4947

50-
inSysPath := filepath.Join("bus", "usb", "devices")
51-
usbDevicesPath := filepath.Join(sysFSPath, inSysPath)
52-
53-
files, err := os.ReadDir(usbDevicesPath)
48+
info, err := ghw.USB(option.WithDisableTools())
5449
if err != nil {
55-
log.Fatal(err)
50+
log.Warnf("requesting USB info failed: %+v", err)
51+
return []*usbdevice{}
5652
}
5753

58-
re := regexp.MustCompile(`^\d+-\d+`)
59-
for _, file := range files {
60-
if len(file.Name()) == 0 {
61-
continue
62-
}
63-
64-
if !re.Match([]byte(file.Name())) {
54+
for _, dev := range info.Devices {
55+
ud := ghwUSBDevice2usbdevice(dev)
56+
if ud == nil {
6557
continue
6658
}
6759

68-
relPortPath := filepath.Join(usbDevicesPath, file.Name())
69-
//fmt.Printf("%s -> %s\n", vals[0], vals[1])
70-
ud := usbDeviceFromSysPath(relPortPath)
71-
if ud != nil {
72-
uds = append(uds, ud)
73-
}
60+
uds = append(uds, ud)
7461
}
75-
7662
return uds
7763
}
7864

79-
func usbDeviceFromSysPath(relPortPath string) *usbdevice {
80-
portPath, err := os.Readlink(relPortPath)
65+
func ghwUSBDevice2usbdevice(dev *usb.Device) *usbdevice {
66+
devnum, err := strconv.ParseUint(dev.Devnum, 10, 16)
8167
if err != nil {
82-
fmt.Printf("err: %+v\n", err)
68+
// ignore hubs, devices with invalid devnum
8369
return nil
8470
}
8571

86-
inSysPath := filepath.Join("bus", "usb", "devices")
87-
usbDevicesPath := filepath.Join(sysFSPath, inSysPath)
88-
portPath = filepath.Join(usbDevicesPath, portPath)
89-
90-
ueventFilePath := filepath.Join(portPath, "uevent")
91-
return ueventFile2usbDevice(ueventFilePath)
92-
}
93-
94-
func ueventFile2usbDevice(ueventFilePath string) *usbdevice {
95-
ueventFp, err := os.Open(ueventFilePath)
72+
// continue even if parsing vendor/product fails, because in the case of passthrough
73+
// by port it still works
74+
vendorID, err := strconv.ParseUint(dev.VendorID, 16, 32)
9675
if err != nil {
97-
return nil
76+
log.Warnf("could not parse vendor id '%s' as uint32: %+v", dev.VendorID, err)
9877
}
99-
defer ueventFp.Close()
100-
101-
return ueventFile2usbDeviceImpl(ueventFilePath, ueventFp)
102-
}
103-
104-
func ueventFile2usbDeviceImpl(ueventFilePath string, ueventFp io.Reader) *usbdevice {
105-
106-
var busnum uint16
107-
var devnum uint16
108-
var vendorID uint32
109-
var productID uint32
110-
var product string
111-
var devicetype string
112-
113-
busnumSet := false
114-
devnumSet := false
115-
productSet := false
116-
117-
sc := bufio.NewScanner(ueventFp)
118-
for sc.Scan() {
119-
vals := strings.SplitN(sc.Text(), "=", 2)
120-
if len(vals) != 2 {
121-
continue
122-
}
123-
124-
if vals[1] == "" {
125-
continue
126-
}
127-
128-
if vals[0] == "BUSNUM" {
129-
val64, err := strconv.ParseUint(vals[1], 10, 16)
130-
if err != nil {
131-
log.Warnf("could not parse BUSNUM %+v", vals)
132-
return nil
133-
}
134-
busnum = uint16(val64)
135-
busnumSet = true
136-
}
137-
if vals[0] == "DEVNUM" {
138-
val64, err := strconv.ParseUint(vals[1], 10, 16)
139-
if err != nil {
140-
log.Warnf("could not parse DEVNUM %+v", vals)
141-
return nil
142-
}
143-
devnum = uint16(val64)
144-
devnumSet = true
145-
}
146-
if vals[0] == "PRODUCT" {
147-
product = vals[1]
148-
vendorID, productID = parseProductString(product)
149-
if vendorID != 0 || productID != 0 {
150-
productSet = true
151-
}
152-
}
153-
if vals[0] == "TYPE" {
154-
devicetype = vals[1]
155-
}
78+
productID, err := strconv.ParseUint(dev.ProductID, 16, 32)
79+
if err != nil {
80+
log.Warnf("could not parse product id '%s' as uint32: %+v", dev.ProductID, err)
15681
}
15782

158-
if sc.Err() != nil {
159-
log.Warnf("Parsing of %s failed: %v", ueventFilePath, sc.Err())
160-
return nil
83+
var usbControllerPCIAddress string
84+
if dev.Parent.PCI != nil {
85+
usbControllerPCIAddress = dev.Parent.PCI.String()
86+
}
87+
ud := usbdevice{
88+
busnum: dev.Busnum,
89+
portnum: dev.Port,
90+
devnum: uint16(devnum),
91+
vendorID: uint32(vendorID),
92+
productID: uint32(productID),
93+
devicetype: dev.Type,
94+
usbControllerPCIAddress: usbControllerPCIAddress,
95+
ueventFilePath: dev.UEventFilePath,
16196
}
97+
return &ud
98+
}
16299

163-
if !busnumSet || !devnumSet || !productSet {
100+
func ueventFile2usbDevice(ueventFilePath string) *usbdevice {
101+
info, err := ghw.USB(option.WithUSBUeventPath(ueventFilePath), option.WithDisableTools())
102+
if err != nil {
103+
log.Warnf("could not retrieve usb device for '%s': %v", ueventFilePath, err)
164104
return nil
165105
}
166106

167-
pciAddress := extractPCIaddress(ueventFilePath)
168-
169-
portnum := extractUSBPort(ueventFilePath)
170-
171-
ud := usbdevice{
172-
busnum: busnum,
173-
devnum: devnum,
174-
portnum: portnum,
175-
vendorID: vendorID,
176-
productID: productID,
177-
devicetype: devicetype,
178-
usbControllerPCIAddress: pciAddress,
179-
ueventFilePath: filepath.Clean(ueventFilePath),
107+
for _, dev := range info.Devices {
108+
ud := ghwUSBDevice2usbdevice(dev)
109+
if ud != nil {
110+
return ud
111+
}
180112
}
181113

182-
return &ud
114+
return nil
183115
}
184116

185117
func parseProductString(product string) (uint32, uint32) {

0 commit comments

Comments
 (0)