github.com/jaypipes/ghw@v0.21.1/pkg/usb/usb_linux.go (about) 1 // Use and distribution licensed under the Apache license version 2. 2 // 3 // See the COPYING file in the root project directory for full text. 4 // 5 6 package usb 7 8 import ( 9 "bufio" 10 "bytes" 11 "fmt" 12 "os" 13 "path/filepath" 14 "strings" 15 16 "github.com/jaypipes/ghw/pkg/context" 17 "github.com/jaypipes/ghw/pkg/linuxpath" 18 ) 19 20 func (i *Info) load() error { 21 var errs []error 22 23 i.Devices, errs = usbs(i.ctx) 24 25 if len(errs) == 0 { 26 return nil 27 } 28 return fmt.Errorf("error(s) happened during reading usb info: %+v", errs) 29 } 30 31 func fillUSBFromUevent(dir string, dev *Device) (err error) { 32 ueventFp, err := os.Open(filepath.Join(dir, "uevent")) 33 if err != nil { 34 return 35 } 36 defer func() { 37 err = ueventFp.Close() 38 }() 39 40 sc := bufio.NewScanner(ueventFp) 41 for sc.Scan() { 42 line := sc.Text() 43 44 splits := strings.SplitN(line, "=", 2) 45 if len(splits) != 2 { 46 continue 47 } 48 49 key := strings.ToUpper(splits[0]) 50 val := splits[1] 51 52 switch key { 53 case "DRIVER": 54 dev.Driver = val 55 case "TYPE": 56 dev.Type = val 57 case "PRODUCT": 58 splits := strings.SplitN(val, "/", 3) 59 if len(splits) != 3 { 60 continue 61 } 62 dev.VendorID = splits[0] 63 dev.ProductID = splits[1] 64 dev.RevisionID = splits[2] 65 } 66 } 67 return nil 68 } 69 70 func slurp(path string) string { 71 bs, err := os.ReadFile(path) 72 if err != nil { 73 return "" 74 } 75 76 return string(bytes.TrimSpace(bs)) 77 } 78 79 func usbs(ctx *context.Context) ([]*Device, []error) { 80 devs := make([]*Device, 0) 81 errs := []error{} 82 83 paths := linuxpath.New(ctx) 84 usbDevicesDirs, err := os.ReadDir(paths.SysBusUsbDevices) 85 if err != nil { 86 return devs, []error{err} 87 } 88 89 for _, dir := range usbDevicesDirs { 90 fullDir, err := os.Readlink(filepath.Join(paths.SysBusUsbDevices, dir.Name())) 91 if err != nil { 92 continue 93 } 94 if !filepath.IsAbs(fullDir) { 95 fullDir, err = filepath.Abs(filepath.Join(paths.SysBusUsbDevices, fullDir)) 96 if err != nil { 97 continue 98 } 99 } 100 101 dev := Device{} 102 103 err = fillUSBFromUevent(fullDir, &dev) 104 if err != nil { 105 errs = append(errs, err) 106 } 107 108 dev.Interface = slurp(filepath.Join(fullDir, "interface")) 109 dev.Product = slurp(filepath.Join(fullDir, "product")) 110 111 devs = append(devs, &dev) 112 } 113 114 return devs, errs 115 }