github.com/jaypipes/ghw@v0.21.1/pkg/gpu/gpu_windows.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 gpu 7 8 import ( 9 "strings" 10 11 "github.com/jaypipes/pcidb" 12 "github.com/yusufpapurcu/wmi" 13 14 "github.com/jaypipes/ghw/pkg/pci" 15 "github.com/jaypipes/ghw/pkg/util" 16 ) 17 18 const wqlVideoController = "SELECT Caption, CreationClassName, Description, DeviceID, DriverVersion, Name, PNPDeviceID, SystemCreationClassName, SystemName, VideoArchitecture, VideoMemoryType, VideoModeDescription, VideoProcessor FROM Win32_VideoController" 19 20 type win32VideoController struct { 21 Caption string 22 CreationClassName string 23 Description string 24 DeviceID string 25 DriverVersion string 26 Name string 27 PNPDeviceID string 28 SystemCreationClassName string 29 SystemName string 30 VideoArchitecture uint16 31 VideoMemoryType uint16 32 VideoModeDescription string 33 VideoProcessor string 34 } 35 36 const wqlPnPEntity = "SELECT Caption, CreationClassName, Description, DeviceID, Manufacturer, Name, PNPClass, PNPDeviceID FROM Win32_PnPEntity" 37 38 type win32PnPEntity struct { 39 Caption string 40 CreationClassName string 41 Description string 42 DeviceID string 43 Manufacturer string 44 Name string 45 PNPClass string 46 PNPDeviceID string 47 } 48 49 func (i *Info) load() error { 50 // Getting data from WMI 51 var win32VideoControllerDescriptions []win32VideoController 52 if err := wmi.Query(wqlVideoController, &win32VideoControllerDescriptions); err != nil { 53 return err 54 } 55 56 // Building dynamic WHERE clause with addresses to create a single query collecting all desired data 57 queryAddresses := []string{} 58 for _, description := range win32VideoControllerDescriptions { 59 var queryAddres = strings.ReplaceAll(description.PNPDeviceID, "\\", `\\`) 60 queryAddresses = append(queryAddresses, "PNPDeviceID='"+queryAddres+"'") 61 } 62 whereClause := strings.Join(queryAddresses[:], " OR ") 63 64 // Getting data from WMI 65 var win32PnPDescriptions []win32PnPEntity 66 var wqlPnPDevice = wqlPnPEntity + " WHERE " + whereClause 67 if err := wmi.Query(wqlPnPDevice, &win32PnPDescriptions); err != nil { 68 return err 69 } 70 71 // Converting into standard structures 72 cards := make([]*GraphicsCard, 0) 73 for _, description := range win32VideoControllerDescriptions { 74 card := &GraphicsCard{ 75 Address: description.DeviceID, // https://stackoverflow.com/questions/32073667/how-do-i-discover-the-pcie-bus-topology-and-slot-numbers-on-the-board 76 Index: 0, 77 DeviceInfo: GetDevice(description.PNPDeviceID, win32PnPDescriptions), 78 } 79 card.DeviceInfo.Driver = description.DriverVersion 80 cards = append(cards, card) 81 } 82 i.GraphicsCards = cards 83 return nil 84 } 85 86 func GetDevice(id string, entities []win32PnPEntity) *pci.Device { 87 // Backslashing PnP address ID as requested by JSON and VMI query: https://docs.microsoft.com/en-us/windows/win32/wmisdk/where-clause 88 var queryAddress = strings.ReplaceAll(id, "\\", `\\`) 89 // Preparing default structure 90 var device = &pci.Device{ 91 Address: queryAddress, 92 Vendor: &pcidb.Vendor{ 93 ID: util.UNKNOWN, 94 Name: util.UNKNOWN, 95 Products: []*pcidb.Product{}, 96 }, 97 Subsystem: &pcidb.Product{ 98 ID: util.UNKNOWN, 99 Name: util.UNKNOWN, 100 Subsystems: []*pcidb.Product{}, 101 }, 102 Product: &pcidb.Product{ 103 ID: util.UNKNOWN, 104 Name: util.UNKNOWN, 105 Subsystems: []*pcidb.Product{}, 106 }, 107 Class: &pcidb.Class{ 108 ID: util.UNKNOWN, 109 Name: util.UNKNOWN, 110 Subclasses: []*pcidb.Subclass{}, 111 }, 112 Subclass: &pcidb.Subclass{ 113 ID: util.UNKNOWN, 114 Name: util.UNKNOWN, 115 ProgrammingInterfaces: []*pcidb.ProgrammingInterface{}, 116 }, 117 ProgrammingInterface: &pcidb.ProgrammingInterface{ 118 ID: util.UNKNOWN, 119 Name: util.UNKNOWN, 120 }, 121 } 122 // If an entity is found we get its data inside the standard structure 123 for _, description := range entities { 124 if id == description.PNPDeviceID { 125 device.Vendor.ID = description.Manufacturer 126 device.Vendor.Name = description.Manufacturer 127 device.Product.ID = description.Name 128 device.Product.Name = description.Description 129 break 130 } 131 } 132 return device 133 }