Skip to content

Commit 7a75779

Browse files
stsdcryonakano
andauthored
Use libpci to retrieve some basic PCI data (#440)
* Add pci dep * Add libpci dep * libpci-dev * missed space * Try to use LIB_VERSION * Add Access and Dev structs * wip * Use struct in cname * Add pci_scan_bus * Update structs according to ver. 3.10.0 * Make pci_init a standalone function * list all pci addresses * Introduce pci_lookup_name * remove ref * convert Access to class * Reintroduce pci_cleanup as destroy_function for Access class * standalone functions are now methods of Access class * Introduce class Dev; use free_function * Return unowned nullable string in lookup_name * Introduce fill_info * Add Version annotations * Add subsys_vendor_id and subsys_id; add missing FILL consts * Drop SessionManager and use libpci to get GPU name * fix lint * Reintroduce GPU monitoring; introduce multiple GPU support foundament * Fix for Intel graphics * A bit better debug messages * Consider 3D cotroller as a GPU * Update Resources.vala * Add Intel GPU dummy class * Add proper vendor name to the GPU name * Display not supported label for Intel and Nvidia gpus * lint * Improve comment styling for hints and docs * Add comment * Remove obsolete code * Update src/Views/SystemView/SystemView.vala Co-authored-by: Ryo Nakano <ryonakaknock3@gmail.com> * Refactoring: atomize comments; put literals into consts * Remove space at the start of the file Co-authored-by: Ryo Nakano <ryonakaknock3@gmail.com> * Make it clear that Intel GPU needs implementation. * Add libpci-dev to readme * Use pci consts from Utils * Use switch-case for GPU detection * Use for loop for detecting GPU * make sysfs path in nvidia protected * Explicit setting properties without digging into the method in the interface * Compare GPU types instead of string properties * Update names of IGPU methods * Display pretty version of libpci * Use LIBPCI_* consts to display pretty version * Move PCI defines to independant source * Add Flags attribute to enum LookupMode --------- Co-authored-by: Ryo Nakano <ryonakaknock3@gmail.com>
1 parent 548254f commit 7a75779

File tree

15 files changed

+525
-136
lines changed

15 files changed

+525
-136
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
apt install -y libgala-dev libgee-0.8-dev libglib2.0-dev libgranite-dev libgtk-3-dev libhandy-1-dev \
3030
libdbus-glib-1-dev libwnck-3-dev libgtop2-dev libwingpanel-3.0-dev libudisks2-dev \
3131
libxnvctrl0 libxnvctrl-dev libcurl4-gnutls-dev libflatpak-dev libjson-glib-dev \
32-
liblivechart-1-dev \
32+
liblivechart-1-dev libpci-dev \
3333
meson valac sassc git
3434
- name: Build
3535
run: |

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ Monitor will be available from the Applications menu.
3838
If you plan to install WITH a wingpanel-indicator
3939

4040
```bash
41-
sudo apt install build-essential cmake sassc valac libgtk-3-dev libgee-0.8-dev libgranite-dev libgtop2-dev libwnck-3-dev libhandy-1-dev libudisks2-dev libjson-glib-dev libflatpak-dev libxnvctrl-dev liblivechart-1-dev libwingpanel-dev
41+
sudo apt install build-essential cmake sassc valac libgtk-3-dev libgee-0.8-dev libgranite-dev libgtop2-dev libwnck-3-dev libhandy-1-dev libudisks2-dev libjson-glib-dev libflatpak-dev libxnvctrl-dev liblivechart-1-dev libpci-dev libwingpanel-dev
4242
```
4343

4444
Alternatively, if you plan to install WITHOUT a wingpanel-indicator
4545

4646
```bash
47-
sudo apt install build-essential cmake sassc valac libgtk-3-dev libgee-0.8-dev libgranite-dev libgtop2-dev libwnck-3-dev libhandy-1-dev libudisks2-dev libjson-glib-dev libflatpak-dev libxnvctrl-dev liblivechart-1-dev
47+
sudo apt install build-essential cmake sassc valac libgtk-3-dev libgee-0.8-dev libgranite-dev libgtop2-dev libwnck-3-dev libhandy-1-dev libudisks2-dev libjson-glib-dev libflatpak-dev libxnvctrl-dev liblivechart-1-dev libpci-dev
4848
```
4949

5050

meson.build

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ libdir = join_paths(prefix, get_option('libdir'))
1212
icondir = join_paths(datadir, 'icons', 'hicolor')
1313
vapidir = meson.current_source_dir() / 'vapi/'
1414

15-
add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), language:'c')
15+
add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), language: 'c')
1616

