forked from jaypipes/ghw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gpu_windows.go
128 lines (116 loc) · 4 KB
/
gpu_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// 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
}