Files
scrutiny/vendor/github.com/jaypipes/ghw/gpu_windows.go
T
2020-08-21 06:31:48 +00:00

129 lines
4.0 KiB
Go

// Use and distribution licensed under the Apache license version 2.
//
// See the COPYING file in the root project directory for full text.
//
package ghw
import (
"strings"
"github.com/StackExchange/wmi"
"github.com/jaypipes/pcidb"
)
const wqlVideoController = "SELECT Caption, CreationClassName, Description, DeviceID, Name, PNPDeviceID, SystemCreationClassName, SystemName, VideoArchitecture, VideoMemoryType, VideoModeDescription, VideoProcessor FROM Win32_VideoController"
type win32VideoController struct {
Caption string
CreationClassName string
Description string
DeviceID string
Name string
PNPDeviceID string
SystemCreationClassName string
SystemName string
VideoArchitecture uint16
VideoMemoryType uint16
VideoModeDescription string
VideoProcessor string
}
const wqlPnPEntity = "SELECT Caption, CreationClassName, Description, DeviceID, Manufacturer, Name, PNPClass, PNPDeviceID FROM Win32_PnPEntity"
type win32PnPEntity struct {
Caption string
CreationClassName string
Description string
DeviceID string
Manufacturer string
Name string
PNPClass string
PNPDeviceID string
}
func (ctx *context) gpuFillInfo(info *GPUInfo) error {
// Getting data from WMI
var win32VideoControllerDescriptions []win32VideoController
if err := wmi.Query(wqlVideoController, &win32VideoControllerDescriptions); err != nil {
return err
}
// Building dynamic WHERE clause with addresses to create a single query collecting all desired data
queryAddresses := []string{}
for _, description := range win32VideoControllerDescriptions {
var queryAddres = strings.Replace(description.PNPDeviceID, "\\", `\\`, -1)
queryAddresses = append(queryAddresses, "PNPDeviceID='"+queryAddres+"'")
}
whereClause := strings.Join(queryAddresses[:], " OR ")
// Getting data from WMI
var win32PnPDescriptions []win32PnPEntity
var wqlPnPDevice = wqlPnPEntity + " WHERE " + whereClause
if err := wmi.Query(wqlPnPDevice, &win32PnPDescriptions); err != nil {
return err
}
// Converting into standard structures
cards := make([]*GraphicsCard, 0)
for _, description := range win32VideoControllerDescriptions {
card := &GraphicsCard{
Address: description.DeviceID, // https://stackoverflow.com/questions/32073667/how-do-i-discover-the-pcie-bus-topology-and-slot-numbers-on-the-board
Index: 0,
DeviceInfo: ctx.GetDevice(description.PNPDeviceID, win32PnPDescriptions),
}
cards = append(cards, card)
}
info.GraphicsCards = cards
return nil
}
func (ctx *context) GetDevice(id string, entities []win32PnPEntity) *PCIDevice {
// Backslashing PnP address ID as requested by JSON and VMI query: https://docs.microsoft.com/en-us/windows/win32/wmisdk/where-clause
var queryAddress = strings.Replace(id, "\\", `\\`, -1)
// Preparing default structure
var device = &PCIDevice{
Address: queryAddress,
Vendor: &pcidb.Vendor{
ID: UNKNOWN,
Name: UNKNOWN,
Products: []*pcidb.Product{},
},
Subsystem: &pcidb.Product{
ID: UNKNOWN,
Name: UNKNOWN,
Subsystems: []*pcidb.Product{},
},
Product: &pcidb.Product{
ID: UNKNOWN,
Name: UNKNOWN,
Subsystems: []*pcidb.Product{},
},
Class: &pcidb.Class{
ID: UNKNOWN,
Name: UNKNOWN,
Subclasses: []*pcidb.Subclass{},
},
Subclass: &pcidb.Subclass{
ID: UNKNOWN,
Name: UNKNOWN,
ProgrammingInterfaces: []*pcidb.ProgrammingInterface{},
},
ProgrammingInterface: &pcidb.ProgrammingInterface{
ID: UNKNOWN,
Name: UNKNOWN,
},
}
// If an entity is found we get its data inside the standard structure
for _, description := range entities {
if id == description.PNPDeviceID {
device.Vendor.ID = description.Manufacturer
device.Vendor.Name = description.Manufacturer
device.Product.ID = description.Name
device.Product.Name = description.Description
break
}
}
return device
}