1717
add_project_arguments(['--vapidir', vapidir], language: 'vala')
1818
add_project_arguments(['-DWNCK_I_KNOW_THIS_IS_UNSTABLE', '-w'], language: 'c')
@@ -38,35 +38,42 @@ app_dependencies = [
3838
dependency('flatpak'),
3939

4040
# FIXME Bump required version to >= 1.10.0 when GTK 4 porting
41-
dependency('livechart', version: '< 1.10.0', fallback: ['live-chart', 'livechart_dep']),
41+
dependency(
42+
'livechart',
43+
version: '< 1.10.0',
44+
fallback: ['live-chart', 'livechart_dep'],
45+
),
4246

43-
meson.get_compiler('c').find_library('m', required : false),
47+
meson.get_compiler('c').find_library('m', required: false),
4448
meson.get_compiler('vala').find_library('posix'),
45-
meson.get_compiler('c').find_library('XNVCtrl'),
4649
meson.get_compiler('c').find_library('X11'),
50+
51+
# PCI needs lower version limit '>= 3.8.0'
52+
meson.get_compiler('c').find_library('pci'),
53+
meson.get_compiler('vala').find_library('pci', dirs: vapidir),
54+
55+
meson.get_compiler('c').find_library('XNVCtrl'),
4756
meson.get_compiler('vala').find_library('libxnvctrl', dirs: vapidir),
4857
]
4958

50-
5159
config_data = configuration_data()
5260
config_data.set('GETTEXT_PACKAGE', meson.project_name())
5361

5462
subdir('data')
5563

5664
config_data.set('VCS_TAG', '@VCS_TAG@')
5765
project_config = vcs_tag(
58-
input: configure_file(
59-
input: 'src/Conf.vala.in',
60-
output: 'Conf.vala.in',
61-
configuration: config_data
62-
),
63-
output: 'Conf.vala',
64-
command: ['git', 'describe', '--tags', '--dirty']
66+
input: configure_file(
67+
input: 'src/Conf.vala.in',
68+
output: 'Conf.vala.in',
69+
configuration: config_data,
70+
),
71+
output: 'Conf.vala',
72+
command: ['git', 'describe', '--tags', '--dirty'],
6573
)
6674

6775
subdir('src')
6876

69-
7077
# Add in a post install script
7178
meson.add_install_script('meson/post_install.py')
7279

src/Monitor.vala

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace Monitor {
2323
Object (
2424
application_id: "io.elementary.monitor",
2525
flags : ApplicationFlags.FLAGS_NONE
26-
);
26+
);
2727
status_background = status_indicator;
2828
}
2929

