77package main
88
99import (
10- "bufio"
1110 "encoding/json"
1211 "encoding/xml"
1312 "flag"
1413 "fmt"
1514 "log"
1615 "os"
17- "path/filepath"
18- "regexp"
1916 "strings"
2017 "text/tabwriter"
18+
19+ "github.com/TimRots/gutil-linux/pci"
2120)
2221
2322const (
5655 xmloutput = flag .Bool ("xml" , false , "use XML output format" )
5756
5857 PciDevices []PciDevice
59- errCnt = 0
6058)
6159
6260func init () {
@@ -88,7 +86,7 @@ func main() {
8886}
8987
9088func printDevices (opts string , params ... bool ) {
91- PciDevices := ParsePciDevices ()
89+ PciDevices , err := pci . ParsePciDevices ()
9290
9391 switch opts {
9492 case "json" :
@@ -100,9 +98,13 @@ func printDevices(opts string, params ...bool) {
10098 default :
10199 tabWriter (PciDevices )
102100 }
101+
102+ if err != nil {
103+ log .Fatal (err )
104+ }
103105}
104106
105- func tabWriter (PciDevices []PciDevice ) {
107+ func tabWriter (PciDevices []pci. PciDevice ) {
106108 w := tabwriter .NewWriter (os .Stdout , 0 , 0 , 1 , ' ' , 0 )
107109 defer w .Flush ()
108110
@@ -157,147 +159,3 @@ func tabWriter(PciDevices []PciDevice) {
157159 }
158160 }
159161}
160-
161- func readFromFile (f string , w int ) string {
162- var value []string
163-
164- file , err := os .Open (f )
165- if err != nil {
166- log .Fatal (err )
167- }
168- defer file .Close ()
169-
170- if w == 0 {
171- w = 1
172- }
173- scanner , i , w := bufio .NewScanner (file ), 0 , w
174- for scanner .Scan () {
175- for _ , word := range regexp .MustCompile (`[\S]+` ).FindAllString (scanner .Text (), - 1 ) {
176- switch i ++ ; {
177- case i == w :
178- value = append (value , string (word ))
179- }
180- return strings .Join (value , " " )
181- }
182- }
183- return ""
184- }
185-
186- func Lookup (searchType , ven , dev , class , subclass string ) string {
187- var found bool = false
188-
189- // Open pci.ids
190- f , err := os .Open ("./pci.ids" )
191- if err != nil {
192- errCnt ++
193- if errCnt < 2 {
194- fmt .Println ("Error: Cannot open pci.ids file, defaulting to numeric" )
195- }
196- * numeric = true
197- return ""
198- }
199- // close pci.ids file when done
200- defer func () {
201- if err := f .Close (); err != nil {
202- log .Fatal (err )
203- }
204- }()
205-
206- scanner := bufio .NewScanner (f )
207- for scanner .Scan () {
208- switch searchType {
209- case "vendor" : // Return first occurence of ven that does not have a \t prefix.
210- if strings .Contains (scanner .Text (), ven ) && ! strings .HasPrefix (scanner .Text (), "\t " ) {
211- return strings .TrimLeft (scanner .Text (), ven + " " )
212- }
213-
214- case "device" : // Return first occurence of dev after vendor is found
215- if strings .Contains (scanner .Text (), ven ) && ! strings .HasPrefix (scanner .Text (), "\t " ) {
216- found = true
217- }
218- if strings .HasPrefix (scanner .Text (), "\t " + dev ) && found {
219- return strings .TrimLeft (scanner .Text (), "\t \t " + dev + " " )
220- }
221-
222- case "class" : // Split class (eg: 0600), search for "C 06" and return first occurence of "\t\t00" therafter.
223- if strings .Contains (scanner .Text (), "C" + " " + class [0 :2 ]) && ! strings .HasPrefix (scanner .Text (), "\t " ) {
224- found = true
225- }
226- if strings .HasPrefix (scanner .Text (), "\t " + class [2 :4 ]) && found {
227- return strings .TrimLeft (scanner .Text (), "\t \t " + class + " " )
228-
229- }
230- case "subsystem" : // Match and return line "\t\t vendor subsystem_device"
231- if strings .Contains (scanner .Text (), ven + " " + subclass ) {
232- return strings .TrimLeft (scanner .Text (), "\t \t " + ven + " " + subclass )
233- }
234- }
235- }
236- if err := scanner .Err (); err != nil {
237- log .Fatal (err )
238- }
239- return "Unknown " + searchType
240- }
241-
242- func ParsePciDevices () []PciDevice {
243- var devices []string
244-
245- read := func (bus , filename string ) string {
246- return readFromFile (filepath .Join (PATH_SYS_BUS_PCI_DEVICES , bus , filename ), 1 )
247- }
248-
249- lookupKernelDriver := func (bus string ) string {
250- read := readFromFile (filepath .Join (PATH_SYS_DEVICES_PCI + bus [0 :7 ], bus , "uevent" ), 1 )
251- if strings .Contains (read , "DRIVER=" ) {
252- return read [7 :]
253- }
254- return ""
255- }
256-
257- // Find all devices in /sys/bus/pci/devices/ and append each device to devices[]
258- if err := filepath .Walk (
259- PATH_SYS_BUS_PCI_DEVICES ,
260- func (path string , info os.FileInfo , err error ) error {
261- if ! info .IsDir () {
262- devices = append (devices , info .Name ())
263- }
264- return nil
265- }); err != nil {
266- log .Fatal (err )
267- }
268-
269- // Iterate over each bus and parse & append values to PciDevices[]
270- for _ , bus := range devices {
271- dev := read (bus , "device" )[2 :6 ]
272- ven := read (bus , "vendor" )[2 :6 ]
273- class := read (bus , "class" )[2 :6 ]
274- subDev := read (bus , "subsystem_device" )[2 :6 ]
275- subVen := read (bus , "subsystem_vendor" )[2 :6 ]
276- mod := read (bus , "modalias" )
277- irq := read (bus , "irq" )
278- rev := read (bus , "revision" )[2 :4 ]
279-
280- venName := Lookup ("vendor" , ven , "" , "" , "" )
281- devName := Lookup ("device" , ven , dev , "" , "" )
282- devClass := Lookup ("class" , "" , "" , class , "" )
283-
284- subSys := ""
285- if subVen != "0000" {
286- subSys = Lookup ("subsystem" , ven , "" , "" , subDev )
287- }
288-
289- kernelDriver := lookupKernelDriver (bus )
290-
291- if ! * showdomainnumbers && ! * jsonoutput {
292- bus = strings .TrimPrefix (bus , "0000:" )
293- }
294-
295- PciDevices = append (PciDevices ,
296- PciDevice {
297- bus , ven , dev , class , subVen , subDev , irq , rev ,
298- venName , devName , devClass , subSys , "" , mod , kernelDriver ,
299- },
300- )
301- }
302- return PciDevices
303- }
0 commit comments