@@ -70,21 +70,21 @@ namespace Monitor {
7070
if (!MonitorApp.settings.get_boolean ("indicator-state")) {
7171
MonitorApp.settings.set_boolean ("indicator-state", true);
7272
}
73-
// if (!MonitorApp.settings.get_boolean ("indicator-cpu-state")) {
74-
// MonitorApp.settings.set_boolean ("indicator-cpu-state", true);
75-
// }
76-
// if (!MonitorApp.settings.get_boolean ("indicator-memory-state")) {
77-
// MonitorApp.settings.set_boolean ("indicator-memory-state", true);
78-
// }
79-
// if (!MonitorApp.settings.get_boolean ("indicator-temperature-state")) {
80-
// MonitorApp.settings.set_boolean ("indicator-temperature-state", true);
81-
// }
82-
// if (!MonitorApp.settings.get_boolean ("indicator-network-upload-state")) {
83-
// MonitorApp.settings.set_boolean ("indicator-network-upload-state", false);
84-
// }
85-
// if (!MonitorApp.settings.get_boolean ("indicator-network-download-state")) {
86-
// MonitorApp.settings.set_boolean ("indicator-network-download-state", false);
87-
// }
73+
// if (!MonitorApp.settings.get_boolean ("indicator-cpu-state")) {
74+
// MonitorApp.settings.set_boolean ("indicator-cpu-state", true);
75+
// }
76+
// if (!MonitorApp.settings.get_boolean ("indicator-memory-state")) {
77+
// MonitorApp.settings.set_boolean ("indicator-memory-state", true);
78+
// }
79+
// if (!MonitorApp.settings.get_boolean ("indicator-temperature-state")) {
80+
// MonitorApp.settings.set_boolean ("indicator-temperature-state", true);
81+
// }
82+
// if (!MonitorApp.settings.get_boolean ("indicator-network-upload-state")) {
83+
// MonitorApp.settings.set_boolean ("indicator-network-upload-state", false);
84+
// }
85+
// if (!MonitorApp.settings.get_boolean ("indicator-network-download-state")) {
86+
// MonitorApp.settings.set_boolean ("indicator-network-download-state", false);
87+
// }
8888

8989
window.hide ();
9090
MonitorApp.settings.set_boolean ("background-state", true);
@@ -101,6 +101,13 @@ namespace Monitor {
101101
print (" Monitor %s \n", VCS_TAG);
102102
print ("\n");
103103

104+
print (
105+
"LibPCI ver: %d.%d.%d \n",
106+
PCIUtils.LIBPCI_MAJOR_VER,
107+
PCIUtils.LIBPCI_MINOR_VER,
108+
PCIUtils.LIBPCI_PATCH_VER
109+
);
110+
104111
// add command line options
105112
try {
106113
var opt_context = new OptionContext ("");

src/PCIUtils.vala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0-or-later
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*/
5+
6+
namespace Monitor.PCIUtils {
7+
const int LIBPCI_MAJOR_VER = (Pci.LIB_VERSION & 0xFF0000) >> 16;
8+
const int LIBPCI_MINOR_VER = (Pci.LIB_VERSION & 0x00FF00) >> 8;
9+
const int LIBPCI_PATCH_VER = (Pci.LIB_VERSION & 0x0000FF) >> 0;
10+
}

src/Resources/GPU/GPUAmd.vala

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
*/
55

66
public class Monitor.GPUAmd : IGPU, Object {
7-
public SessionManager ? session_manager { get; protected set; }
87

98
public Gee.HashMap<string, HwmonTemperature> hwmon_temperatures { get; set; }
109

1110
public string hwmon_module_name { get; set; }
1211

12+
public string name { get; set; }
13+
1314
public int percentage { get; protected set; }
1415

1516
public int memory_percentage { get; protected set; }
@@ -20,53 +21,33 @@ public class Monitor.GPUAmd : IGPU, Object {
2021

2122
public double temperature { get; protected set; }
2223

23-
private string path { get; set; }
24-
25-
construct {
26-
// session_manager = get_sessman ();
27-
// When path for GPU is created it can be assigned to card0 or card1
28-
// this a bit random. This should be removed when multiple GPU
29-
// support will be added.
30-
try {
31-
var dir = Dir.open ("/sys/class/drm/");
32-
string ? name;
33-
while ((name = dir.read_name ()) != null) {
34-
if (name == "card0") {
35-
path = "/sys/class/drm/card0/";
36-
debug ("GPU path: %s", path);
37-
38-
} else if (name == "card1") {
39-
path = "/sys/class/drm/card1/";
40-
debug ("GPU path: %s", path);
41-
42-
}
43-
}
44-
if (path == null) {
45-
debug ("Can't detect right path for AMD GPU");
46-
}
47-
} catch (Error e) {
48-
print ("Error: %s\n", e.message);
49-
}
24+
protected string sysfs_path { get; set; }
25+
26+
public GPUAmd (Pci.Access pci_access, Pci.Dev pci_device) {
27+
name = pci_parse_name (pci_access, pci_device);
28+
name = "AMD® " + name;
29+
30+
sysfs_path = pci_parse_sysfs_path (pci_access, pci_device);
5031
}
5132

5233
private void update_temperature () {
5334
temperature = double.parse (hwmon_temperatures.get ("edge").input) / 1000;
5435
}
5536

5637
private void update_memory_vram_used () {
57-
memory_vram_used = double.parse (get_sysfs_value (path + "device/mem_info_vram_used"));
38+
memory_vram_used = double.parse (get_sysfs_value (sysfs_path + "/mem_info_vram_used"));
5839
}
5940

6041
private void update_memory_vram_total () {
61-
memory_vram_total = double.parse (get_sysfs_value (path + "device/mem_info_vram_total"));
42+
memory_vram_total = double.parse (get_sysfs_value (sysfs_path + "/mem_info_vram_total"));
6243
}
6344

6445
private void update_memory_percentage () {
6546
memory_percentage = (int) (Math.round ((memory_vram_used / memory_vram_total) * 100));
6647
}
6748

6849
private void update_percentage () {
69-
percentage = int.parse (get_sysfs_value (path + "device/gpu_busy_percent"));
50+
percentage = int.parse (get_sysfs_value (sysfs_path + "/gpu_busy_percent"));
7051
}
7152

7253
public void update () {

src/Resources/GPU/GPUIntel.vala

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0-or-later
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*/
5+
6+
public class Monitor.GPUIntel : IGPU, Object {
7+
8+
public Gee.HashMap<string, HwmonTemperature> hwmon_temperatures { get; set; }
9+
10+
public string hwmon_module_name { get; set; }
11+
12+
public string name { get; set; }
13+
14+
public int percentage { get; protected set; }
15+
16+
public int memory_percentage { get; protected set; }
17+
18+
public double memory_vram_used { get; protected set; }
19+
20+
public double memory_vram_total { get; set; }
21+
22+
public double temperature { get; protected set; }
23+
24+
protected string sysfs_path { get; set; }
25+
26+
public GPUIntel (Pci.Access pci_access, Pci.Dev pci_device) {
27+
name = pci_parse_name (pci_access, pci_device);
28+
name = "Intel® " + name;
29+
30+
sysfs_path = pci_parse_sysfs_path (pci_access, pci_device);
31+
}
32+
33+
private void update_temperature () {
34+
// @TODO: Intel GPU temperature retrieval needs implementation.
35+
temperature = 0;
36+
}
37+
38+
private void update_memory_vram_used () {
39+
// @TODO: Intel GPU used VRAM retrieval needs implementation.
40+
memory_vram_used = 0;
41+
}
42+
43+
private void update_memory_vram_total () {
44+
// @TODO: Intel GPU total VRAM retrieval needs implementation.
45+
memory_vram_total = 0;
46+
}
47+
48+
private void update_memory_percentage () {
49+
// @TODO: Intel GPU memory percentage needs implementation.
50+
memory_percentage = 0;
51+
}
52+
53+
private void update_percentage () {
54+
// @TODO: Intel GPU usage percentage needs implementation.
55+
percentage = 0;
56+
}
57+
58+
public void update () {
59+
update_temperature ();
60+
update_memory_vram_used ();
61+
update_memory_vram_total ();
62+
update_memory_percentage ();
63+
update_percentage ();
64+
}
65+
66+
}

src/Resources/GPU/GPUNvidia.vala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
*/
55

66
public class Monitor.GPUNvidia : IGPU, Object {
7-
public SessionManager ? session_manager { get; protected set; }
87

98
public Gee.HashMap<string, HwmonTemperature> hwmon_temperatures { get; set; }
109

1110
public string hwmon_module_name { get; set; }
1211

12+
public string name { get; set; }
13+
1314
public int percentage { get; protected set; }
1415

1516
public int memory_percentage { get; protected set; }
@@ -22,6 +23,8 @@ public class Monitor.GPUNvidia : IGPU, Object {
2223

2324
public double temperature { get; protected set; }
2425

26+
protected string sysfs_path { get; set; }
27+
2528
public int nvidia_temperature = 0;
2629

2730
public int nvidia_memory_vram_used = 0;
@@ -46,8 +49,14 @@ public class Monitor.GPUNvidia : IGPU, Object {
4649

4750
public X.Display nvidia_display;
4851

52+
public GPUNvidia (Pci.Access pci_access, Pci.Dev pci_device) {
53+
name = pci_parse_name (pci_access, pci_device);
54+
name = "nVidia® " + name;
55+
56+
sysfs_path = pci_parse_sysfs_path (pci_access, pci_device);
57+
}
58+
4959
construct {
50-
// session_manager = get_sessman ();
5160
nvidia_display = new X.Display ();
5261
}
5362

src/Resources/GPU/IGPU.vala

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,12 @@
44
*/
55

66
public interface Monitor.IGPU : Object {
7-
public abstract SessionManager ? session_manager { get; public set; }
87

98
public abstract Gee.HashMap<string, HwmonTemperature> hwmon_temperatures { get; set; }
109

1110
public abstract string hwmon_module_name { get; protected set; }
1211

13-
public string name {
14-
owned get {
15-
return session_manager.renderer.split ("(", 2)[0];
16-
}
17-
}
12+
public abstract string name { get; protected set; }
1813

1914
public abstract int percentage { get; protected set; }
2015

@@ -26,6 +21,8 @@ public interface Monitor.IGPU : Object {
2621

2722
public abstract double temperature { get; protected set; }
2823

24+
protected abstract string sysfs_path { get; protected set; }
25+
2926
public abstract void update_temperature ();
3027

3128
public abstract void update_memory_vram_used ();
@@ -38,6 +35,19 @@ public interface Monitor.IGPU : Object {
3835

3936
public abstract void update ();
4037

38+
protected virtual string pci_parse_name (Pci.Access pci_access, Pci.Dev pci_device) {
39+
char namebuf[256];
40+
return pci_access.lookup_name (namebuf, Pci.LookupMode.DEVICE, pci_device.vendor_id, pci_device.device_id);
41+
}
42+
43+
protected virtual string pci_parse_sysfs_path (Pci.Access pci_access, Pci.Dev pci_device) {
44+
string pci_path_domain_bus = "%04x:%02x".printf (pci_device.domain_16, pci_device.bus);
45+
string pci_path_dev_func = "%02x.%d".printf (pci_device.dev, pci_device.func);
46+
string path = "/sys/class/pci_bus/%s/device/%s:%s".printf (pci_path_domain_bus, pci_path_domain_bus, pci_path_dev_func);
47+
debug ("GPU path: %s", path);
48+
49+
return path;
50+
}
4151

4252
public virtual string get_sysfs_value (string path) {
4353
string content;

0 commit comments

Comments
 (0)