Compare commits

...

101 Commits

Author SHA1 Message Date
Carter Li bcc8f6d0b8 Merge pull request #1665 from fastfetch-cli/dev
Release v2.40.1
2025-04-04 00:45:57 +08:00
Carter Li 90ca6ee3cd Release: v2.40.1 2025-04-04 00:27:11 +08:00
李通洲 b679185c87 Logo: don't try to find files named - 2025-04-03 22:42:15 +08:00
李通洲 6bbed12083 IO: remove fast path of ffPathExists, which causes too many problems
Fix #1662
2025-04-03 22:38:05 +08:00
李通洲 f04851891e TPM (macOS): fix compiling error on old system
Fix #1659
2025-04-03 16:21:02 +08:00
Carter Li f94d9ca3bd Packaging: update debian stuff [ci skip] 2025-04-03 08:49:01 +08:00
Carter Li f833dda3b9 Merge pull request #1656 from fastfetch-cli/dev
Release: v2.40.0
2025-04-03 08:41:21 +08:00
李通洲 ceecb39bc5 WM (Linux): fix https://github.com/fastfetch-cli/fastfetch/issues/1657#issuecomment-2772749780 2025-04-02 23:22:34 +08:00
Carter Li c957ca7230 WM (Linux): query Hyprland version from hyprland dev header 2025-04-02 19:15:09 +08:00
李通洲 5dfd2676c2 Binary: add comments 2025-04-02 10:35:42 +08:00
李通洲 d650f67ece WM (Linux): correctly fall back to calling wm --version if ffBinaryExtractStrings fails
Fix #1657
2025-04-02 10:35:42 +08:00
李通洲 760e82913a CI: remove Dragonfly BSD
Ref: #1632
2025-04-02 08:53:51 +08:00
Carter Li e64a44a3e6 WM (Linux): fix (?) Hyprland version detection 2025-04-02 00:12:21 +08:00
李通洲 be9cf00b05 Release: v2.40.0 2025-04-01 20:20:06 +08:00
李通洲 52fdabeb2e Uptime: round seconds to the nearest minute
To match the behavior of `uptime` command
2025-04-01 19:40:15 +08:00
李通洲 846f4c003e DisplayServer (Linux): silence compiler errors 2025-04-01 19:15:21 +08:00
李通洲 dc5f2ac577 Util (Windows): fix mem leaks 2025-04-01 19:15:20 +08:00
李通洲 663650cb61 Util (Windows): fix possible errors in Unicode.c 2025-04-01 19:15:20 +08:00
李通洲 45aecae221 Util (Linux): fix executable file check 2025-04-01 19:02:35 +08:00
李通洲 3d3669ae3a FFlist: use uint8_t instead of char to store raw data 2025-04-01 19:02:35 +08:00
李通洲 ac2aba0faf Threading: fix timeout calcuation 2025-04-01 11:07:28 +08:00
李通洲 d0ca944b9c Netif (Linux): support default route detection for ipv6 2025-04-01 10:48:30 +08:00
李通洲 3d7c631abd Wifi: fix code smells 2025-04-01 10:48:04 +08:00
Carter Li abe78823b6 PhysicalMemory (Linux): code refactor 2025-04-01 09:43:37 +08:00
李通洲 7e03b03cb7 Users (Linux): support IPv6 client addr 2025-04-01 09:43:37 +08:00
李通洲 27fe997dc3 Users (Windows): support IPv6 client IP 2025-03-31 23:41:54 +08:00
李通洲 fe46159e40 Uptime (NetBSD): fix boot time calcuation 2025-03-31 23:40:35 +08:00
李通洲 031aa985f1 TPM (macOS): add support 2025-03-31 23:40:01 +08:00
李通洲 07c61f70d9 InitSystem (Haiku): set pid=0 if fails to detect init pid 2025-03-31 23:39:25 +08:00
李通洲 71b05d2594 Doc: update changelog [ci skip] 2025-03-31 21:43:43 +08:00
李通洲 98665d1b82 Revert "CI: build in debug mode"
This reverts commit e05ac797cc.
2025-03-31 19:08:02 +08:00
李通洲 da0eedf888 Swap (Windows): support multiple paging files 2025-03-31 18:56:03 +08:00
李通洲 1133cb619b Swap (OpenBSD): fix mem leaks 2025-03-31 18:56:03 +08:00
李通洲 a091d209cf Swap: fix code smells 2025-03-31 18:44:41 +08:00
李通洲 47c658815b Sound: fix typo and mem leaks 2025-03-31 16:38:58 +08:00
李通洲 b0d0c74073 Doc: update changelog [ci skip] 2025-03-31 10:59:55 +08:00
李通洲 9535b4d480 Chore (Windows): silense compiler warnings 2025-03-31 10:48:14 +08:00
Carter Li c64cbf57d8 fastfetch: load config from fastfetch binary path
Fix #1649
2025-03-31 10:48:09 +08:00
komaru.yml d11235bbe2 Logo (Ascii): Change Nexa Linux logo (#1653) 2025-03-31 08:51:48 +08:00
Angel Gustavo Lopez 3054c6618e Logo (Builtin): change name of Xray-OS 2025-03-30 21:48:47 +08:00
李通洲 f34d51dddc Terminal (Windows): fix file version detection 2025-03-30 16:38:54 +08:00
李通洲 e05ac797cc CI: build in debug mode 2025-03-29 20:42:42 +08:00
李通洲 187059deef GPU (Windows): fix max frequency detection for AMD ODN 2025-03-29 20:42:42 +08:00
李通洲 5c9f184314 GPU (Windows): use ODN as OD7; fix ADL2_Overdrive8_Current_Setting_Get call and some other bugs 2025-03-29 17:03:56 +08:00
李通洲 49725c2cc6 Doc: update changelog [ci skip] 2025-03-28 16:32:13 +08:00
李通洲 eec9a26952 TerminalFont (Windows): support Warp Terminal 2025-03-28 15:26:30 +08:00
李通洲 88d616e978 GPU (Windows): try more OD funcs; add more verbose logs 2025-03-28 14:57:43 +08:00
李通洲 4fccad5d10 Disk (macOS): silense compiler warnings 2025-03-28 14:57:43 +08:00
李通洲 ec18363f51 DNS (macOS): detect DNS entries by SystemConfiguration 2025-03-28 10:49:20 +08:00
Carter Li b87a36785b DNS (Linux): add systemd-resolved support; add verbose logs 2025-03-28 09:50:33 +08:00
李通洲 1d7b212d8d Media: fix code smells 2025-03-27 16:44:14 +08:00
李通洲 4b6f2a9efa Gamepad / Keyboard / Mouse (FreeBSD): break detection earlier 2025-03-27 14:40:33 +08:00
李通洲 bdaf303da4 Keyboard (FreeBSD): fall back to KDGKBINFO if usbhid fails 2025-03-27 14:15:25 +08:00
李通洲 3fb773eedd Gamepad / Mouse / Keyboard (FreeBSD): fix memleaks 2025-03-27 14:08:01 +08:00
李通洲 e73647973d Host (Windows): fix build on WoA 2025-03-27 09:38:32 +08:00
李通洲 d2b3a075b2 GPU (Windows): actually use correct OD fns for recent AMD GPUs 2025-03-27 09:29:21 +08:00
李通洲 f139148745 GPU (Windows): add OverdriveN functions for AMD 2025-03-26 23:55:23 +08:00
Carter Li e2ec2c695c GPU (Windows): fix ADL2_Adapter_AdapterInfoX3_Get result test 2025-03-26 22:22:44 +08:00
李通洲 ba4ec47a8c GPU (Windows): added verbose logs 2025-03-26 21:10:51 +08:00
李通洲 de5ef3842c Global: fix code smells 2025-03-26 16:44:52 +08:00
李通洲 1129ed9be4 Host (macOS): add new models; fix an invalid model ID 2025-03-26 16:27:15 +08:00
李通洲 0d4f1544c7 Chore: fix code smell 2025-03-26 14:42:55 +08:00
李通洲 e68a9476b5 Disk (SunOS): remove creation time detection support
ctim is `Timestamp of last file status change`, not creation time
2025-03-26 11:02:57 +08:00
李通洲 17556c7a95 Util/debug: add missing #pragma once 2025-03-26 09:47:33 +08:00
李通洲 eca9f626a5 Separator: fix outputColor doesn't work when length is set
Fix #1644
2025-03-25 23:22:25 +08:00
李通洲 7562e05123 Chore: fix a lot code smell 2025-03-25 22:08:50 +08:00
李通洲 bf17f2b4b9 LocalIP: change {name} to {ifname} in --localip-key-format for consistancy
Breaking change.

Fix #1639
2025-03-25 22:08:50 +08:00
李通洲 88e193e9fd GPU: fix code smell 2025-03-25 22:08:50 +08:00
李通洲 e474a47fad GPU (General): fix GPU device type detection 2025-03-25 22:08:50 +08:00
李通洲 c77fb71a69 Battery (NetBSD): report remaining time 2025-03-25 22:08:49 +08:00
李通洲 48dd5976e1 Battery (Linux): fix critical state detection 2025-03-25 22:08:49 +08:00
李通洲 093f7e438b Battery (macOS): fix manufacture date detection 2025-03-25 22:08:49 +08:00
李通洲 0a0c1745b3 GPU (macOS): fix code smell 2025-03-25 22:08:49 +08:00
Techflash 7b5dc58140 CPU (Linux): fix CPU detection on some PPC platforms (#1640)
On some PowerPC devices (notably the Nintendo Wii and Nintendo Wii U),
fastfetch detects the CPU incorrectly.  It goes down the code path
of 'detectSocName()', and actually matches the model of the device
itself... as the CPU model name.  This is obviously incorrect, and
leads to reporting such as 'CPU: wii'.  Disable this code path
alltogether on PPC to prevent this, and just let it pull from cpuinfo.
This lets it have correct CPU reporting, such as on the Wii, giving
'CPU: 750CL @ 0.73GHz'.
2025-03-25 03:05:23 -05:00
李通洲 8681d2f74a GPU (Windows): fix code smells 2025-03-25 00:14:03 +08:00
李通洲 2b20ed873c GPU: update JSON result structure; fix segfault and memleaks 2025-03-24 22:56:00 +08:00
李通洲 ae3c15b7fd GPU (Windows): support VMEM type detection via nvapi
Ref #993
2025-03-24 21:43:09 +08:00
李通洲 8dafd8f300 GPU (Windows): rewrite implementation for AMD GPUs using ADL SDK
Detect more information including memory type
2025-03-24 21:43:09 +08:00
李通洲 c9a1765f29 GPU (Windows): support memory type detection for Intel dGPUs 2025-03-24 15:22:34 +08:00
李通洲 cc246ea239 GPU: prepare for memory type & shared memory usage detection 2025-03-24 15:21:14 +08:00
李通洲 0ae5fceb07 GPU (Windows): add display-library for future use 2025-03-23 23:53:01 +08:00
李通洲 6dd18050be IO: don't suppress IO in debug mode 2025-03-23 21:56:32 +08:00
李通洲 9eca6e0b48 Bootmgr: report boot order 2025-03-23 21:30:53 +08:00
李通洲 4d58d1be66 Smbios (OpenBSD): add comments for UEFI systems [ci skip] 2025-03-23 20:30:31 +08:00
Carter Li 6694388969 Logo (Builtin): fix opensuse-tumbleweed_small
Fix #1636
2025-03-23 17:22:02 +08:00
Carter Li f7058cd125 Wifi (Linux): add verbose logs 2025-03-23 17:19:43 +08:00
李通洲 80033b656f Wifi (DragonFly): fix building 2025-03-23 12:23:30 +08:00
李通洲 1c719fa743 Bootmgr (BSD): add support for OpenBSD and NetBSD 2025-03-23 12:08:15 +08:00
李通洲 a9f5722fd9 BIOS (OpenBSD): check bios type 2025-03-23 11:34:02 +08:00
李通洲 0952d7917f Smbios: add verbose debug logs 2025-03-23 11:19:49 +08:00
李通洲 a3f50f32bf Smbios (OpenBSD): add support for legency BIOS 2025-03-23 11:19:49 +08:00
李通洲 ab1bfffbd4 util/debug: add missing headers 2025-03-23 10:52:08 +08:00
李通洲 41d6187f11 Wifi (FreeBSD): use ioctl to improve performance
And support more features
2025-03-23 09:46:44 +08:00
Techflash d4b175b146 Logo (Builtin): Change WiiLinuxNgx to more generic name (#1633)
Wii-Linux-Ngx is no longer the most up to date version of Linux for the Wii.
This change retains the original name for compatibility sake, and because
Neagix's version does indeed still exist.  It moves the ASCII art to a more
generic file path, and introduces 2 new aliases for it: Wii-Linux, and WiiLinux.
2025-03-21 17:21:54 +08:00
Carter Li 8905962389 Packaging: update debian stuff [ci skip] 2025-03-21 11:03:29 +08:00
李通洲 d9d34ccbbb Terminal (macOS): fix Warp Terminal pid detection 2025-03-21 10:08:26 +08:00
李通洲 d21048c165 Presets: update examples/{24,26} [ci skip] 2025-03-21 09:43:06 +08:00
Carter Li 8b0c32a35f Merge pull request #1631 from fastfetch-cli/dev
Release v2.39.1
2025-03-20 23:24:14 +08:00
李通洲 db269d29e8 Release: v2.39.1 2025-03-20 23:16:13 +08:00
李通洲 f9f628eae6 Networking: request HTTP/1.0, as we don't support chunked response
Fix #1629
2025-03-20 23:08:41 +08:00
Carter Li 92e9fbf2eb Packaging: update debian stuff [ci skip] 2025-03-20 10:41:30 +08:00
141 changed files with 9648 additions and 996 deletions
-39
View File
@@ -520,41 +520,6 @@ jobs:
name: fastfetch-freebsd-amd64
path: ./fastfetch-*.*
dragonfly-amd64:
name: DragonFly-amd64
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: run VM
uses: vmactions/dragonflybsd-vm@v1
with:
usesh: yes
prepare: |
uname -a
pkg update
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa libelf
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-dragonfly-amd64
path: ./fastfetch-*.*
openbsd-amd64:
name: OpenBSD-amd64
runs-on: ubuntu-latest
@@ -659,9 +624,6 @@ jobs:
- name: copy necessary dlls
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
- name: download amd_ags
run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x64.dll
- name: list features
run: ./fastfetch --list-features
@@ -709,7 +671,6 @@ jobs:
- freebsd-amd64
- openbsd-amd64
- netbsd-amd64
- dragonfly-amd64
- sunos-amd64
- windows-amd64
permissions:
+54 -1
View File
@@ -1,3 +1,56 @@
# 2.40.1
Bugfixes:
* Fix compiling error on old intel platform (TPM, macOS)
* Fix `--file-raw -` no longer working (Logo, #1659)
* Regression of v2.40.0
# 2.40.0
Changes:
* In `key-format` of `LocalIP` module, `{name}` has been renamed to `{ifname}` for consistency (LocalIP, #1639)
Features:
* Support Warp Terminal font detection (TerminalFont, Windows)
* Support more AMD GPU information using ADL SDK, including memory type detection (GPU, Windows)
* Support Intel dGPU memory type detection (GPU, Windows)
* Support Nvidia VMEM type detection via NVAPI (GPU, Windows, #993)
* Support Boot manager detection for OpenBSD and NetBSD (Bootmgr, OpenBSD / NetBSD)
* Use `SystemConfiguration` for DNS entries detection (DNS, macOS)
* Add `systemd-resolved` support for DNS module (DNS, Linux, #1646)
* Improve performance and accuracy of Wifi detection on FreeBSD using ioctl (Wifi, FreeBSD)
* Support remaining time reporting for batteries on NetBSD (Battery, NetBSD)
* Add new Mac models support (Host, macOS)
* Load config from fastfetch binary path with `--config` option (#1649)
* Support TPM detection on macOS (TPM, macOS)
* Support IPv6 client address report (Users, Linux / Windows)
* Support default route detection for IPv6 (LocalIP, Linux)
* Round seconds to the nearest minute to match the behavior of `uptime` command (Uptime)
Bugfixes:
* Fix `outputColor` not working when `length` is set in Separator module (#1644)
* Fix CPU detection on PowerPC platforms (#1640, CPU, Linux)
* Fix battery manufacture date detection (Battery, macOS)
* Fix battery critical state detection (Battery, Linux)
* Fix Warp Terminal PID detection (Terminal, macOS)
* Remove disk creation time detection support on SunOS as ctim is file status change timestamp, not creation time (Disk, SunOS)
* Fall back to KDGKBINFO if `usbhid` fails (Keyboard, FreeBSD)
* Fix multiple paging file support (Swap, Windows)
* Fix memleaks, code smells in multiple modules
* Fix boot time calculation on NetBSD (Uptime, NetBSD)
* Temporarily fix Hyprland version detection (WM, Linux, #1657)
Logo:
* Fix opensuse-tumbleweed_small (#1636)
* Change WiiLinuxNgx to more generic name with aliases Wii-Linux and WiiLinux (#1633)
* Change name of Xray-OS to Ada (#1651)
* Change Nexa Linux logo (#1653)
# 2.39.1
Bugfixes:
* Fix a regression that PublicIP detection fails randomly (PublicIP, #1629)
# 2.39.0
Changes:
@@ -331,7 +384,7 @@ Features:
* Support tilix version detection (Terminal, Linux)
* Support percent type config in module level. Example:
```json
```jsonc
{
"type": "memory",
"percent": {
+13 -11
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.39.0
VERSION 2.40.1
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -708,7 +708,6 @@ elseif(FreeBSD)
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_bsd.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
@@ -720,10 +719,12 @@ elseif(FreeBSD)
if(DragonFly)
list(APPEND LIBFASTFETCH_SRC
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/wifi/wifi_nosupport.c
)
else()
list(APPEND LIBFASTFETCH_SRC
src/detection/bluetooth/bluetooth_bsd.c
src/detection/wifi/wifi_bsd.c
)
endif()
elseif(NetBSD)
@@ -739,7 +740,7 @@ elseif(NetBSD)
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_nbsd.c
src/detection/bootmgr/bootmgr_nosupport.c
src/detection/bootmgr/bootmgr_bsd.c
src/detection/brightness/brightness_nbsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_nbsd.c
@@ -817,22 +818,22 @@ elseif(OpenBSD)
src/common/processing_linux.c
src/common/sysctl.c
src/detection/battery/battery_obsd.c
src/detection/bios/bios_nosupport.c
src/detection/bios/bios_windows.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_nosupport.c
src/detection/bootmgr/bootmgr_nosupport.c
src/detection/board/board_windows.c
src/detection/bootmgr/bootmgr_bsd.c
src/detection/brightness/brightness_obsd.c
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_nosupport.c
src/detection/chassis/chassis_windows.c
src/detection/cpu/cpu_obsd.c
src/detection/cpucache/cpucache_nosupport.c
src/detection/cpucache/cpucache_shared.c
src/detection/cpuusage/cpuusage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/disk/disk_bsd.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_nosupport.c
src/detection/physicalmemory/physicalmemory_nosupport.c
src/detection/physicalmemory/physicalmemory_linux.c
src/detection/diskio/diskio_obsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/drm.c
@@ -889,6 +890,7 @@ elseif(OpenBSD)
src/detection/zpool/zpool_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
src/util/smbiosHelper.c
)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
@@ -911,7 +913,7 @@ elseif(APPLE)
src/detection/cpuusage/cpuusage_apple.c
src/detection/cursor/cursor_apple.m
src/detection/disk/disk_bsd.c
src/detection/dns/dns_linux.c
src/detection/dns/dns_apple.c
src/detection/physicaldisk/physicaldisk_apple.c
src/detection/physicalmemory/physicalmemory_apple.m
src/detection/diskio/diskio_apple.c
@@ -945,7 +947,7 @@ elseif(APPLE)
src/detection/terminalshell/terminalshell_linux.c
src/detection/terminalsize/terminalsize_linux.c
src/detection/theme/theme_nosupport.c
src/detection/tpm/tpm_nosupport.c
src/detection/tpm/tpm_apple.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.m
+24
View File
@@ -1,3 +1,27 @@
fastfetch (2.40.0) jammy; urgency=medium
* Update to 2.40.0
-- Carter Li <zhangsongcui@live.cn> Thu, 03 Apr 2025 08:46:54 +0800
fastfetch (2.39.1) jammy; urgency=medium
* Update to 2.39.1
-- Carter Li <zhangsongcui@live.cn> Fri, 21 Mar 2025 11:02:19 +0800
fastfetch (2.39.0ubuntu1) jammy; urgency=medium
* Remove unwanted debugging code
-- Carter Li <zhangsongcui@live.cn> Thu, 20 Mar 2025 10:39:22 +0800
fastfetch (2.39.0) jammy; urgency=medium
* Update to 2.39.0
-- Carter Li <zhangsongcui@live.cn> Thu, 20 Mar 2025 10:35:18 +0800
fastfetch (2.38.0) jammy; urgency=medium
* Update to 2.38.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.38.0_source.buildinfo universe/utils optional
fastfetch_2.40.0_source.buildinfo universe/utils optional
+11 -11
View File
@@ -28,38 +28,38 @@
{
"type": "title",
"key": "{#90}{$1}│ {#92}User {#90}│",
"format": "{$2}{$3}{user-name} {#2}[{home-dir}]"
"format": "{$2}{$3}{user-name} {#2}[{home-dir}]"
},
{
"type": "users",
"key": "{#90}{$1}│ {#92}Users {#90}│",
"myselfOnly": false,
"format": "{$2}{$3}{1}@{host-name}{/host-name}localhost{/}{?client-ip} {#2}[IP:{client-ip}]{?} {#2}[Login time: {login-time}]",
"format": "{$2}{$3}{1}@{host-name}{/host-name}localhost{/}{?client-ip} {#2}[IP:{client-ip}]{?} [Login time: {login-time}]"
},
{
"type": "datetime",
"key": "{#90}{$1}│ {#92}Datetime {#90}│",
"format": "{$2}{$3}{year}-{month-pretty}-{day-in-month} {hour-pretty}:{minute-pretty}:{second-pretty} {#2}{weekday} {#2}[W{week}] {#2}[UTC{offset-from-utc}]"
"format": "{$2}{$3}{year}-{month-pretty}-{day-in-month} {hour-pretty}:{minute-pretty}:{second-pretty} [{weekday}] [W{week}] [UTC{offset-from-utc}]"
},
{
"type": "title",
"key": "{#90}{$1}│ {#93}Host: {#90}│",
"format": "{$2}{$3}{#1}{#36}{host-name}"
"key": "{#90}{$1}│ {#93}Host {#90}│",
"format": "{$2}{$3}{host-name}"
},
{
"type": "host",
"key": "{#90}{$1}│ {#93}Machine {#90}│",
"format": "{$2}{$3}{name} {#2}{version}"
"format": "{$2}{$3}{name} {#2}{version}"
},
{
"type": "os",
"key": "{#90}{$1}│ {#93}OS {#90}│",
"format": "{$2}{$3}{pretty-name} {codename} {#2}[v{version}] {#2}[{arch}]"
"format": "{$2}{$3}{?pretty-name}{pretty-name}{?}{/pretty-name}{name}{/} {codename} {#2}[v{version}] [{arch}]"
},
{
"type": "kernel",
"key": "{#90}{$1}│ {#93}Kernel {#90}│",
"format": "{$2}{$3}{sysname} {#2}[v{release}]"
"format": "{$2}{$3}{sysname} {#2}[v{release}]"
},
{
"type": "uptime",
@@ -71,14 +71,14 @@
"key": "{#90}{$1}│ {#91}CPU {#90}│",
"showPeCoreCount": true,
"temp": true,
"format": "{$2}{$3}{name} {#2}[C:{core-types}] {#2}[{freq-max}]"
"format": "{$2}{$3}{name} {#2}[C:{core-types}] [{freq-max}]"
},
{
"type": "gpu",
"key": "{#90}{$1}│ {#91}GPU {#90}│",
"detectionMethod": "auto",
"driverSpecific": true,
"format": "{$2}{$3}{name} {#2}[C:{core-count}] {#2}[{type}]"
"format": "{$2}{$3}{name} {#2}[C:{core-count}]{?frequency} [{frequency}]{?} [{type}]"
},
{
"type": "memory",
@@ -98,7 +98,7 @@
{
"type": "terminal",
"key": "{#90}{$1}│ {#95}Terminal {#90}│",
"format": "{$2}{$3}{pretty-name} {#2}[{version}] [PID:{pid}]"
"format": "{$2}{$3}{pretty-name} {#2}[{version}] [PID:{pid}]"
},
{
"type": "terminalfont",
+165
View File
@@ -0,0 +1,165 @@
// Modified from: 24.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"padding": {
"top": 2
}
},
"display": {
"separator": "",
"constants": [
// CONSTANT {$1} - VERTICAL BARS AT START AND 75th CHARACTERS FORWARD AND BACKWARD
"\u001b[90m│ │\u001b[60D\u001b[39m"
]
},
"modules": [
// CUSTOM - Top UI bar
{
"type": "custom",
"key": "{#90}╭ Keys ───────╮",
"format": "{#90}╭ Values ────────────────────────────────────────────────────╮",
},
{
"type": "title",
"key": "{#90}│ {#92}User {#90}│",
"format": "{$1}{user-name} {#2}[{home-dir}]"
},
{
"type": "users",
"key": "{#90}│ {#92}Users {#90}│",
"myselfOnly": false,
"format": "{$1}{1}@{host-name}{/host-name}localhost{/}{?client-ip} {#2}[IP:{client-ip}]{?} [Login time: {login-time}]"
},
{
"type": "datetime",
"key": "{#90}│ {#92}Datetime {#90}│",
"format": "{$1}{year}-{month-pretty}-{day-in-month} {hour-pretty}:{minute-pretty}:{second-pretty} {#2}[{weekday}] [W{week}] [UTC{offset-from-utc}]"
},
{
"type": "title",
"key": "{#90}│ {#93}Host {#90}│",
"format": "{$1}{host-name}"
},
{
"type": "host",
"key": "{#90}│ {#93}Machine {#90}│",
"format": "{$1}{name} {#2}{version}"
},
{
"type": "os",
"key": "{#90}│ {#93}OS {#90}│",
"format": "{$1}{?pretty-name}{pretty-name}{?}{/pretty-name}{name}{/} {codename} {#2}[v{version}] [{arch}]"
},
{
"type": "kernel",
"key": "{#90}│ {#93}Kernel {#90}│",
"format": "{$1}{sysname} {#2}[v{release}]"
},
{
"type": "uptime",
"key": "{#90}│ {#93}Uptime {#90}│",
"format": "{$1}{?days}{days} Days + {?}{hours}:{minutes}:{seconds}"
},
{
"type": "cpu",
"key": "{#90}│ {#91}CPU {#90}│",
"showPeCoreCount": true,
"temp": true,
"format": "{$1}{name} {#2}[C:{core-types}] [{freq-max}]"
},
{
"type": "gpu",
"key": "{#90}│ {#91}GPU {#90}│",
"detectionMethod": "auto",
"driverSpecific": true,
"format": "{$1}{name} {#2}[C:{core-count}]{?frequency} [{frequency}]{?} {#2}[{type}]"
},
{
"type": "memory",
"key": "{#90}│ {#91}Memory {#90}│",
"format": "{$1}{used} / {total} ({percentage})"
},
{
"type": "disk",
"key": "{#90}│ {#91}Disk {#90}│",
"format": "{$1}{size-used} / {size-total} ({size-percentage})"
},
{
"type": "poweradapter",
"key": "{#90}│ {#91}Power {#90}│",
"format": "{$1}{name}"
},
{
"type": "terminal",
"key": "{#90}│ {#95}Terminal {#90}│",
"format": "{$1}{pretty-name} {#2}[{version}] [PID:{pid}]"
},
{
"type": "terminalfont",
"key": "{#90}│ {#95}Font {#90}│",
"format": "{$1}{name} {#2}[{size}]"
},
{
"type": "shell",
"key": "{#90}│ {#95}Shell {#90}│",
"format": "{$1}{pretty-name} {#2}[v{version}] [PID:{pid}]"
},
{
// localip IPv4
"type": "localip",
"key": "{#90}│ {#94}Local IPv4 {#90}│",
"showPrefixLen": true,
"showIpv4": true,
"showIpv6": false,
"showMtu": true,
"format": "{$1}{ifname}: {ipv4} {#2}[MTU:{mtu}]"
},
{
// localip IPv6
"type": "localip",
"key": "{#90}│ {#94}Local IPv6 {#90}│",
"showPrefixLen": true,
"showIpv4": false,
"showIpv6": true,
"showMtu": true,
"format": "{$1}{ifname}: {ipv6} {#2}[MTU:{mtu}]"
},
{
"type": "publicip",
"key": "{#90}│ {#94}Public IPv4 {#90}│",
"ipv6": false,
"format": "{$1}{ip} {#2}[{location}]"
},
{
"type": "publicip",
"key": "{#90}│ {#94}Public IPv6 {#90}│",
"ipv6": true,
"format": "{$1}{ip} {#2}[{location}]"
},
// CUSTOM - Button UI bar
{
"type": "custom",
"key": "{#90}╰─────────────╯",
"format": "{#90}╰────────────────────────────────────────────────────────────╯",
},
"break",
{
"type": "custom",
"key": " ",
"format": "{#90}╭ Colors ───────────────────────────────────────────────────────────────────╮",
},
{
"type": "custom",
"format": "{#90}│ {#40} {#41} {#42} {#43} {#44} {#45} {#46} {#47} {#} {#90}│",
},
{
"type": "custom",
"format": "{#90}│ {#100} {#101} {#102} {#103} {#104} {#105} {#106} {#107} {#} {#90}│",
},
{
"type": "custom",
"format": "{#90}╰───────────────────────────────────────────────────────────────────────────╯",
},
]
}
-383
View File
@@ -1,383 +0,0 @@
//
// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
/// \file
/// \mainpage
/// AGS Library Overview
/// --------------------
/// This document provides an overview of the AGS (AMD GPU Services) library. The AGS library provides software developers with the ability to query
/// AMD GPU software and hardware state information that is not normally available through standard operating systems or graphic APIs.
///
/// The latest version of the API is publicly hosted here: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/.
/// It is also worth checking http://gpuopen.com/gaming-product/amd-gpu-services-ags-library/ for any updates and articles on AGS.
/// \internal
/// Online documentation is publicly hosted here: http://gpuopen-librariesandsdks.github.io/ags/
/// \endinternal
///
/// ---------------------------------------
/// What's new in AGS 6.2 since version 6.1
/// ---------------------------------------
/// AGS 6.2 includes the following updates:
/// * Shader clock intrinsics
/// * Minor improvements and fixes
///
/// ---------------------------------------
/// What's new in AGS 6.1 since version 6.0
/// ---------------------------------------
/// AGS 6.1 includes the following updates:
/// * RDNA3 detection
///
/// ---------------------------------------
/// What's new in AGS 6.0 since version 5.4.2
/// ---------------------------------------
/// AGS 6.0 includes the following updates:
/// * DX12 ray tracing hit token for RDNA2 hardware.
/// * Shader intrinsic that exposes ReadLaneAt in DX12.
/// * Shader intrinsics that expose explicit float conversions in DX12.
/// * Refactored and revised API to minimize user error.
/// * Added agsGetVersionNumber.
/// * Detection for external GPUs.
/// * Detection of RDNA2 architecture.
/// * Grouped the more established intrinsics together into per year support.
/// * Function pointer typedefs for the API
///
/// ---------------------------------------
/// What's new in AGS 5.4.2 since version 5.4.1
/// ---------------------------------------
/// AGS 5.4.2 includes the following updates:
/// * sharedMemoryInBytes has been reinstated.
/// * Clock speed returned for APUs.
///
/// ---------------------------------------
/// What's new in AGS 5.4.1 since version 5.4.0
/// ---------------------------------------
/// AGS 5.4.1 includes the following updates:
/// * AsicFamily_Count to help with code maintenance.
/// * Visual Studio 2019 support.
/// * x86 support
/// * BaseInstance and BaseVertex intrinsics along with corresponding caps bits.
/// * GetWaveSize intrinsic along with corresponding caps bits.
///
/// ---------------------------------------
/// What's new in AGS 5.4 since version 5.3
/// ---------------------------------------
/// AGS 5.4 includes the following updates:
/// * A more detailed description of the GPU architecture, now including RDNA GPUs.
/// * Radeon 7 core and memory speeds returned.
/// * Draw index and Atomic U64 intrinsics for both DX11 and DX12.
///
/// ---------------------------------------
/// What's new in AGS 5.3 since version 5.2
/// ---------------------------------------
/// AGS 5.3 includes the following updates:
/// * DX11 deferred context support for Multi Draw Indirect and UAV Overlap extensions.
/// * A Radeon Software Version helper to determine whether the installed driver meets your game's minimum driver version requirements.
/// * Freesync HDR Gamma 2.2 mode which uses a 1010102 swapchain and can be considered as an alternative to using the 64 bit swapchain required for Freesync HDR scRGB.
///
/// Using the AGS library
/// ---------------------
/// It is recommended to take a look at the source code for the samples that come with the AGS SDK:
/// * AGSSample
/// * CrossfireSample
/// * EyefinitySample
/// The AGSSample application is the simplest of the three examples and demonstrates the code required to initialize AGS and use it to query the GPU and Eyefinity state.
/// The CrossfireSample application demonstrates the use of the new API to transfer resources on GPUs in Crossfire mode. Lastly, the EyefinitySample application provides a more
/// extensive example of Eyefinity setup than the basic example provided in AGSSample.
/// There are other samples on Github that demonstrate the DirectX shader extensions, such as the Barycentrics11 and Barycentrics12 samples.
///
/// To add AGS support to an existing project, follow these steps:
/// * Link your project against the correct import library. Choose from either the 32 bit or 64 bit version.
/// * Copy the AGS dll into the same directory as your game executable.
/// * Include the amd_ags.h header file from your source code.
/// * Include the AGS hlsl files if you are using the shader intrinsics.
/// * Declare a pointer to an AGSContext and make this available for all subsequent calls to AGS.
/// * On game initialization, call \ref agsInitialize passing in the address of the context. On success, this function will return a valid context pointer.
///
/// Don't forget to cleanup AGS by calling \ref agsDeInitialize when the app exits, after the device has been destroyed.
#ifndef AMD_AGS_H
#define AMD_AGS_H
#define AMD_AGS_VERSION_MAJOR 6 ///< AGS major version
#define AMD_AGS_VERSION_MINOR 2 ///< AGS minor version
#define AMD_AGS_VERSION_PATCH 0 ///< AGS patch version
#ifdef __cplusplus
extern "C" {
#endif
/// \defgroup Defines AGS defines
/// @{
#if defined (AGS_GCC)
#define AMD_AGS_API
#else
#define AMD_AGS_API __declspec(dllexport) ///< AGS exported functions
#endif
#define AGS_MAKE_VERSION( major, minor, patch ) ( ( major << 22 ) | ( minor << 12 ) | patch ) ///< Macro to create the app and engine versions for the fields in \ref AGSDX12ExtensionParams and \ref AGSDX11ExtensionParams and the Radeon Software Version
#define AGS_UNSPECIFIED_VERSION 0xFFFFAD00 ///< Use this to specify no version
#define AGS_CURRENT_VERSION AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ) ///< Macro to return the current AGS version as defined by the AGS header file
/// @}
/// \defgroup enums General enumerations
/// @{
/// The return codes
typedef enum AGSReturnCode
{
AGS_SUCCESS, ///< Successful function call
AGS_FAILURE, ///< Failed to complete call for some unspecified reason
AGS_INVALID_ARGS, ///< Invalid arguments into the function
AGS_OUT_OF_MEMORY, ///< Out of memory when allocating space internally
AGS_MISSING_D3D_DLL, ///< Returned when a D3D dll fails to load
AGS_LEGACY_DRIVER, ///< Returned if a feature is not present in the installed driver
AGS_NO_AMD_DRIVER_INSTALLED, ///< Returned if the AMD GPU driver does not appear to be installed
AGS_EXTENSION_NOT_SUPPORTED, ///< Returned if the driver does not support the requested driver extension
AGS_ADL_FAILURE, ///< Failure in ADL (the AMD Display Library)
AGS_DX_FAILURE, ///< Failure from DirectX runtime
AGS_D3DDEVICE_NOT_CREATED ///< Failure due to not creating the D3D device successfully via AGS.
} AGSReturnCode;
/// @}
typedef struct AGSContext AGSContext; ///< All function calls in AGS require a pointer to a context. This is generated via \ref agsInitialize
/// The rectangle struct used by AGS.
typedef struct AGSRect
{
int offsetX; ///< Offset on X axis
int offsetY; ///< Offset on Y axis
int width; ///< Width of rectangle
int height; ///< Height of rectangle
} AGSRect;
/// The display info struct used to describe a display enumerated by AGS
typedef struct AGSDisplayInfo
{
char name[ 256 ]; ///< The name of the display
char displayDeviceName[ 32 ]; ///< The display device name, i.e. DISPLAY_DEVICE::DeviceName
unsigned int isPrimaryDisplay : 1; ///< Whether this display is marked as the primary display
unsigned int HDR10 : 1; ///< HDR10 is supported on this display
unsigned int dolbyVision : 1; ///< Dolby Vision is supported on this display
unsigned int freesync : 1; ///< Freesync is supported on this display
unsigned int freesyncHDR : 1; ///< Freesync HDR is supported on this display
unsigned int eyefinityInGroup : 1; ///< The display is part of the Eyefinity group
unsigned int eyefinityPreferredDisplay : 1; ///< The display is the preferred display in the Eyefinity group for displaying the UI
unsigned int eyefinityInPortraitMode : 1; ///< The display is in the Eyefinity group but in portrait mode
unsigned int reservedPadding : 24; ///< Reserved for future use
int maxResolutionX; ///< The maximum supported resolution of the unrotated display
int maxResolutionY; ///< The maximum supported resolution of the unrotated display
float maxRefreshRate; ///< The maximum supported refresh rate of the display
AGSRect currentResolution; ///< The current resolution and position in the desktop, ignoring Eyefinity bezel compensation
AGSRect visibleResolution; ///< The visible resolution and position. When Eyefinity bezel compensation is enabled this will
///< be the sub region in the Eyefinity single large surface (SLS)
float currentRefreshRate; ///< The current refresh rate
int eyefinityGridCoordX; ///< The X coordinate in the Eyefinity grid. -1 if not in an Eyefinity group
int eyefinityGridCoordY; ///< The Y coordinate in the Eyefinity grid. -1 if not in an Eyefinity group
double chromaticityRedX; ///< Red display primary X coord
double chromaticityRedY; ///< Red display primary Y coord
double chromaticityGreenX; ///< Green display primary X coord
double chromaticityGreenY; ///< Green display primary Y coord
double chromaticityBlueX; ///< Blue display primary X coord
double chromaticityBlueY; ///< Blue display primary Y coord
double chromaticityWhitePointX; ///< White point X coord
double chromaticityWhitePointY; ///< White point Y coord
double screenDiffuseReflectance; ///< Percentage expressed between 0 - 1
double screenSpecularReflectance; ///< Percentage expressed between 0 - 1
double minLuminance; ///< The minimum luminance of the display in nits
double maxLuminance; ///< The maximum luminance of the display in nits
double avgLuminance; ///< The average luminance of the display in nits
int logicalDisplayIndex; ///< The internally used index of this display
int adlAdapterIndex; ///< The internally used ADL adapter index
int reserved; ///< reserved field
} AGSDisplayInfo;
/// The ASIC family
typedef enum AsicFamily
{
AsicFamily_Unknown, ///< Unknown architecture, potentially from another IHV. Check \ref AGSDeviceInfo::vendorId
AsicFamily_PreGCN, ///< Pre GCN architecture.
AsicFamily_GCN1, ///< AMD GCN 1 architecture: Oland, Cape Verde, Pitcairn & Tahiti.
AsicFamily_GCN2, ///< AMD GCN 2 architecture: Hawaii & Bonaire. This also includes APUs Kaveri and Carrizo.
AsicFamily_GCN3, ///< AMD GCN 3 architecture: Tonga & Fiji.
AsicFamily_GCN4, ///< AMD GCN 4 architecture: Polaris.
AsicFamily_Vega, ///< AMD Vega architecture, including Raven Ridge (ie AMD Ryzen CPU + AMD Vega GPU).
AsicFamily_RDNA, ///< AMD RDNA architecture
AsicFamily_RDNA2, ///< AMD RDNA2 architecture
AsicFamily_RDNA3, ///< AMD RDNA3 architecture
AsicFamily_Count ///< Number of enumerated ASIC families
} AsicFamily;
/// The device info struct used to describe a physical GPU enumerated by AGS
typedef struct AGSDeviceInfo
{
const char* adapterString; ///< The adapter name string
AsicFamily asicFamily; ///< Set to Unknown if not AMD hardware
unsigned int isAPU : 1; ///< Whether this device is an APU
unsigned int isPrimaryDevice : 1; ///< Whether this device is marked as the primary device
unsigned int isExternal :1; ///< Whether this device is a detachable, external device
unsigned int reservedPadding : 29; ///< Reserved for future use
int vendorId; ///< The vendor id
int deviceId; ///< The device id
int revisionId; ///< The revision id
int numCUs; ///< Number of compute units
int numWGPs; ///< Number of RDNA Work Group Processors. Only valid if ASIC is RDNA onwards.
int numROPs; ///< Number of ROPs
int coreClock; ///< Core clock speed at 100% power in MHz
int memoryClock; ///< Memory clock speed at 100% power in MHz
int memoryBandwidth; ///< Memory bandwidth in MB/s
float teraFlops; ///< Teraflops of GPU. Zero if not GCN onwards. Calculated from iCoreClock * iNumCUs * 64 Pixels/clk * 2 instructions/MAD
unsigned long long localMemoryInBytes; ///< The size of local memory in bytes. 0 for non AMD hardware.
unsigned long long sharedMemoryInBytes; ///< The size of system memory available to the GPU in bytes. It is important to factor this into your VRAM budget for APUs
///< as the reported local memory will only be a small fraction of the total memory available to the GPU.
int numDisplays; ///< The number of active displays found to be attached to this adapter.
AGSDisplayInfo* displays; ///< List of displays allocated by AGS to be numDisplays in length.
int eyefinityEnabled; ///< Indicates if Eyefinity is active
int eyefinityGridWidth; ///< Contains width of the multi-monitor grid that makes up the Eyefinity Single Large Surface.
int eyefinityGridHeight; ///< Contains height of the multi-monitor grid that makes up the Eyefinity Single Large Surface.
int eyefinityResolutionX; ///< Contains width in pixels of the multi-monitor Single Large Surface.
int eyefinityResolutionY; ///< Contains height in pixels of the multi-monitor Single Large Surface.
int eyefinityBezelCompensated; ///< Indicates if bezel compensation is used for the current SLS display area. 1 if enabled, and 0 if disabled.
int adlAdapterIndex; ///< Internally used index into the ADL list of adapters
int reserved; ///< reserved field
} AGSDeviceInfo;
/// \defgroup general General API functions
/// API for initialization, cleanup, HDR display modes and Crossfire GPU count
/// @{
typedef void* (__stdcall *AGS_ALLOC_CALLBACK)( size_t allocationSize ); ///< AGS user defined allocation prototype
typedef void (__stdcall *AGS_FREE_CALLBACK)( void* allocationPtr ); ///< AGS user defined free prototype
/// The configuration options that can be passed in to \ref agsInitialize
typedef struct AGSConfiguration
{
AGS_ALLOC_CALLBACK allocCallback; ///< Optional memory allocation callback. If not supplied, malloc() is used
AGS_FREE_CALLBACK freeCallback; ///< Optional memory freeing callback. If not supplied, free() is used
} AGSConfiguration;
/// The top level GPU information returned from \ref agsInitialize
typedef struct AGSGPUInfo
{
const char* driverVersion; ///< The AMD driver package version
const char* radeonSoftwareVersion; ///< The Radeon Software Version
int numDevices; ///< Number of GPUs in the system
AGSDeviceInfo* devices; ///< List of GPUs in the system
} AGSGPUInfo;
/// The struct to specify the display settings to the driver.
typedef struct AGSDisplaySettings AGSDisplaySettings;
/// The result returned from \ref agsCheckDriverVersion
typedef enum AGSDriverVersionResult
{
AGS_SOFTWAREVERSIONCHECK_OK, ///< The reported Radeon Software Version is newer or the same as the required version
AGS_SOFTWAREVERSIONCHECK_OLDER, ///< The reported Radeon Software Version is older than the required version
AGS_SOFTWAREVERSIONCHECK_UNDEFINED ///< The check could not determine as result. This could be because it is a private or custom driver or just invalid arguments.
} AGSDriverVersionResult;
///
/// Helper function to check the installed software version against the required software version.
///
/// \param [in] radeonSoftwareVersionReported The Radeon Software Version returned from \ref AGSGPUInfo::radeonSoftwareVersion.
/// \param [in] radeonSoftwareVersionRequired The Radeon Software Version to check against. This is specificed using \ref AGS_MAKE_VERSION.
/// \return The result of the check.
///
AMD_AGS_API AGSDriverVersionResult agsCheckDriverVersion( const char* radeonSoftwareVersionReported, unsigned int radeonSoftwareVersionRequired );
///
/// Function to return the AGS version number.
///
/// \return The version number made using AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ).
///
AMD_AGS_API int agsGetVersionNumber();
///
/// Function used to initialize the AGS library.
/// agsVersion must be specified as AGS_CURRENT_VERSION or the call will return \ref AGS_INVALID_ARGS.
/// Must be called prior to any of the subsequent AGS API calls.
/// Must be called prior to ID3D11Device or ID3D12Device creation.
/// \note The caller of this function should handle the possibility of the call failing in the cases below. One option is to do a vendor id check and only call \ref agsInitialize if there is an AMD GPU present.
/// \note This function will fail with \ref AGS_NO_AMD_DRIVER_INSTALLED if there is no AMD driver found on the system.
/// \note This function will fail with \ref AGS_LEGACY_DRIVER in Catalyst versions before 12.20.
///
/// \param [in] agsVersion The API version specified using the \ref AGS_CURRENT_VERSION macro. If this does not match the version in the binary this initialization call will fail.
/// \param [in] config Optional pointer to a AGSConfiguration struct to override the default library configuration.
/// \param [out] context Address of a pointer to a context. This function allocates a context on the heap which is then required for all subsequent API calls.
/// \param [out] gpuInfo Optional pointer to a AGSGPUInfo struct which will get filled in for all the GPUs in the system.
///
AMD_AGS_API AGSReturnCode agsInitialize( int agsVersion, const AGSConfiguration* config, AGSContext** context, AGSGPUInfo* gpuInfo );
///
/// Function used to clean up the AGS library.
///
/// \param [in] context Pointer to a context. This function will deallocate the context from the heap.
///
AMD_AGS_API AGSReturnCode agsDeInitialize( AGSContext* context );
///
/// Function used to set a specific display into HDR mode
/// \note Setting all of the values apart from color space and transfer function to zero will cause the display to use defaults.
/// \note Call this function after each mode change (switch to fullscreen, any change in swapchain etc).
/// \note HDR10 PQ mode requires a 1010102 swapchain.
/// \note HDR10 scRGB mode requires an FP16 swapchain.
/// \note Freesync HDR scRGB mode requires an FP16 swapchain.
/// \note Freesync HDR Gamma 2.2 mode requires a 1010102 swapchain.
/// \note Dolby Vision requires a 8888 UNORM swapchain.
///
/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize
/// \param [in] deviceIndex The index of the device listed in \ref AGSGPUInfo::devices.
/// \param [in] displayIndex The index of the display listed in \ref AGSDeviceInfo::displays.
/// \param [in] settings Pointer to the display settings to use.
///
AMD_AGS_API AGSReturnCode agsSetDisplayMode( AGSContext* context, int deviceIndex, int displayIndex, const AGSDisplaySettings* settings );
/// @}
/// @}
#ifdef __cplusplus
} // extern "C"
#endif
#endif // AMD_AGS_H
-7
View File
@@ -1,7 +0,0 @@
{
"home": "https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK",
"license": "MIT (embeded in source)",
"version": "AGS v6.2.0",
"author": "Advanced Micro Devices, Inc",
"modified": "CarterLi"
}
File diff suppressed because it is too large Load Diff
+46
View File
@@ -0,0 +1,46 @@
//
// Copyright (c) 2016 - 2022 Advanced Micro Devices, Inc. All rights reserved.
//
// MIT LICENSE:
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
/// \file adl_sdk.h
/// \brief Contains the definition of the Memory Allocation Callback.\n <b>Included in ADL SDK</b>
///
/// \n\n
/// This file contains the definition of the Memory Allocation Callback.\n
/// It also includes definitions of the respective structures and constants.\n
/// <b> This is the only header file to be included in a C/C++ project using ADL </b>
#ifndef ADL_SDK_H_
#define ADL_SDK_H_
#include "adl_structures.h"
#if defined (LINUX)
#define __stdcall
#endif /* (LINUX) */
/// Memory Allocation Call back
typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int );
#define ADL_SDK_MAJOR_VERSION 17
#define ADL_SDK_MINOR_VERSION 1
#endif /* ADL_SDK_H_ */
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
{
"home": "https://github.com/GPUOpen-LibrariesAndSDKs/display-library",
"license": "MIT (embeded in source)",
"version": "ADL SDK 17.1",
"author": "Advanced Micro Devices, Inc"
}
-19
View File
@@ -119,7 +119,6 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
}
else
{
#if (__APPLE__ || __HAIKU__) // #1395
struct stat fileStat;
if(stat(path, &fileStat) != 0)
return false;
@@ -131,24 +130,6 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
return true;
#else
size_t len = strlen(path);
assert(len < PATH_MAX);
if (len == 0) return false;
int ret;
if (path[len - 1] != '/')
{
char buf[PATH_MAX + 1];
memcpy(buf, path, len);
buf[len] = '/';
buf[len + 1] = 0;
ret = access(buf, F_OK);
}
else
ret = access(path, F_OK);
return pathType == FF_PATHTYPE_DIRECTORY ? ret == 0 : ret == -1 && errno == ENOTDIR;
#endif
}
#endif
+5
View File
@@ -256,6 +256,11 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
bool ffSuppressIO(bool suppress)
{
#ifndef NDEBUG
if (instance.config.display.debugMode)
return false;
#endif
static bool init = false;
static int origOut = -1;
static int origErr = -1;
+5
View File
@@ -159,6 +159,11 @@ bool ffPathExpandEnv(const char* in, FFstrbuf* out)
bool ffSuppressIO(bool suppress)
{
#ifndef NDEBUG
if (instance.config.display.debugMode)
return false;
#endif
static bool init = false;
static HANDLE hOrigOut = INVALID_HANDLE_VALUE;
static HANDLE hOrigErr = INVALID_HANDLE_VALUE;
+28 -2
View File
@@ -7,7 +7,7 @@
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
static bool getDefaultRouteIPv4(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
{
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
if (!netRoute) return false;
@@ -15,12 +15,38 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
// skip first line
FF_UNUSED(fscanf(netRoute, "%*[^\n]\n"));
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, ...
while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2)
{
if (destination != 0) continue;
*ifIndex = if_nametoindex(iface);
return true;
}
iface[0] = '\0';
return false;
}
static bool getDefaultRouteIPv6(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
{
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/ipv6_route", "r");
if (!netRoute) return false;
uint32_t prefixLen;
//destination, dest_prefix_len, source, src_prefix_len, next hop, metric, ref counter, use counter, flags, iface
while (fscanf(netRoute, "%*s %x %*s %*s %*s %*s %*s %*s %*s %" FF_STR(IF_NAMESIZE) "s", &prefixLen, iface) == 2)
{
if (prefixLen != 0) continue;
*ifIndex = if_nametoindex(iface);
return true;
}
iface[0] = '\0';
return false;
}
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
{
if (getDefaultRouteIPv4(iface, ifIndex))
return true;
return getDefaultRouteIPv6(iface, ifIndex);
}
+2 -2
View File
@@ -189,7 +189,7 @@ static const char* initNetworkingState(FFNetworkingState* state, const char* hos
ffStrbufInitA(&state->command, 64);
ffStrbufAppendS(&state->command, "GET ");
ffStrbufAppendS(&state->command, path);
ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&state->command, " HTTP/1.0\nHost: ");
ffStrbufAppendS(&state->command, host);
ffStrbufAppendS(&state->command, "\r\n");
@@ -476,7 +476,7 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
return "Content length mismatch";
}
if (ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n")) {
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
FF_DEBUG("Received valid HTTP 200 response, content %u bytes, total %u bytes", contentLength, buffer->length);
} else {
FF_DEBUG("Invalid response: %.40s...", buffer->chars);
+2 -2
View File
@@ -151,7 +151,7 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
ffStrbufAppendS(&command, "GET ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
ffStrbufAppendS(&command, " HTTP/1.0\nHost: ");
ffStrbufAppendS(&command, host);
ffStrbufAppendS(&command, "\r\n");
ffStrbufAppendS(&command, "Connection: close\r\n"); // Explicitly request connection closure
@@ -314,7 +314,7 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
return "No HTTP header end found";
}
if (ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n")) {
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
FF_DEBUG("Received valid HTTP 200 response, content length: %u bytes, total length: %u bytes",
contentLength, buffer->length);
} else {
+6
View File
@@ -198,6 +198,12 @@ void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t s
return;
}
if(seconds >= 30)
{
minutes++;
seconds = 0;
}
if(days > 0)
{
ffStrbufAppendF(result, "%u day", days);
+2 -2
View File
@@ -65,8 +65,8 @@
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
{
ts.tv_sec += ts.tv_sec / 1000;
ts.tv_nsec += (ts.tv_nsec % 1000) * 1000000;
ts.tv_sec += timeout / 1000;
ts.tv_nsec += (timeout % 1000) * 1000000;
if (pthread_timedjoin_np(thread, NULL, &ts) != 0)
{
pthread_kill(thread, SIGTERM);
+1 -1
View File
@@ -98,7 +98,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '0');
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
+1 -1
View File
@@ -108,7 +108,7 @@ static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer))
{
ffStrbufTrimRightSpace(&result->manufacturer);
ffStrbufTrimRightSpace(&tmpBuffer);
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
{
if (result->status.length)
+6 -2
View File
@@ -70,9 +70,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
critical = true;
}
else if (ffStrEquals(desc, "discharge rate"))
{
prop_dictionary_get_uint(dict, "cur-value", &dischargeRate);
}
}
if (max > 0)
@@ -92,7 +90,10 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
if (charging)
ffStrbufAppendS(&battery->status, "Charging, ");
else if (dischargeRate)
{
ffStrbufAppendS(&battery->status, "Discharging, ");
battery->timeRemaining = (int32_t)((double)curr / dischargeRate * 3600);
}
if (critical)
ffStrbufAppendS(&battery->status, "Critical, ");
if (acConnected)
@@ -100,8 +101,11 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
}
prop_object_iterator_release(iter);
}
prop_object_iterator_release(itKey);
prop_object_release(root);
return NULL;
}
+1 -1
View File
@@ -25,7 +25,7 @@ const char* ffDetectBios(FFBiosResult* result)
{
ffStrbufSetStatic(&result->type,
ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) ||
ffPathExists("/boot/efi/efi/" /*efi partition*/, FF_PATHTYPE_DIRECTORY)
ffPathExists("/boot/efi/efi/" /*efi partition. Note /boot/efi exists on BIOS system*/, FF_PATHTYPE_DIRECTORY)
? "UEFI" : "BIOS");
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include <stdlib.h>
const char *ffDetectBios(FFBiosResult *bios)
const char* ffDetectBios(FFBiosResult* bios)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
+7 -2
View File
@@ -27,6 +27,11 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
};
};
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
#elif __OpenBSD__
#include "common/io/io.h"
#include <fcntl.h>
#include <unistd.h>
#endif
typedef struct FFSmbiosBios
@@ -89,8 +94,8 @@ const char* ffDetectBios(FFBiosResult* bios)
default: break;
}
}
#elif __HAIKU__
// Currently SMBIOS detection is supported in legency BIOS only
#elif __HAIKU__ || __OpenBSD__
// Currently SMBIOS detection is supported in legancy BIOS only
ffStrbufSetStatic(&bios->type, "BIOS");
#endif
+1 -1
View File
@@ -21,5 +21,5 @@ const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MA
if (bt_devenum((void*) enumDev, devices) < 0)
return "bt_devenum() failed";
return 0;
return NULL;
}
@@ -3,12 +3,12 @@
#import <IOBluetooth/IOBluetooth.h>
// For some reason the official declaration of IOBluetoothHostController don't include property `controllers`
// For some reason the official declaration of IOBluetoothHostController doesn't include property `controllers`
@interface IOBluetoothHostController()
+ (id)controllers;
@end
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
NSArray<IOBluetoothHostController*>* ctrls = IOBluetoothHostController.controllers;
if(!ctrls)
@@ -83,7 +83,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
ffStrbufInitS(&device->name, blri.localInfo.name);
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X",
addr.rgBytes[5],
addr.rgBytes[4],
addr.rgBytes[3],
@@ -97,6 +97,8 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
device->enabled = true;
device->connectable = ffBluetoothIsConnectable(hRadio);
device->discoverable = ffBluetoothIsDiscoverable(hRadio);
CloseHandle(hRadio);
} while (ffBluetoothFindNextRadio(hFind, &hRadio));
ffBluetoothFindRadioClose(hFind);
+1
View File
@@ -6,6 +6,7 @@ typedef struct FFBootmgrResult
{
FFstrbuf name;
FFstrbuf firmware;
uint16_t order;
bool secureBoot;
} FFBootmgrResult;
+17 -3
View File
@@ -2,10 +2,22 @@
#include "efi_helper.h"
#include "common/io/io.h"
#include <sys/efiio.h>
#ifdef __OpenBSD__
#include <dev/efi/efiio.h>
#else
#include <sys/efiio.h>
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef __NetBSD__
typedef uint16_t efi_char;
#endif
#ifndef EFI_GLOBAL_VARIABLE
#define EFI_GLOBAL_VARIABLE { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } }
#endif
const char* ffDetectBootmgr(FFBootmgrResult* result)
{
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR);
@@ -13,7 +25,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
uint8_t buffer[2048];
struct efi_var_ioc ioc = {
.vendor = { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } },
.vendor = EFI_GLOBAL_VARIABLE,
.data = buffer,
};
@@ -23,8 +35,10 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2)
return "ioctl(EFIIOC_VAR_GET, BootCurrent) failed";
result->order = *(uint16_t*)buffer;
unsigned char hex[5];
snprintf((char*) hex, sizeof(hex), "%04X", *(uint16_t*)buffer);
snprintf((char*) hex, sizeof(hex), "%04X", result->order);
ioc.datasize = sizeof(buffer);
ioc.name = (efi_char[]){ 'B', 'o', 'o', 't', hex[0], hex[1], hex[2], hex[3], '\0' };
ioc.namesize = sizeof("Boot####") * 2;
+4 -2
View File
@@ -11,8 +11,10 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "BootCurrent-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6)
return "Failed to read efivar: BootCurrent";
uint16_t value = *(uint16_t *)&buffer[4];
snprintf((char*) buffer, sizeof(buffer), FF_EFIVARS_PATH_PREFIX "Boot%04X-" FF_EFI_GLOBAL_GUID, value);
result->order = *(uint16_t *)&buffer[4];
snprintf((char*) buffer, sizeof(buffer), FF_EFIVARS_PATH_PREFIX "Boot%04X-" FF_EFI_GLOBAL_GUID, result->order);
ssize_t size = ffReadFileData((const char*) buffer, sizeof(buffer), buffer);
if (size < 5 + (int) sizeof(FFEfiLoadOption) || size == (ssize_t) sizeof(buffer))
+4 -4
View File
@@ -1,11 +1,12 @@
#include "bootmgr.h"
#include "efi_helper.h"
#include "common/io/io.h"
#include <windows.h>
const char* enablePrivilege(const wchar_t* privilege)
{
HANDLE token;
FF_AUTO_CLOSE_FD HANDLE token = NULL;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
return "OpenProcessToken() failed";
@@ -32,13 +33,12 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
if (enablePrivilege(L"SeSystemEnvironmentPrivilege") != NULL)
return "Failed to enable SeSystemEnvironmentPrivilege";
uint16_t value;
if (GetFirmwareEnvironmentVariableW(L"BootCurrent", L"{" FF_EFI_GLOBAL_GUID L"}", &value, sizeof(value)) != 2)
if (GetFirmwareEnvironmentVariableW(L"BootCurrent", L"{" FF_EFI_GLOBAL_GUID L"}", &result->order, sizeof(result->order)) != 2)
return "GetFirmwareEnvironmentVariableW(BootCurrent) failed";
uint8_t buffer[2048];
wchar_t key[16];
swprintf(key, ARRAY_SIZE(key), L"Boot%04X", value);
swprintf(key, ARRAY_SIZE(key), L"Boot%04X", result->order);
uint32_t size = GetFirmwareEnvironmentVariableW(key, L"{" FF_EFI_GLOBAL_GUID L"}", buffer, sizeof(buffer));
if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer))
return "GetFirmwareEnvironmentVariableW(Boot####) failed";
+24 -13
View File
@@ -8,24 +8,35 @@
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
FF_AUTO_CLOSE_FD int devfd = open("/dev/ttyC0", O_RDONLY);
char path[] = "/dev/ttyCX";
for (char i = '0'; i <= '9'; ++i) {
path[strlen("/dev/ttyC")] = i;
if (devfd < 0) return "open(dev/ttyC0, O_RDONLY) failed";
FF_AUTO_CLOSE_FD int devfd = open(path, O_RDONLY);
struct wsdisplay_param param = {
.param = WSDISPLAYIO_PARAM_BRIGHTNESS,
};
if (devfd < 0) {
if (errno == EACCES && i == '0')
return "Permission denied when opening tty device";
if (errno == ENOENT)
break;
continue;
}
if (ioctl(devfd, WSDISPLAYIO_GETPARAM, &param) < 0)
return "ioctl(WSDISPLAYIO_GETPARAM) failed";
struct wsdisplay_param param = {
.param = WSDISPLAYIO_PARAM_BRIGHTNESS,
};
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitStatic(&brightness->name, "wsdisplay");
if (ioctl(devfd, WSDISPLAYIO_GETPARAM, &param) < 0)
continue;
brightness->max = param.max;
brightness->min = param.min;
brightness->current = param.curval;
brightness->builtin = true;
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInitF(&brightness->name, "ttyC%c", i);
brightness->max = param.max;
brightness->min = param.min;
brightness->current = param.curval;
brightness->builtin = true;
}
return NULL;
}
@@ -43,6 +43,7 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
FF_LIBRARY_LOAD(dxva2, "dlopen dxva2" FF_LIBRARY_EXTENSION " failed", "dxva2" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dxva2, GetPhysicalMonitorsFromHMONITOR)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dxva2, GetMonitorBrightness)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dxva2, DestroyPhysicalMonitor)
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
@@ -64,6 +65,8 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
brightness->current = curr;
brightness->builtin = false;
}
ffDestroyPhysicalMonitor(physicalMonitor.hPhysicalMonitor);
}
}
return NULL;
+3
View File
@@ -12,7 +12,10 @@ static const char* enumerateDevices(FFBtrfsResult* item, int dfd, FFstrbuf* buff
FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd);
if(dirp == NULL)
{
close(subfd);
return "fdopendir(\"/sys/fs/btrfs/UUID/devices\") == NULL";
}
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
+1 -1
View File
@@ -37,7 +37,7 @@ const char* ffDetectCamera(FFlist* result)
{
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.808"); break;
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.878"); break;
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
+5 -3
View File
@@ -48,7 +48,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
for (uint32_t i = 0; i < count; i++)
{
IMFActivate* device = devices[i];
IMFActivate* FF_AUTO_RELEASE_COM_OBJECT device = devices[i];
wchar_t buffer[256];
uint32_t length = 0;
@@ -90,9 +90,11 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
continue;
// Assume first type is the maximum resolution
IMFMediaType* FF_AUTO_RELEASE_COM_OBJECT type = NULL;
IMFMediaType* type = NULL;
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
{
on_scope_exit destroyType([=] { type->Release(); });
GUID majorType;
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
continue;
@@ -123,7 +125,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
}
}
CoTaskMemFree(devices);
if (devices) CoTaskMemFree(devices);
return nullptr;
}
+1
View File
@@ -34,6 +34,7 @@ const char* ffChassisTypeToString(uint32_t type)
case 0x1A: return "Compact PCI";
case 0x1B: return "Advanced TCA";
case 0x1C: return "Blade";
case 0x1D: return "Mobile Workstation";
case 0x1E: return "Tablet";
case 0x1F: return "Convertible";
case 0x20: return "Detachable";
+3 -2
View File
@@ -17,10 +17,11 @@ const char* ffDetectChassis(FFChassisResult* result)
if (ffStrbufStartsWithS(&host.name, "MacBook "))
ffStrbufSetStatic(&result->type, "Laptop");
else if (ffStrbufStartsWithS(&host.name, "Mac mini "))
else if (ffStrbufStartsWithS(&host.name, "Mac mini ") ||
ffStrbufStartsWithS(&host.name, "Mac Studio "))
ffStrbufSetStatic(&result->type, "Mini PC");
else if (ffStrbufStartsWithS(&host.name, "iMac "))
ffStrbufSetStatic(&result->type, "All-in-One");
ffStrbufSetStatic(&result->type, "All in One");
else
ffStrbufSetStatic(&result->type, "Desktop");
+1 -3
View File
@@ -430,7 +430,6 @@ FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), "\nphysical id\t:", strlen("\nphysical id\t:"))))
{
if (!p) break;
p += strlen("\nphysical id\t:");
char* pend;
unsigned long id = strtoul(p, &pend, 10);
@@ -586,7 +585,6 @@ FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const c
while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), key, keylen)))
{
if (!p) break;
p += keylen;
char* pend;
unsigned long id = strtoul(p, &pend, 10);
@@ -608,7 +606,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
#if __ANDROID__
detectAndroid(cpu);
#else
#elif !__powerpc__ && !__powerpc
detectSocName(cpu);
#endif
+8 -1
View File
@@ -9,12 +9,19 @@
#include <unistd.h>
#include <fcntl.h>
static void freePropDict(prop_dictionary_t* pdict)
{
assert(pdict != NULL);
if (*pdict == NULL) return;
prop_object_release(*pdict);
}
static const char* detectCpuTemp(double* current)
{
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
prop_dictionary_t root = NULL;
__attribute__((__cleanup__(freePropDict))) prop_dictionary_t root = NULL;
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
+8 -6
View File
@@ -23,22 +23,24 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
{
kstat_named_t* kn = kstat_data_lookup(ks, "brand");
ffStrbufSetNS(&cpu->name, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
if (kn) ffStrbufSetNS(&cpu->name, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
}
{
kstat_named_t* kn = kstat_data_lookup(ks, "vendor_id");
ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
if (kn) ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
}
ffCPUDetectSpeedByCpuid(cpu);
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
if (kn->value.ui32 > cpu->frequencyBase)
cpu->frequencyBase = kn->value.ui32;
{
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
if (kn && kn->value.ui32 > cpu->frequencyBase)
cpu->frequencyBase = kn->value.ui32;
}
ks = kstat_lookup(kc, "unix", -1, "system_misc");
if (ks && kstat_read(kc, ks, NULL) >= 0)
{
kstat_named_t* kn = kstat_data_lookup(ks, "ncpus");
cpu->coresLogical = cpu->coresPhysical = cpu->coresOnline = (uint16_t) kn->value.ui32;
if (kn) cpu->coresLogical = cpu->coresPhysical = cpu->coresOnline = (uint16_t) kn->value.ui32;
}
return NULL;
+7 -3
View File
@@ -128,9 +128,13 @@ static const char* detectByRegistry(FFCPUResult* cpu)
if (cpu->coresLogical == 0)
{
DWORD cores;
if (RegQueryInfoKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", NULL, NULL, &cores, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
FF_HKEY_AUTO_DESTROY hProcsKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor", &hProcsKey, NULL))
{
uint32_t cores;
if (ffRegGetNSubKeys(hProcsKey, &cores, NULL))
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
}
}
uint32_t mhz;
+2
View File
@@ -26,6 +26,8 @@ const char* detectThermalTemp(double* current, double* critical)
else
*critical = 0.0/0.0;
}
return NULL;
}
return "No WMI result returned";
+1 -1
View File
@@ -31,7 +31,7 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
case CacheInstruction: cacheType = FF_CPU_CACHE_TYPE_INSTRUCTION; break;
case CacheData: cacheType = FF_CPU_CACHE_TYPE_DATA; break;
case CacheTrace: cacheType = FF_CPU_CACHE_TYPE_TRACE; break;
default: __builtin_unreachable(); break;
default: break;
}
ffCPUCacheAddItem(result, ptr->Cache.Level, ptr->Cache.CacheSize, ptr->Cache.LineSize, cacheType);
}
+3
View File
@@ -3,6 +3,7 @@
#include <mach/processor_info.h>
#include <mach/mach_host.h>
#include <mach/vm_map.h>
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
@@ -28,5 +29,7 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
.totalAll = (uint64_t)total,
};
}
vm_deallocate(mach_task_self(), (vm_address_t) cpuInfo, numCpuInfo * sizeof(integer_t));
return NULL;
}
+3 -3
View File
@@ -36,7 +36,7 @@ static const char* detectFsLabel(struct statfs* fs, FFDisk* disk)
return "geom_gettree() failed";
}
for (cLabels = geomTree.lg_class.lh_first; !ffStrEquals(cLabels->lg_name, "LABEL"); cLabels = cLabels->lg_class.le_next);
for (cLabels = geomTree.lg_class.lh_first; cLabels && !ffStrEquals(cLabels->lg_name, "LABEL"); cLabels = cLabels->lg_class.le_next);
if (!cLabels)
return "Class LABEL is not found";
}
@@ -165,7 +165,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->filesTotal = (uint32_t) fs->f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs->f_ffree);
disk->filesUsed = (uint32_t) (fs->f_files - fs->f_ffree);
ffStrbufInitS(&disk->mountFrom, fs->f_mntfromname);
ffStrbufInitS(&disk->mountpoint, fs->f_mntonname);
@@ -185,7 +185,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
#ifndef __DragonFly__
struct stat st;
if(stat(fs->f_mntonname, &st) == 0 && st.st_birthtimespec.tv_sec > 0)
disk->createTime = (uint64_t)((st.st_birthtimespec.tv_sec * 1000) + (st.st_birthtimespec.tv_nsec / 1000000));
disk->createTime = (uint64_t)(((uint64_t) st.st_birthtimespec.tv_sec * 1000) + ((uint64_t) st.st_birthtimespec.tv_nsec / 1000000));
#endif
}
+3 -3
View File
@@ -14,7 +14,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
for (dev_t dev; (dev = next_dev(&pos)) >= B_OK;)
{
fs_info fs;
if (fs_stat_dev(dev, &fs) < -1) continue;
if (fs_stat_dev(dev, &fs) < 0) continue;
node_ref node(fs.dev, fs.root);
BDirectory dir(&node);
@@ -32,10 +32,10 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
disk->bytesTotal = (uint64_t)fs.total_blocks * (uint64_t) fs.block_size;
disk->bytesFree = (uint64_t)fs.free_blocks * (uint64_t) fs.block_size;
disk->bytesAvailable = disk->bytesFree;
disk->bytesUsed = 0; // To be filled in ./disk. c
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->filesTotal = (uint32_t) fs.total_nodes;
disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs.free_nodes);
disk->filesUsed = (uint32_t) (fs.total_nodes - fs.free_nodes);
ffStrbufInitS(&disk->mountFrom, fs.device_name);
ffStrbufInitS(&disk->mountpoint, path.Path());
+4 -1
View File
@@ -209,7 +209,10 @@ static bool isRemovable(FFDisk* currentDisk)
char sysBlockVolume[PATH_MAX]; // /sys/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1
if (realpath(sysBlockPartition, sysBlockVolume) == NULL)
return false;
strcpy(strrchr(sysBlockVolume, '/') + 1, "removable");
char* lastSlash = strrchr(sysBlockVolume, '/');
if (lastSlash == NULL)
return false;
strcpy(lastSlash + 1, "removable");
char removableChar = '0';
return ffReadFileData(sysBlockVolume, 1, &removableChar) > 0 && removableChar == '1';
-3
View File
@@ -99,9 +99,6 @@ static void detectStats(FFDisk* disk)
ffStrbufSetS(&disk->name, fs.f_fstr);
disk->createTime = 0;
struct stat deviceStat;
if(stat(disk->mountpoint.chars, &deviceStat) == 0)
disk->createTime = (uint64_t) deviceStat.st_ctim.tv_sec * 1000 + (uint64_t) deviceStat.st_ctim.tv_nsec / 1000000000;
}
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
+5
View File
@@ -69,10 +69,15 @@ const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options)
uint64_t temp = *currValue;
*currValue -= *prevValue;
*currValue /= (time2 - time1) / 1000 /* seconds */;
// For next function call
*prevValue = temp;
}
}
// For next function call
time1 = time2;
// Leak ioCounters1 here
return NULL;
}
+5 -1
View File
@@ -13,7 +13,8 @@
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
struct gmesh geomTree;
__attribute__((__cleanup__(geom_deletetree)))
struct gmesh geomTree = {};
if (geom_gettree(&geomTree) < 0)
return "geom_gettree() failed";
@@ -21,6 +22,9 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
return "geom_stats_open() failed";
void* snap = geom_stats_snapshot_get();
if (!snap)
return "geom_stats_snapshot_get() failed";
struct devstat* snapIter;
while ((snapIter = geom_stats_snapshot_next(snap)) != NULL)
{
+8 -6
View File
@@ -8,10 +8,10 @@
#include <inttypes.h>
#include <fcntl.h>
static void parseDiskIOCounters(int dfd, const char* devName, FFlist* result, FFDiskIOOptions* options)
static const char* parseDiskIOCounters(int dfd, const char* devName, FFlist* result, FFDiskIOOptions* options)
{
FF_AUTO_CLOSE_FD int devfd = openat(dfd, "device", O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
if (devfd < 0) return; // virtual device
if (devfd < 0) return "virtual device";
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
@@ -49,7 +49,7 @@ static void parseDiskIOCounters(int dfd, const char* devName, FFlist* result, FF
}
if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix))
return;
return "ignored";
}
// I/Os merges sectors ticks ...
@@ -57,10 +57,10 @@ static void parseDiskIOCounters(int dfd, const char* devName, FFlist* result, FF
{
char sysBlockStat[PROC_FILE_BUFFSIZ];
ssize_t fileSize = ffReadFileDataRelative(dfd, "stat", ARRAY_SIZE(sysBlockStat) - 1, sysBlockStat);
if (fileSize <= 0) return;
if (fileSize <= 0) return "failed to read stat file";
sysBlockStat[fileSize] = '\0';
if (sscanf(sysBlockStat, "%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) <= 0)
return;
return "invalid stat file format";
}
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
@@ -70,6 +70,8 @@ static void parseDiskIOCounters(int dfd, const char* devName, FFlist* result, FF
device->bytesWritten = sectorWritten * 512;
device->readCount = nRead;
device->writeCount = nWritten;
return NULL;
}
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
@@ -83,7 +85,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
const char* const devName = sysBlockEntry->d_name;
if (devName[0] == '.') continue;;
if (devName[0] == '.') continue;
FF_AUTO_CLOSE_FD int dfd = openat(dirfd(sysBlockDirp), devName, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
if (dfd > 0) parseDiskIOCounters(dfd, devName, result, options);
+3 -3
View File
@@ -12,12 +12,12 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0) < 0)
return "sysctl({HW_IOSTATS}, NULL) failed";
uint32_t nDrive = (uint32_t) (len / sizeof(struct io_sysctl));
struct io_sysctl* stats = malloc(len);
FF_AUTO_FREE struct io_sysctl* stats = malloc(len);
if (sysctl(mib, ARRAY_SIZE(mib), stats, &len, NULL, 0) < 0)
return "sysctl({HW_IOSTATS}, stats) failed";
for (uint32_t i = 0; i < nDrive; ++i)
{
struct io_sysctl* st = &stats[i];
+1 -1
View File
@@ -13,7 +13,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
return "sysctl({HW_DISKSTATS}, NULL) failed";
uint32_t nDrive = (uint32_t) (len / sizeof(struct diskstats));
struct diskstats* stats = malloc(len);
FF_AUTO_FREE struct diskstats* stats = malloc(len);
if (sysctl(mib, ARRAY_SIZE(mib), stats, &len, NULL, 0) < 0)
return "sysctl({HW_DISKSTATS}, stats) failed";
+1 -1
View File
@@ -27,7 +27,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInit(&device->devPath);
ffStrbufInit(&device->devPath); // unlike other platforms, `/dev/ks_name` is not available
ffStrbufInitS(&device->name, ks->ks_name);
device->bytesRead = kio.nread;
device->readCount = kio.reads;
+2 -2
View File
@@ -56,8 +56,6 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFDiskIO
return true;
}
ffStrbufInitWS(&device->devPath, szDevice);
DISK_PERFORMANCE dp = {};
if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &dp, sizeof(dp), &retSize, NULL))
{
@@ -72,6 +70,8 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFDiskIO
result->length--;
}
ffStrbufInitWS(&device->devPath, szDevice);
return true;
}
@@ -4,6 +4,33 @@
#include <math.h>
static bool checkHdrStatus(FFDisplayResult* display)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffSettingsGetAndroidProperty("ro.surface_flinger.has_HDR_display", &buffer))
{
if (ffStrbufIgnCaseEqualS(&buffer, "true"))
{
display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
if (ffSettingsGetAndroidProperty("persist.sys.hdr_mode", &buffer) &&
ffStrbufToUInt(&buffer, 0) > 0)
display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED;
return true;
}
else
{
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
return true;
}
}
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
return false;
}
static void detectWithDumpsys(FFDisplayServerResult* ds)
{
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
@@ -54,7 +81,7 @@ static void detectWithDumpsys(FFDisplayServerResult* ds)
}
ffStrbufRecalculateLength(&name);
ffdsAppendDisplay(ds,
FFDisplayResult* display = ffdsAppendDisplay(ds,
(uint32_t)width,
(uint32_t)height,
refreshRate,
@@ -72,6 +99,7 @@ static void detectWithDumpsys(FFDisplayServerResult* ds)
0,
"dumpsys"
);
if (display) display->hdrStatus = checkHdrStatus(display);
}
index = nextIndex + 1;
@@ -92,7 +120,7 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
uint32_t height = (uint32_t) ffStrbufToUInt(&buffer, 0);
ffStrbufSubstrAfterFirstC(&buffer, ',');
double scaleFactor = (double) ffStrbufToUInt(&buffer, 0) / 160.;
return ffdsAppendDisplay(ds,
FFDisplayResult* display = ffdsAppendDisplay(ds,
width,
height,
0,
@@ -110,6 +138,8 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
0,
"getprop"
);
if (display) display->hdrStatus = checkHdrStatus(display);
return !!display;
}
return false;
@@ -68,7 +68,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
if(displayInfo)
{
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
if(ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames) == NULL)
ffCfDictGetString(productNames, CFSTR("en_US"), &buffer);
// CGDisplayScreenSize reports invalid result for external displays on old Intel MacBook Pro
@@ -273,7 +273,7 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result)
FF_LIST_FOR_EACH(FFstrbuf, basePath, instance.state.platform.configDirs)
{
char path[1024];
snprintf(path, ARRAY_SIZE(path) - 1, "%s%s", basePath->chars, fileName);
snprintf(path, ARRAY_SIZE(path), "%s%s", basePath->chars, fileName);
if (ffReadFileBuffer(path, &monitorsXml))
break;
}
+1 -1
View File
@@ -374,7 +374,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
ffStrbufAppendS(&procPath, dirent->d_name);
uint32_t procFolderPathLength = procPath.length;
//Don't check for processes not owend by the current user.
//Don't check for processes not owned by the current user.
ffStrbufAppendS(&procPath, "/loginuid");
ffReadFileBuffer(procPath.chars, &loginuid);
if(ffStrbufToUInt(&loginuid, (uint64_t) -1) != userId)
+3 -3
View File
@@ -26,7 +26,7 @@ typedef struct XcbPropertyData
FF_LIBRARY_SYMBOL(xcb_get_atom_name_reply)
} XcbPropertyData;
static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyData)
static bool xcbInitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, XcbPropertyData* propertyData)
{
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_intern_atom, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_intern_atom_reply, false)
@@ -333,7 +333,7 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcbRandr, "dlopen lbxcb-randr failed", "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD(xcbRandr, "dlopen libxcb-randr failed", "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_connect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_get_setup)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_setup_roots_iterator)
@@ -369,7 +369,7 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
data.connection = ffxcb_connect(NULL, NULL);
if(data.connection == NULL)
return "xcb_connect failed";
return "xcb_connect() failed";
data.result = result;
+4 -4
View File
@@ -17,7 +17,7 @@ typedef struct X11PropertyData
FF_LIBRARY_SYMBOL(XFree)
} X11PropertyData;
static bool x11InitPropertyData(void* libraryHandle, X11PropertyData* propertyData)
static bool x11InitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, X11PropertyData* propertyData)
{
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XInternAtom, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XGetWindowProperty, false)
@@ -147,7 +147,7 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
"xlib-randr-crtc"
);
if (edidLength)
if (item && edidLength)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
@@ -231,7 +231,7 @@ static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
if(monitorInfos == NULL)
return false;
bool foundAMonitor;
bool foundAMonitor = false;
for(int i = 0; i < numberOfMonitors; i++)
{
@@ -272,7 +272,7 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
0,
(uint32_t) WidthMMOfScreen(screen),
(uint32_t) HeightMMOfScreen(screen),
"xlib_randr_screen"
"xlib-randr-screen"
);
}
+109
View File
@@ -0,0 +1,109 @@
#include "detection/dns/dns.h"
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include "util/apple/cf_helpers.h"
#include "util/debug.h"
#include <SystemConfiguration/SystemConfiguration.h>
static const char* detectDnsFromConf(const char* path, FFDNSOptions* options, FFlist* results)
{
FF_DEBUG("Attempting to read DNS config from %s", path);
FF_AUTO_CLOSE_FILE FILE* file = fopen(path, "r");
if (!file)
{
FF_DEBUG("Failed to open %s: %m", path);
return "fopen(path, r) failed";
}
if (results->length > 0)
{
FF_DEBUG("Clearing existing DNS entries (%u entries)", results->length);
FF_LIST_FOR_EACH(FFstrbuf, item, *results)
ffStrbufDestroy(item);
ffListClear(results);
}
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
while (getline(&line, &len, file) != -1)
{
if (ffStrStartsWith(line, "nameserver"))
{
char* nameserver = line + strlen("nameserver");
while (*nameserver == ' ' || *nameserver == '\t')
nameserver++;
if (*nameserver == '\0') continue;
char* comment = strchr(nameserver, '#');
if (comment) *comment = '\0';
if ((ffStrContainsC(nameserver, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) ||
(ffStrContainsC(nameserver, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT)))
continue;
FFstrbuf* item = (FFstrbuf*) ffListAdd(results);
ffStrbufInitS(item, nameserver);
ffStrbufTrimRightSpace(item);
FF_DEBUG("Found DNS server: %s", item->chars);
}
}
FF_DEBUG("Found %u DNS servers in %s", results->length, path);
return NULL;
}
const char* ffDetectDNS(FFDNSOptions* options, FFlist* results)
{
// Handle macOS-specific DNS configurations
FF_DEBUG("Using SystemConfiguration framework for macOS");
// Create a reference to the dynamic store
FF_CFTYPE_AUTO_RELEASE SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("fastfetch"), NULL, NULL);
if (store)
{
// Get the network global IPv4 and IPv6 configuration
FF_CFTYPE_AUTO_RELEASE CFStringRef key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
if (key)
{
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef dict = SCDynamicStoreCopyValue(store, key);
if (dict)
{
// Get the DNS server addresses array
CFArrayRef dnsServers = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
if (dnsServers)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
for (CFIndex i = 0; i < CFArrayGetCount(dnsServers); i++)
{
if (ffCfStrGetString(CFArrayGetValueAtIndex(dnsServers, i), &buffer) == NULL)
{
// Check if the address matches our filter
if ((ffStrbufContainC(&buffer, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) ||
(ffStrbufContainC(&buffer, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT)))
continue;
// Add to results
FFstrbuf* item = (FFstrbuf*) ffListAdd(results);
ffStrbufInitMove(item, &buffer);
FF_DEBUG("Found DNS server on macOS: %s", item->chars);
}
}
}
}
}
}
// If we didn't find any servers, try resolv.conf as fallback
if (results->length > 0)
return NULL;
FF_DEBUG("No DNS servers found via SystemConfiguration, trying resolv.conf");
// Try standard resolv.conf location on macOS as a fallback
return detectDnsFromConf("/var/run/resolv.conf", options, results);
}
+100 -3
View File
@@ -3,6 +3,7 @@
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include "util/debug.h"
#ifdef __HAIKU__
#define RESOLV_CONF "/system/settings/network/resolv.conf"
@@ -10,11 +11,24 @@
#define RESOLV_CONF "/etc/resolv.conf"
#endif
const char* ffDetectDNS(FFDNSOptions* options, FFlist* results)
static const char* detectDnsFromConf(const char* path, FFDNSOptions* options, FFlist* results)
{
FF_AUTO_CLOSE_FILE FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT RESOLV_CONF, "r");
FF_DEBUG("Attempting to read DNS config from %s", path);
FF_AUTO_CLOSE_FILE FILE* file = fopen(path, "r");
if (!file)
return "fopen (" FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf) failed";
{
FF_DEBUG("Failed to open %s: %m", path);
return "fopen(path, r) failed";
}
if (results->length > 0)
{
FF_DEBUG("Clearing existing DNS entries (%u entries)", results->length);
FF_LIST_FOR_EACH(FFstrbuf, item, *results)
ffStrbufDestroy(item);
ffListClear(results);
}
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
@@ -38,7 +52,90 @@ const char* ffDetectDNS(FFDNSOptions* options, FFlist* results)
FFstrbuf* item = (FFstrbuf*) ffListAdd(results);
ffStrbufInitS(item, nameserver);
ffStrbufTrimRightSpace(item);
FF_DEBUG("Found DNS server: %s", item->chars);
}
}
FF_DEBUG("Found %u DNS servers in %s", results->length, path);
return NULL;
}
const char* ffDetectDNS(FFDNSOptions* options, FFlist* results)
{
FF_DEBUG("Starting DNS detection");
const char* error = detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT RESOLV_CONF, options, results);
if (error != NULL)
{
FF_DEBUG("Error detecting DNS: %s", error);
return error;
}
#if __linux__ && !__ANDROID__
// Handle different DNS management services
if (results->length == 1)
{
const FFstrbuf* firstEntry = FF_LIST_GET(FFstrbuf, *results, 0);
if (ffStrbufEqualS(firstEntry, "127.0.0.53"))
{
FF_DEBUG("Detected systemd-resolved (127.0.0.53), checking actual DNS servers");
// Managed by systemd-resolved
if (detectDnsFromConf("/run/systemd/resolve/resolv.conf", options, results) == NULL)
return NULL;
}
else if (ffStrbufEqualS(firstEntry, "127.0.0.1"))
{
FF_DEBUG("Detected possible NetworkManager (127.0.0.1), checking actual DNS servers");
// Managed by NetworkManager
if (detectDnsFromConf("/var/run/NetworkManager/resolv.conf", options, results) == NULL)
return NULL;
}
}
// Check other possible DNS configuration files
if (results->length == 0)
{
FF_DEBUG("No DNS servers found, trying alternative config files");
// Try resolvconf
FF_DEBUG("Trying resolvconf configuration");
if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/run/resolvconf/resolv.conf", options, results) == NULL && results->length > 0)
return NULL;
// Try dnsmasq
FF_DEBUG("Trying dnsmasq configuration");
if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/var/run/dnsmasq/resolv.conf", options, results) == NULL && results->length > 0)
return NULL;
// Try openresolv
FF_DEBUG("Trying openresolv configuration");
if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf.openresolv", options, results) == NULL && results->length > 0)
return NULL;
}
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__)
// Handle BSD-specific DNS configurations
if (results->length == 0)
{
FF_DEBUG("No DNS servers found, trying BSD-specific config files");
// FreeBSD and other BSDs may use resolvconf service
FF_DEBUG("Trying BSD resolvconf configuration");
if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/var/run/resolvconf/resolv.conf", options, results) == NULL && results->length > 0)
return NULL;
// Some BSDs store DNS configuration here
FF_DEBUG("Trying BSD nameserver configuration");
if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/var/run/nameserver", options, results) == NULL && results->length > 0)
return NULL;
// Try common BSD paths
FF_DEBUG("Trying BSD common paths");
if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/etc/nameserver", options, results) == NULL && results->length > 0)
return NULL;
}
#endif
FF_DEBUG("DNS detection completed with %u servers found", results->length);
return NULL;
}
+1
View File
@@ -10,6 +10,7 @@
#ifdef _WIN32
static inline char* realpath(const char* restrict file_name, char* restrict resolved_name)
{
assert(resolved_name != NULL);
return _fullpath(resolved_name, file_name, _MAX_PATH);
}
#endif
+7 -2
View File
@@ -20,8 +20,12 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
{
snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) continue;
if (fd < 0)
{
if (errno == ENOENT)
break; // No more devices
continue; // Device not found
}
report_desc_t repDesc = hid_get_report_desc(fd);
if (!repDesc) continue;
@@ -53,6 +57,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
device->battery = 0;
}
}
hid_end_parse(hData);
}
hid_dispose_report_desc(repDesc);
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#include "3rdparty/display-library/adl_sdk.h"
// https://gpuopen-librariesandsdks.github.io/adl/modules.html
// Function to initialize the ADL2 interface and to obtain client's context handle.
extern int ADL2_Main_Control_Create(ADL_MAIN_MALLOC_CALLBACK callback, int iEnumConnectedAdapters, ADL_CONTEXT_HANDLE* context);
// Destroy client's ADL context.
extern int ADL2_Main_Control_Destroy(ADL_CONTEXT_HANDLE context);
// Retrieves adapter information for given adapter or all OS-known adapters.
// Return ADL_OK on success, DESPITE THE OFFICIAL DOCUMENT SAYS IT RETURNS 1 FOR SUCCESS!
extern int ADL2_Adapter_AdapterInfoX3_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* numAdapters, AdapterInfo** lppAdapterInfo);
// Function to retrieve Graphic Core Info.
extern int ADL2_Adapter_Graphic_Core_Info_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLGraphicCoreInfo* pGraphicCoreInfo);
// Function to retrieve memory information from the adapter. Version 2
extern int ADL2_Adapter_MemoryInfo2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLMemoryInfo2* lpMemoryInfo2);
// This function retrieves the VRAM usage of given adapter.
extern int ADL2_Adapter_VRAMUsage_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iVRAMUsageInMB);
// This function retrieves the Dedicated VRAM usage of given adapter.
extern int ADL2_Adapter_DedicatedVRAMUsage_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iVRAMUsageInMB);
// Function to get the ASICFamilyType from the adapter.
extern int ADL2_Adapter_ASICFamilyType_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpAsicTypes, int* lpValids);
// Function to retrieve current power management capabilities.
extern int ADL2_Overdrive_Caps(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iSupported, int* iEnabled, int* iVersion);
/////////// Overdrive 6 functions
// Function to retrieve current Overdrive and performance-related activity.
extern int ADL2_Overdrive6_CurrentStatus_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLOD6CurrentStatus* lpCurrentStatus);
// Function to retrieve GPU temperature from the thermal controller.
extern int ADL2_Overdrive6_Temperature_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* lpTemperature);
// Function to retrieve the current or default Overdrive clock ranges.
extern int ADL2_Overdrive6_StateInfo_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iStateType, ADLOD6StateInfo* lpStateInfo);
/// Overdrive N functions
// Despite the name (N means Next), this is actually Overdrive7 API
// https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Sample/OverdriveN/OverdriveN.cpp#L209
// Function to retrieve the OverdriveN capabilities.
extern int ADL2_OverdriveN_CapabilitiesX2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNCapabilitiesX2* lpODCapabilities);
// Function to retrieve the current OD performance status.
extern int ADL2_OverdriveN_PerformanceStatus_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNPerformanceStatus *lpODPerformanceStatus);
// Function to retrieve the current temperature.
extern int ADL2_OverdriveN_Temperature_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int iTemperatureType, int *iTemperature);
// Function to retrieve the current GPU clocks settings.
extern int ADL2_OverdriveN_SystemClocksX2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLODNPerformanceLevelsX2 *lpODPerformanceLevels);
/// Overdrive 8 functions
// Function to retrieve the Overdrive8 current settings.
extern int ADL2_Overdrive8_Current_Setting_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLOD8CurrentSetting *lpCurrentSetting);
// Function to retrieve the Overdrive8 current settings.
extern int ADL2_New_QueryPMLogData_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLPMLogDataOutput *lpDataOutput);
+1
View File
@@ -55,6 +55,7 @@ const char* detectByOpenGL(FFlist* gpus)
ffStrbufInitMove(&gpu->name, &result.renderer);
ffStrbufInit(&gpu->driver);
ffStrbufInitF(&gpu->platformApi, "OpenGL %s", result.version.chars);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
+1
View File
@@ -34,6 +34,7 @@ typedef struct FFGPUResult
FFstrbuf name;
FFstrbuf driver;
FFstrbuf platformApi;
FFstrbuf memoryType;
double temperature;
double coreUsage;
int32_t coreCount;
+505 -35
View File
@@ -1,75 +1,545 @@
#include "gpu_driver_specific.h"
// Everything detected in this file is static.
// The real time monitoring requires ADLX, whose interface is much more complicated than AGS
// Whoever has AMD graphic cards interested in this may contribute
// * ADLX (AMD Device Library eXtra): https://github.com/GPUOpen-LibrariesAndSDKs/ADLX
#include "3rdparty/ags/amd_ags.h"
#include "adl.h"
#include "common/library.h"
#include "util/mallocHelper.h"
#include "util/debug.h"
// Helper function to convert ADL status code to string
FF_MAYBE_UNUSED static const char* ffAdlStatusToString(int status) {
switch (status) {
#define FF_ADL_STATUS_CASE(name) case name: return #name;
FF_ADL_STATUS_CASE(ADL_OK)
FF_ADL_STATUS_CASE(ADL_OK_WARNING)
FF_ADL_STATUS_CASE(ADL_OK_MODE_CHANGE)
FF_ADL_STATUS_CASE(ADL_OK_RESTART)
FF_ADL_STATUS_CASE(ADL_OK_WAIT)
FF_ADL_STATUS_CASE(ADL_ERR)
FF_ADL_STATUS_CASE(ADL_ERR_NOT_INIT)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_PARAM)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_PARAM_SIZE)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_ADL_IDX)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_CONTROLLER_IDX)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_DIPLAY_IDX)
FF_ADL_STATUS_CASE(ADL_ERR_NOT_SUPPORTED)
FF_ADL_STATUS_CASE(ADL_ERR_NULL_POINTER)
FF_ADL_STATUS_CASE(ADL_ERR_DISABLED_ADAPTER)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_CALLBACK)
FF_ADL_STATUS_CASE(ADL_ERR_RESOURCE_CONFLICT)
FF_ADL_STATUS_CASE(ADL_ERR_SET_INCOMPLETE)
FF_ADL_STATUS_CASE(ADL_ERR_NO_XDISPLAY)
FF_ADL_STATUS_CASE(ADL_ERR_CALL_TO_INCOMPATIABLE_DRIVER)
FF_ADL_STATUS_CASE(ADL_ERR_NO_ADMINISTRATOR_PRIVILEGES)
FF_ADL_STATUS_CASE(ADL_ERR_FEATURESYNC_NOT_STARTED)
FF_ADL_STATUS_CASE(ADL_ERR_INVALID_POWER_STATE)
#undef FF_ADL_STATUS_CASE
default: return "Unknown ADL error";
}
}
// Memory allocation function
static void* __attribute__((__stdcall__)) ffAdlMainMemoryAlloc(int iSize)
{
return malloc((size_t) iSize);
}
struct FFAdlData {
FF_LIBRARY_SYMBOL(ADL2_Main_Control_Destroy)
FF_LIBRARY_SYMBOL(ADL2_Adapter_AdapterInfoX3_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_Graphic_Core_Info_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_VRAMUsage_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive_Caps)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_CapabilitiesX2_Get)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_SystemClocksX2_Get)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_PerformanceStatus_Get)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_Temperature_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive8_Current_Setting_Get)
FF_LIBRARY_SYMBOL(ADL2_New_QueryPMLogData_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive6_CurrentStatus_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive6_Temperature_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive6_StateInfo_Get)
bool inited;
ADL_CONTEXT_HANDLE apiHandle;
} adlData;
static void shutdownAdl()
{
if (adlData.apiHandle)
{
FF_DEBUG("Destroying ADL context");
adlData.ffADL2_Main_Control_Destroy(adlData.apiHandle);
adlData.apiHandle = NULL;
}
}
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
{
static bool inited = false;
static AGSGPUInfo gpuInfo;
FF_DEBUG("Attempting to detect AMD GPU info using '%s'", soName);
if (!inited)
if (!adlData.inited)
{
inited = true;
FF_LIBRARY_LOAD(libags, "dlopen amd_ags failed", soName , 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libags, agsInitialize)
adlData.inited = true;
FF_DEBUG("Initializing ADL library");
FF_LIBRARY_LOAD(atiadl, "dlopen atiadlxx failed", soName , 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(atiadl, ADL2_Main_Control_Create)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Main_Control_Destroy)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_AdapterInfoX3_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_Graphic_Core_Info_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_VRAMUsage_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive_Caps)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_CapabilitiesX2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_SystemClocksX2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_PerformanceStatus_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive8_Current_Setting_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_New_QueryPMLogData_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_Temperature_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_CurrentStatus_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_Temperature_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_StateInfo_Get)
FF_DEBUG("ADL library loaded");
struct AGSContext* apiHandle;
if (ffagsInitialize(AGS_CURRENT_VERSION, NULL, &apiHandle, &gpuInfo) != AGS_SUCCESS)
return "loading ags library failed";
int result = ffADL2_Main_Control_Create(ffAdlMainMemoryAlloc, 1 /*iEnumConnectedAdapters*/, &adlData.apiHandle);
FF_DEBUG("ADL2_Main_Control_Create returned %s (%d)", ffAdlStatusToString(result), result);
if (result != ADL_OK)
return "ffADL2_Main_Control_Create() failed";
// agsDeInitialize will free pointers allocated in gpuInfo. Just leak them.
atexit(shutdownAdl);
atiadl = NULL; // don't close atiadl
FF_DEBUG("ADL initialization complete");
}
if (gpuInfo.numDevices == 0)
return "loading ags library failed or no AMD gpus found";
AGSDeviceInfo* device = NULL;
for (int iDev = 0; iDev < gpuInfo.numDevices; iDev++)
if (!adlData.apiHandle)
{
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
FF_DEBUG("ADL context not initialized");
return "ffADL2_Main_Control_Create() failed";
}
FF_AUTO_FREE AdapterInfo* devices = NULL;
int numDevices = 0;
int adapterResult = adlData.ffADL2_Adapter_AdapterInfoX3_Get(adlData.apiHandle, -1, &numDevices, &devices);
FF_DEBUG("ADL2_Adapter_AdapterInfoX3_Get returned %s (%d)", ffAdlStatusToString(adapterResult), adapterResult);
if (adapterResult == ADL_OK)
{
FF_DEBUG("found %d adapters", numDevices);
}
else
{
FF_DEBUG("ffADL2_Adapter_AdapterInfoX3_Get() failed");
return "ffADL2_Adapter_AdapterInfoX3_Get() failed";
}
const AdapterInfo* device = NULL;
for (int iDev = 0; iDev < numDevices; iDev++)
{
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
FF_DEBUG("Checking device %d: bus=%d, device=%d, func=%d against requested bus=%u, device=%u, func=%u",
iDev, devices[iDev].iBusNumber, devices[iDev].iDeviceNumber, devices[iDev].iFunctionNumber,
cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
if (
cond->pciDeviceId.deviceId == (uint32_t) gpuInfo.devices[iDev].deviceId &&
cond->pciDeviceId.vendorId == (uint32_t) gpuInfo.devices[iDev].vendorId &&
cond->pciDeviceId.revId == (uint32_t) gpuInfo.devices[iDev].revisionId)
cond->pciBusId.bus == (uint32_t) devices[iDev].iBusNumber &&
cond->pciBusId.device == (uint32_t) devices[iDev].iDeviceNumber &&
cond->pciBusId.func == (uint32_t) devices[iDev].iFunctionNumber)
{
device = &gpuInfo.devices[iDev];
device = &devices[iDev];
FF_DEBUG("Found matching device: %s (index: %d)", device->strAdapterName, device->iAdapterIndex);
break;
}
}
}
if (!device)
{
FF_DEBUG("Device not found");
return "Device not found";
}
if (result.coreCount)
*result.coreCount = (uint32_t) device->numCUs;
{
ADLGraphicCoreInfo coreInfo;
int status = adlData.ffADL2_Adapter_Graphic_Core_Info_Get(adlData.apiHandle, device->iAdapterIndex, &coreInfo);
FF_DEBUG("ADL2_Adapter_Graphic_Core_Info_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
FF_DEBUG("Core info - NumCUs: %d, NumPEsPerCU: %d", coreInfo.iNumCUs, coreInfo.iNumPEsPerCU);
*result.coreCount = (uint32_t) coreInfo.iNumCUs * (uint32_t) coreInfo.iNumPEsPerCU;
FF_DEBUG("Got core count: %u", *result.coreCount);
}
else
{
FF_DEBUG("Failed to get core count");
}
}
if (result.memory)
{
result.memory->total = device->localMemoryInBytes;
result.memory->used = FF_GPU_VMEM_SIZE_UNSET;
int vramUsage = 0;
int status = adlData.ffADL2_Adapter_DedicatedVRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage);
FF_DEBUG("ADL2_Adapter_DedicatedVRAMUsage_Get returned %s (%d), usage: %d MB",
ffAdlStatusToString(status), status, vramUsage);
if (status == ADL_OK) {
result.memory->used = (uint64_t) vramUsage * 1024 * 1024;
FF_DEBUG("Dedicated VRAM usage: %llu bytes (%d MB)", result.memory->used, vramUsage);
} else {
FF_DEBUG("Failed to get dedicated VRAM usage");
}
if (result.sharedMemory)
{
vramUsage = 0;
status = adlData.ffADL2_Adapter_VRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage);
FF_DEBUG("ADL2_Adapter_VRAMUsage_Get returned %s (%d), usage: %d MB",
ffAdlStatusToString(status), status, vramUsage);
if (status == ADL_OK) {
uint64_t totalUsage = (uint64_t) vramUsage * 1024 * 1024;
result.sharedMemory->used = totalUsage - result.memory->used;
FF_DEBUG("Total VRAM usage: %llu bytes, Shared VRAM usage: %llu bytes (%llu MB)",
totalUsage, result.sharedMemory->used, result.sharedMemory->used / (1024 * 1024));
} else {
FF_DEBUG("Failed to get total VRAM usage");
}
}
}
if (result.frequency)
*result.frequency = (uint32_t) device->coreClock; // Maximum frequency
if (result.memoryType)
{
ADLMemoryInfo2 memoryInfo;
int status = adlData.ffADL2_Adapter_MemoryInfo2_Get(adlData.apiHandle, device->iAdapterIndex, &memoryInfo);
FF_DEBUG("ADL2_Adapter_MemoryInfo2_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
FF_DEBUG("Memory info - Type: %s, Size: %lld MB", memoryInfo.strMemoryType, memoryInfo.iMemorySize / 1024 / 1024);
ffStrbufSetS(result.memoryType, memoryInfo.strMemoryType);
FF_DEBUG("Got memory type: %s", memoryInfo.strMemoryType);
}
else
{
FF_DEBUG("Failed to get memory type");
}
}
if (result.type)
*result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
{
int asicTypes = 0;
int valids = 0;
int status = adlData.ffADL2_Adapter_ASICFamilyType_Get(adlData.apiHandle, device->iAdapterIndex, &asicTypes, &valids);
FF_DEBUG("ADL2_Adapter_ASICFamilyType_Get returned %s (%d), asicTypes: 0x%x, valids: 0x%x",
ffAdlStatusToString(status), status, asicTypes, valids);
if (status == ADL_OK)
{
asicTypes &= valids; // This design is strange
*result.type = asicTypes & ADL_ASIC_INTEGRATED ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
FF_DEBUG("GPU type: %s (asicTypes: 0x%x, valids: 0x%x)",
*result.type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete", asicTypes, valids);
}
else
{
FF_DEBUG("Failed to get GPU type");
}
}
if (result.index)
*result.index = (uint32_t) device->adlAdapterIndex;
{
*result.index = (uint32_t) device->iAdapterIndex;
FF_DEBUG("Setting adapter index: %u", *result.index);
}
if (result.name)
ffStrbufSetS(result.name, device->adapterString);
{
ffStrbufSetS(result.name, device->strAdapterName);
FF_DEBUG("Setting adapter name: %s; UDID: %s, Present: %d, Exist: %d", device->strAdapterName, device->strUDID, device->iPresent, device->iExist);
}
int odVersion = 0;
{
int odSupported = 0;
int odEnabled = 0;
int status = adlData.ffADL2_Overdrive_Caps(adlData.apiHandle, device->iAdapterIndex, &odSupported, &odEnabled, &odVersion);
FF_DEBUG("ADL2_Overdrive_Caps returned %s (%d); supported %d, enabled %d; version %d",
ffAdlStatusToString(status), status, odSupported, odEnabled, odVersion);
if (status != ADL_OK)
{
FF_DEBUG("Overdrive not supported, results may be inaccurate");
// Note even if Overdrive is not supported, we can still get the OD version
}
}
if (odVersion == 8)
{
FF_DEBUG("Using Overdrive8 API (odVersion=%d)", odVersion);
if (result.frequency)
{
ADLOD8CurrentSetting currentSetting = { .count = OD8_COUNT };
int status = adlData.ffADL2_Overdrive8_Current_Setting_Get(adlData.apiHandle, device->iAdapterIndex, &currentSetting);
FF_DEBUG("ADL2_Overdrive8_Current_Setting_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
FF_DEBUG("OD8 Settings count: %d", currentSetting.count);
*result.frequency = (uint32_t) currentSetting.Od8SettingTable[OD8_GFXCLK_FMAX];
FF_DEBUG("Got max engine clock (OD8_GFXCLK_FMAX): %u MHz", *result.frequency);
}
else
{
FF_DEBUG("Failed to get max frequency information");
}
}
if (result.temp || result.coreUsage)
{
ADLPMLogDataOutput pmLogDataOutput = {};
int status = adlData.ffADL2_New_QueryPMLogData_Get(adlData.apiHandle, device->iAdapterIndex, &pmLogDataOutput);
FF_DEBUG("ADL2_New_QueryPMLogData_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (result.temp)
{
ADLSingleSensorData* sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_HOTSPOT];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_HOTSPOT, "ADL_PMLOG_TEMPERATURE_HOTSPOT", sensor->supported, sensor->value);
if (sensor->supported)
{
*result.temp = sensor->value;
FF_DEBUG("Temperature: %.1f°C (HOTSPOT)", *result.temp);
}
else
{
sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_GFX];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_GFX, "ADL_PMLOG_TEMPERATURE_GFX", sensor->supported, sensor->value);
if (sensor->supported)
{
*result.temp = sensor->value;
FF_DEBUG("Temperature: %.1f°C (GFX)", *result.temp);
}
else
{
sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_SOC];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_SOC, "ADL_PMLOG_TEMPERATURE_SOC", sensor->supported, sensor->value);
if (sensor->supported)
{
*result.temp = sensor->value;
FF_DEBUG("Temperature: %.1f°C (SOC)", *result.temp);
}
else
{
FF_DEBUG("No supported temp sensor found, temp detection failed");
}
}
}
}
if (result.coreUsage)
{
ADLSingleSensorData* activity = &pmLogDataOutput.sensors[ADL_PMLOG_INFO_ACTIVITY_GFX];
FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_INFO_ACTIVITY_GFX, "ADL_PMLOG_INFO_ACTIVITY_GFX", activity->supported, activity->value);
if (activity->supported)
{
*result.coreUsage = activity->value;
FF_DEBUG("Core usage: %.1f%%", *result.coreUsage);
}
else
{
FF_DEBUG("Sensor %d not supported, GPU usage detection failed", ADL_PMLOG_INFO_ACTIVITY_GFX);
}
}
}
else
{
FF_DEBUG("Failed to get temperature / GPU activity");
}
}
}
else if (odVersion == 7)
{
FF_DEBUG("Using OverdriveN API (odVersion=%d)", odVersion);
if (result.frequency)
{
// https://github.com/MaynardMiner/odvii/blob/master/OverdriveN.cpp#L176
ADLODNCapabilitiesX2 odCapabilities = {};
int status = adlData.ffADL2_OverdriveN_CapabilitiesX2_Get(adlData.apiHandle, device->iAdapterIndex, &odCapabilities);
FF_DEBUG("ADL2_OverdriveN_CapabilitiesX2_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
if (odCapabilities.iMaximumNumberOfPerformanceLevels == 0)
{
FF_DEBUG("ADL2_OverdriveN_CapabilitiesX2_Get: no performance levels available");
}
else
{
FF_DEBUG("ODN Capabilities - MaxPerformanceLevels: %d, GPU Clock Range: [%d - %d]",
odCapabilities.iMaximumNumberOfPerformanceLevels,
odCapabilities.sEngineClockRange.iMin, odCapabilities.sEngineClockRange.iMax);
size_t size = sizeof(ADLODNPerformanceLevelsX2) + sizeof(ADLODNPerformanceLevelX2) * ((unsigned) odCapabilities.iMaximumNumberOfPerformanceLevels - 1);
FF_AUTO_FREE ADLODNPerformanceLevelsX2* odPerfLevels = calloc(size, 1);
odPerfLevels->iSize = (int) size;
odPerfLevels->iNumberOfPerformanceLevels = odCapabilities.iMaximumNumberOfPerformanceLevels;
odPerfLevels->iMode = ODNControlType_Current;
int status = adlData.ffADL2_OverdriveN_SystemClocksX2_Get(adlData.apiHandle, device->iAdapterIndex, odPerfLevels);
FF_DEBUG("ADL2_OverdriveN_SystemClocksX2_Get returned %s (%d), levels: %d",
ffAdlStatusToString(status), status, odPerfLevels->iNumberOfPerformanceLevels);
if (status != ADL_OK)
{
FF_DEBUG("Failed to get frequency information");
}
else
{
// lowest to highest
for (int i = odPerfLevels->iNumberOfPerformanceLevels - 1; i >= 0 ; i--)
{
ADLODNPerformanceLevelX2* level = &odPerfLevels->aLevels[i];
FF_DEBUG("Performance level %d: enabled: %d, engine clock = %d", i, level->iEnabled, level->iClock);
if (level->iEnabled)
{
*result.frequency = (uint32_t) level->iClock / 100; // in 10 kHz
FF_DEBUG("Got max engine clock: %u MHz", *result.frequency);
break;
}
}
}
}
}
else
{
FF_DEBUG("Failed to get frequency information");
}
}
if (result.coreUsage)
{
ADLODNPerformanceStatus performanceStatus = {};
int status = adlData.ffADL2_OverdriveN_PerformanceStatus_Get(adlData.apiHandle, device->iAdapterIndex, &performanceStatus);
FF_DEBUG("ADL2_OverdriveN_PerformanceStatus_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
FF_DEBUG("Performance Status - Activity: %d%%, CoreClock: %dMHz, MemoryClock: %dMHz",
performanceStatus.iGPUActivityPercent,
performanceStatus.iCoreClock,
performanceStatus.iMemoryClock);
*result.coreUsage = performanceStatus.iGPUActivityPercent;
FF_DEBUG("Got GPU activity: %d%%", performanceStatus.iGPUActivityPercent);
}
else
{
FF_DEBUG("Failed to get GPU activity");
}
}
if (result.temp)
{
int milliDegrees = 0;
int status = adlData.ffADL2_OverdriveN_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, 1, &milliDegrees);
FF_DEBUG("ADL2_OverdriveN_Temperature_Get returned %s (%d)", ffAdlStatusToString(status), status);
if (status == ADL_OK)
{
*result.temp = milliDegrees / 1000.0;
FF_DEBUG("Temperature: %.1f°C (raw: %d milliC)", *result.temp, milliDegrees);
}
else
{
FF_DEBUG("Failed to get temperature");
}
}
}
else if (odVersion == 6)
{
FF_DEBUG("Using Overdrive6 API (odVersion=%d)", odVersion);
if (result.frequency)
{
FF_AUTO_FREE ADLOD6StateInfo* stateInfo = calloc(sizeof(ADLOD6StateInfo) + sizeof(ADLOD6PerformanceLevel), 1);
stateInfo->iNumberOfPerformanceLevels = 2;
int status = adlData.ffADL2_Overdrive6_StateInfo_Get(adlData.apiHandle, device->iAdapterIndex, ADL_OD6_GETSTATEINFO_CUSTOM_PERFORMANCE, stateInfo);
FF_DEBUG("ADL2_Overdrive6_StateInfo_Get returned %s (%d), performance levels: %d",
ffAdlStatusToString(status), status, stateInfo->iNumberOfPerformanceLevels);
if (status == ADL_OK)
{
// OD6 uses clock ranges instead of discrete performance levels.
// iNumberOfPerformanceLevels is always 2.
// The 1st level indicates the minimum clocks in the range.
// The 2nd level indicates the maximum clocks in the range.
if (stateInfo->iNumberOfPerformanceLevels != 2)
{
FF_DEBUG("ADL2_Overdrive6_StateInfo_Get: unexpected number of performance levels: %d", stateInfo->iNumberOfPerformanceLevels);
}
else
{
FF_DEBUG("OD6 Settings - MinPerformanceLevels: %d, MaxPerformanceLevels: %d",
stateInfo->aLevels[0].iEngineClock, stateInfo->aLevels[1].iEngineClock);
*result.frequency = (uint32_t) stateInfo->aLevels[1].iEngineClock / 100; // in 10 kHz
FF_DEBUG("Got max engine clock: %u MHz", *result.frequency);
}
}
else
{
FF_DEBUG("Failed to get frequency information");
}
}
if (result.coreUsage)
{
ADLOD6CurrentStatus status = {};
int apiStatus = adlData.ffADL2_Overdrive6_CurrentStatus_Get(adlData.apiHandle, device->iAdapterIndex, &status);
FF_DEBUG("ADL2_Overdrive6_CurrentStatus_Get returned %s (%d)", ffAdlStatusToString(apiStatus), apiStatus);
if (apiStatus == ADL_OK)
{
*result.coreUsage = status.iActivityPercent;
FF_DEBUG("Got GPU activity: %d%%", status.iActivityPercent);
}
else
{
FF_DEBUG("Failed to get GPU activity");
}
}
if (result.temp)
{
int milliDegrees = 0;
int status = adlData.ffADL2_Overdrive6_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, &milliDegrees);
FF_DEBUG("ADL2_Overdrive6_Temperature_Get returned %s (%d), temperature: %d milliC",
ffAdlStatusToString(status), status, milliDegrees);
if (status == ADL_OK)
{
*result.temp = milliDegrees / 1000.0;
FF_DEBUG("Temperature: %.1f°C", *result.temp);
}
else
{
FF_DEBUG("Failed to get temperature");
}
}
}
else
{
FF_DEBUG("Unknown Overdrive version: %d", odVersion);
return "Unknown Overdrive version";
}
FF_DEBUG("AMD GPU detection complete - returning success");
return NULL;
}
+13 -11
View File
@@ -18,11 +18,12 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
{
switch (strtol(gpuName->chars + strlen("Apple M"), NULL, 10))
{
case 0: error = "Invalid Apple Silicon GPU"; break;
case 1: error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result); break;
case 2: error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result); break;
case 3: error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result); break;
case 4: error = ffDetectSmcTemps(FF_TEMP_GPU_M4X, &result); break;
default: error = "Unsupported Apple Silicon GPU";
default: error = "Unsupported Apple Silicon GPU"; break;
}
}
else if (ffStrbufStartsWithS(gpuName, "Intel"))
@@ -102,7 +103,8 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
}
FFGPUResult* gpu = ffListAdd(gpus);
gpu->index = FF_GPU_INDEX_UNSET;
ffStrbufInit(&gpu->memoryType);
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
@@ -112,7 +114,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount) != NULL) // For Apple
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
@@ -131,9 +133,9 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
if (ffCfDictGetInt64(perfStatistics, CFSTR("In use system memory"), (int64_t*) &vramUsed) != NULL)
vramTotal = 0;
}
else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramTotal) == NULL)
else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramUsed) == NULL)
if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramUsed) == NULL)
vramTotal += vramUsed;
else
vramTotal = 0;
@@ -143,15 +145,15 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->name);
//IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs.
//Still needs testing for AMD's
if(ffCfDictGetString(properties, CFSTR("model"), &gpu->name))
if(ffCfDictGetString(properties, CFSTR("model"), &gpu->name) != NULL)
{
CFRelease(properties);
properties = NULL;
io_registry_entry_t parentEntry;
IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parentEntry);
if(IORegistryEntryCreateCFProperties(parentEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t parentEntry = 0;
if(IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parentEntry) != kIOReturnSuccess ||
IORegistryEntryCreateCFProperties(parentEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(parentEntry);
IOObjectRelease(registryEntry);
continue;
}
@@ -179,7 +181,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
gpu->shared.total = vramTotal;
gpu->shared.used = vramUsed;
}
else
else if (gpu->type == FF_GPU_TYPE_DISCRETE)
{
gpu->dedicated.total = vramTotal;
gpu->dedicated.used = vramUsed;
+1
View File
@@ -29,6 +29,7 @@ const char* ffGpuDetectDriverVersion(FFlist* gpus)
ffStrbufAppendS(&x->driver, version.UTF8String);
}
}
return NULL;
}
return "Unsupported macOS version";
}
+6 -2
View File
@@ -13,6 +13,9 @@
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
if (fd < 0)
return "open(\"/dev/pci\", O_RDONLY, 0) failed";
struct pci_conf confs[128];
struct pci_match_conf match = {
.pc_class = PCIC_DISPLAY,
@@ -40,7 +43,8 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(pc->pc_vendor));
ffStrbufInit(&gpu->name);
ffStrbufInitS(&gpu->driver, pc->pd_name);
ffStrbufInit(&gpu->platformApi);
ffStrbufInitStatic(&gpu->platformApi, "/dev/pci");
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
@@ -77,7 +81,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
ffGPUQueryAmdGpuName(pc->pc_device, pc->pc_revid, gpu);
if (gpu->name.length == 0)
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
+4 -2
View File
@@ -41,6 +41,8 @@ typedef struct FFGpuDriverResult
uint32_t* index;
double* temp;
FFGPUMemory* memory;
FFstrbuf* memoryType;
FFGPUMemory* sharedMemory;
uint32_t* coreCount;
double* coreUsage;
FFGPUType* type;
@@ -87,9 +89,9 @@ FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vend
{
*pDetectFn = ffDetectAmdGpuInfo;
#ifdef _WIN64
*pDllName = "amd_ags_x64.dll";
*pDllName = "atiadlxx.dll";
#else
*pDllName = "amd_ags_x86.dll";
*pDllName = "atiadlxy.dll";
#endif
}
#endif
+3 -4
View File
@@ -33,7 +33,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->vendor_id));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
ffStrbufInitStatic(&gpu->platformApi, "libpciaccess");
ffStrbufInit(&gpu->memoryType);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
@@ -46,9 +47,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffGPUQueryAmdGpuName(dev->device_id, dev->revision, gpu);
if (gpu->name.length == 0)
{
ffGPUFillVendorAndName((dev->device_class >> 8) & 8, dev->vendor_id, dev->device_id, gpu);
}
ffGPUFillVendorAndName((dev->device_class >> 8) & 0xFF, dev->vendor_id, dev->device_id, gpu);
}
ffpci_system_cleanup();
+2 -1
View File
@@ -23,7 +23,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev.vendor_id));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
ffStrbufInitStatic(&gpu->platformApi, POKE_DEVICE_FULLNAME);
ffStrbufInit(&gpu->memoryType);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
+51 -6
View File
@@ -12,6 +12,7 @@ struct FFIgclData {
FF_LIBRARY_SYMBOL(ctlEnumTemperatureSensors)
FF_LIBRARY_SYMBOL(ctlTemperatureGetState)
FF_LIBRARY_SYMBOL(ctlEnumMemoryModules)
FF_LIBRARY_SYMBOL(ctlMemoryGetProperties)
FF_LIBRARY_SYMBOL(ctlMemoryGetState)
FF_LIBRARY_SYMBOL(ctlEnumFrequencyDomains)
FF_LIBRARY_SYMBOL(ctlFrequencyGetProperties)
@@ -42,6 +43,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumTemperatureSensors)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlTemperatureGetState)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumMemoryModules)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetProperties)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumFrequencyDomains)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetProperties)
@@ -135,14 +137,56 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
result.memory->total = 0;
for (uint32_t iMem = 0; iMem < memoryCount; iMem++)
{
ctl_mem_state_t memoryState = {
.Size = sizeof(ctl_mem_state_t),
ctl_mem_properties_t memoryProperties = {
.Size = sizeof(memoryProperties),
.Version = 0,
};
if (igclData.ffctlMemoryGetState(memoryModules[iMem], &memoryState) == CTL_RESULT_SUCCESS)
if (igclData.ffctlMemoryGetProperties(memoryModules[iMem], &memoryProperties) == CTL_RESULT_SUCCESS)
{
result.memory->total += memoryState.size;
result.memory->used += memoryState.size - memoryState.free;
if (memoryProperties.location == CTL_MEM_LOC_DEVICE && result.memoryType)
{
switch (memoryProperties.type)
{
#define FF_ICTL_MEM_TYPE_CASE(type) case CTL_MEM_TYPE_##type: ffStrbufSetStatic(result.memoryType, #type); break
FF_ICTL_MEM_TYPE_CASE(HBM);
FF_ICTL_MEM_TYPE_CASE(DDR);
FF_ICTL_MEM_TYPE_CASE(DDR3);
FF_ICTL_MEM_TYPE_CASE(DDR4);
FF_ICTL_MEM_TYPE_CASE(DDR5);
FF_ICTL_MEM_TYPE_CASE(LPDDR);
FF_ICTL_MEM_TYPE_CASE(LPDDR3);
FF_ICTL_MEM_TYPE_CASE(LPDDR4);
FF_ICTL_MEM_TYPE_CASE(LPDDR5);
FF_ICTL_MEM_TYPE_CASE(GDDR4);
FF_ICTL_MEM_TYPE_CASE(GDDR5);
FF_ICTL_MEM_TYPE_CASE(GDDR5X);
FF_ICTL_MEM_TYPE_CASE(GDDR6);
FF_ICTL_MEM_TYPE_CASE(GDDR6X);
FF_ICTL_MEM_TYPE_CASE(GDDR7);
#undef FF_ICTL_MEM_TYPE_CASE
default:
ffStrbufSetF(result.memoryType, "Unknown (%u)", memoryProperties.type);
break;
}
}
ctl_mem_state_t memoryState = {
.Size = sizeof(ctl_mem_state_t),
.Version = 0,
};
if (igclData.ffctlMemoryGetState(memoryModules[iMem], &memoryState) == CTL_RESULT_SUCCESS)
{
if (memoryProperties.location == CTL_MEM_LOC_DEVICE)
{
result.memory->total += memoryState.size;
result.memory->used += memoryState.size - memoryState.free;
}
else if (result.sharedMemory && memoryProperties.location == CTL_MEM_LOC_SYSTEM)
{
result.sharedMemory->total += memoryState.size;
result.sharedMemory->used += memoryState.size - memoryState.free;
}
}
}
}
}
@@ -171,7 +215,8 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe
availableCount++;
}
}
*result.temp = sumValue / availableCount;
if (availableCount > 0)
*result.temp = sumValue / availableCount;
}
}
+5 -1
View File
@@ -426,7 +426,9 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
}
else
{
pPciPath = memrchr(deviceDir->chars, '/', deviceDir->length) + 1;
pPciPath = memrchr(deviceDir->chars, '/', deviceDir->length);
assert(pPciPath);
pPciPath++;
}
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
@@ -438,6 +440,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
@@ -632,6 +635,7 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->memoryType);
ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
+127 -15
View File
@@ -21,6 +21,108 @@ struct FFNvmlData {
bool inited;
} nvmlData;
#if defined(_WIN32) && !defined(FF_DISABLE_DLOPEN)
#include "nvapi.h"
struct FFNvapiData {
FF_LIBRARY_SYMBOL(nvapi_Unload)
FF_LIBRARY_SYMBOL(nvapi_EnumPhysicalGPUs)
FF_LIBRARY_SYMBOL(nvapi_GPU_GetRamType)
bool inited;
} nvapiData;
static const char* detectMemTypeByNvapi(FFGpuDriverResult* result)
{
if (!nvapiData.inited)
{
nvapiData.inited = true;
FF_LIBRARY_LOAD(libnvapi, "dlopen nvapi failed",
#ifdef _WIN64
"nvapi64.dll"
#else
"nvapi.dll"
#endif
, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvapi, nvapi_QueryInterface)
#define FF_NVAPI_INTERFACE(iName, iOffset) \
__typeof__(&iName) ff ## iName = ffnvapi_QueryInterface(iOffset); \
if (ff ## iName == NULL) return "nvapi_QueryInterface " #iName " failed";
FF_NVAPI_INTERFACE(nvapi_Initialize, NVAPI_INTERFACE_OFFSET_INITIALIZE)
FF_NVAPI_INTERFACE(nvapi_Unload, NVAPI_INTERFACE_OFFSET_UNLOAD)
FF_NVAPI_INTERFACE(nvapi_EnumPhysicalGPUs, NVAPI_INTERFACE_OFFSET_ENUM_PHYSICAL_GPUS)
FF_NVAPI_INTERFACE(nvapi_GPU_GetRamType, NVAPI_INTERFACE_OFFSET_GPU_GET_RAM_TYPE)
#undef FF_NVAPI_INTERFACE
if (ffnvapi_Initialize() < 0)
return "NvAPI_Initialize() failed";
nvapiData.ffnvapi_EnumPhysicalGPUs = ffnvapi_EnumPhysicalGPUs;
nvapiData.ffnvapi_GPU_GetRamType = ffnvapi_GPU_GetRamType;
nvapiData.ffnvapi_Unload = ffnvapi_Unload;
atexit((void*) ffnvapi_Unload);
libnvapi = NULL; // don't close nvapi
}
if (nvapiData.ffnvapi_EnumPhysicalGPUs == NULL)
return "loading nvapi library failed";
NvPhysicalGpuHandle handles[32];
int gpuCount = 0;
if (nvapiData.ffnvapi_EnumPhysicalGPUs(handles, &gpuCount) < 0)
return "NvAPI_EnumPhysicalGPUs() failed";
uint32_t gpuIndex = *result->index;
if (gpuIndex >= (uint32_t) gpuCount)
return "GPU index out of range";
// Not very sure. Need to check in multi-GPU system
NvPhysicalGpuHandle gpuHandle = handles[gpuIndex];
NvApiGPUMemoryType memType;
if (nvapiData.ffnvapi_GPU_GetRamType(gpuHandle, &memType) < 0)
return "NvAPI_GPU_GetRamType() failed";
switch (memType)
{
#define FF_NVAPI_MEMORY_TYPE(type) \
case NVAPI_GPU_MEMORY_TYPE_##type: \
ffStrbufSetStatic(result->memoryType, #type); \
break;
FF_NVAPI_MEMORY_TYPE(UNKNOWN)
FF_NVAPI_MEMORY_TYPE(SDRAM)
FF_NVAPI_MEMORY_TYPE(DDR1)
FF_NVAPI_MEMORY_TYPE(DDR2)
FF_NVAPI_MEMORY_TYPE(GDDR2)
FF_NVAPI_MEMORY_TYPE(GDDR3)
FF_NVAPI_MEMORY_TYPE(GDDR4)
FF_NVAPI_MEMORY_TYPE(DDR3)
FF_NVAPI_MEMORY_TYPE(GDDR5)
FF_NVAPI_MEMORY_TYPE(LPDDR2)
FF_NVAPI_MEMORY_TYPE(GDDR5X)
FF_NVAPI_MEMORY_TYPE(LPDDR3)
FF_NVAPI_MEMORY_TYPE(LPDDR4)
FF_NVAPI_MEMORY_TYPE(LPDDR5)
FF_NVAPI_MEMORY_TYPE(GDDR6)
FF_NVAPI_MEMORY_TYPE(GDDR6X)
FF_NVAPI_MEMORY_TYPE(GDDR7)
#undef FF_NVAPI_MEMORY_TYPE
default:
ffStrbufSetF(result->memoryType, "Unknown (%d)", memType);
break;
}
return NULL;
}
#endif
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
{
#ifndef FF_DISABLE_DLOPEN
@@ -61,7 +163,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
char pciBusIdStr[32];
snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr), "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(pciBusIdStr, &device);
if (ret != NVML_SUCCESS)
@@ -88,24 +190,28 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
break;
}
if (!device) return "Device not found";
}
nvmlBrandType_t brand;
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
if (!device) return "Device not found";
if (result.type)
{
switch (brand)
nvmlBrandType_t brand;
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
{
case NVML_BRAND_NVIDIA_RTX:
case NVML_BRAND_QUADRO_RTX:
case NVML_BRAND_GEFORCE:
case NVML_BRAND_TITAN:
case NVML_BRAND_TESLA:
case NVML_BRAND_QUADRO:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
switch (brand)
{
case NVML_BRAND_NVIDIA_RTX:
case NVML_BRAND_QUADRO_RTX:
case NVML_BRAND_GEFORCE:
case NVML_BRAND_TITAN:
case NVML_BRAND_TESLA:
case NVML_BRAND_QUADRO:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
}
}
}
@@ -113,7 +219,13 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
{
unsigned int value;
if (nvmlData.ffnvmlDeviceGetIndex(device, &value) == NVML_SUCCESS)
{
*result.index = value;
#ifdef _WIN32
if (result.memoryType)
detectMemTypeByNvapi(&result);
#endif
}
}
+9 -2
View File
@@ -9,7 +9,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) {
"scanpci",
"/usr/bin/scanpci",
"-v",
NULL,
});
@@ -35,8 +35,14 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
{
// find the start of device entry
const char* pstart = memrchr(buffer.chars, '\n', (size_t) (pclass - buffer.chars));
if (pstart == NULL)
return "PCI info not found, invalid scanpci result";
while (pstart[1] != 'p')
{
pstart = memrchr(buffer.chars, '\n', (size_t) (pstart - buffer.chars - 1));
if (pstart == NULL)
return "PCI info not found, invalid scanpci result";
}
++pstart;
uint32_t vendorId, deviceId;
@@ -51,9 +57,10 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(vendorId));
ffStrbufInit(&gpu->memoryType);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
ffStrbufInitStatic(&gpu->platformApi, "/usr/bin/scanpci");
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
+5 -1
View File
@@ -37,6 +37,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->memoryType);
ffStrbufInitStatic(&gpu->platformApi, "SetupAPI");
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
@@ -47,13 +48,14 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->deviceId = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
uint32_t pciBus = 0, pciAddr = UINT32_MAX, pciDev = 0, pciFunc = 0;
uint32_t pciBus = 0, pciAddr = 0, pciDev = 0, pciFunc = 0;
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) &&
SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL))
{
pciDev = (pciAddr >> 16) & 0xFFFF;
pciFunc = pciAddr & 0xFFFF;
gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc;
pciAddr = 1; // Set to 1 to indicate that the device is a PCI device
}
wchar_t buffer[256];
@@ -173,6 +175,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
.index = &gpu->index,
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.sharedMemory = options->driverSpecific ? &gpu->shared : NULL,
.memoryType = options->driverSpecific ? &gpu->memoryType : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
+1
View File
@@ -70,6 +70,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitS(&gpu->name, desc);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
+44
View File
@@ -141,6 +141,50 @@ typedef struct ctl_mem_state_t
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv417ctlMemoryGetState16ctl_mem_handle_tP15ctl_mem_state_t
extern ctl_result_t ctlMemoryGetState(ctl_mem_handle_t hMemory, ctl_mem_state_t *pState);
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv414ctl_mem_type_t
typedef enum ctl_mem_type_t
{
CTL_MEM_TYPE_HBM = 0,
CTL_MEM_TYPE_DDR = 1,
CTL_MEM_TYPE_DDR3 = 2,
CTL_MEM_TYPE_DDR4 = 3,
CTL_MEM_TYPE_DDR5 = 4,
CTL_MEM_TYPE_LPDDR = 5,
CTL_MEM_TYPE_LPDDR3 = 6,
CTL_MEM_TYPE_LPDDR4 = 7,
CTL_MEM_TYPE_LPDDR5 = 8,
CTL_MEM_TYPE_GDDR4 = 9,
CTL_MEM_TYPE_GDDR5 = 10,
CTL_MEM_TYPE_GDDR5X = 11,
CTL_MEM_TYPE_GDDR6 = 12,
CTL_MEM_TYPE_GDDR6X = 13,
CTL_MEM_TYPE_GDDR7 = 14,
CTL_MEM_TYPE_MAX
} ctl_mem_type_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv413ctl_mem_loc_t
typedef enum ctl_mem_loc_t
{
CTL_MEM_LOC_SYSTEM = 0,
CTL_MEM_LOC_DEVICE = 1,
CTL_MEM_LOC_MAX
} ctl_mem_loc_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv420ctl_mem_properties_t
typedef struct ctl_mem_properties_t
{
uint32_t Size;
uint8_t Version;
ctl_mem_type_t type;
ctl_mem_loc_t location;
uint64_t physicalSize;
int32_t busWidth;
int32_t numChannels;
} ctl_mem_properties_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#_CPPv422ctlMemoryGetProperties16ctl_mem_handle_tP20ctl_mem_properties_t
extern ctl_result_t ctlMemoryGetProperties(ctl_mem_handle_t hMemory, ctl_mem_properties_t *pProperties);
typedef struct ctl_freq_handle_t* ctl_freq_handle_t;
// https://intel.github.io/drivers.gpu.control-library/Control/api.html#ctlenumfrequencydomains
+44
View File
@@ -0,0 +1,44 @@
// References:
// https://github.com/NVIDIA/nvapi (MIT License)
// https://github.com/deathcamp/NVOC/blob/master/nvoc.c (Public Domain)
typedef enum NvApiGPUMemoryType
{
NVAPI_GPU_MEMORY_TYPE_UNKNOWN = 0,
NVAPI_GPU_MEMORY_TYPE_SDRAM,
NVAPI_GPU_MEMORY_TYPE_DDR1,
NVAPI_GPU_MEMORY_TYPE_DDR2,
NVAPI_GPU_MEMORY_TYPE_GDDR2,
NVAPI_GPU_MEMORY_TYPE_GDDR3,
NVAPI_GPU_MEMORY_TYPE_GDDR4,
NVAPI_GPU_MEMORY_TYPE_DDR3,
NVAPI_GPU_MEMORY_TYPE_GDDR5,
NVAPI_GPU_MEMORY_TYPE_LPDDR2,
NVAPI_GPU_MEMORY_TYPE_GDDR5X,
NVAPI_GPU_MEMORY_TYPE_LPDDR3,
NVAPI_GPU_MEMORY_TYPE_LPDDR4,
NVAPI_GPU_MEMORY_TYPE_LPDDR5,
NVAPI_GPU_MEMORY_TYPE_GDDR6,
NVAPI_GPU_MEMORY_TYPE_GDDR6X,
NVAPI_GPU_MEMORY_TYPE_GDDR7,
} NvApiGPUMemoryType;
typedef int NvAPI_Status; // 0 = success; < 0 = error
typedef struct NvPhysicalGpuHandle* NvPhysicalGpuHandle;
typedef enum
{
NVAPI_INTERFACE_OFFSET_INITIALIZE = 0x0150E828,
NVAPI_INTERFACE_OFFSET_UNLOAD = 0xD22BDD7E,
NVAPI_INTERFACE_OFFSET_ENUM_PHYSICAL_GPUS = 0xE5AC921F,
NVAPI_INTERFACE_OFFSET_GPU_GET_RAM_TYPE = 0x57F7CAAC,
NVAPI_INTERFACE_OFFSET_FORCE_UINT32 = 0xFFFFFFFF
} NvApiInterfaceOffsets;
extern void* nvapi_QueryInterface(NvApiInterfaceOffsets offset);
extern NvAPI_Status nvapi_Initialize(void);
extern NvAPI_Status nvapi_Unload(void);
extern NvAPI_Status nvapi_EnumPhysicalGPUs(NvPhysicalGpuHandle* handles, int* count);
extern NvAPI_Status nvapi_GPU_GetRamType(NvPhysicalGpuHandle handle, NvApiGPUMemoryType* memtype);
+1 -1
View File
@@ -14,7 +14,7 @@ typedef struct FFHostResult
} FFHostResult;
const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel);
#ifdef __x86_64__
#if __x86_64__
bool ffHostDetectMac(FFHostResult* host);
#endif
const char* ffDetectHost(FFHostResult* host);
+6 -2
View File
@@ -107,6 +107,11 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
else if(ffStrbufStartsWithS(hwModel, "Mac"))
{
const char* version = hwModel->chars + strlen("Mac");
if(ffStrEquals(version, "16,13")) return "MacBook Air (15-inch, M4, 2025)";
if(ffStrEquals(version, "16,12")) return "MacBook Air (13-inch, M4, 2025)";
if(ffStrEquals(version, "16,11") ||
ffStrEquals(version, "16,10")) return "Mac Mini (2024)";
if(ffStrEquals(version, "16,9")) return "Mac Studio (M4 Max, 2025)";
if(ffStrEquals(version, "16,3")) return "iMac (24-inch, 2024, Four Thunderbolt / USB 4 ports)";
if(ffStrEquals(version, "16,2")) return "iMac (24-inch, 2024, Two Thunderbolt / USB 4 ports)";
if(ffStrEquals(version, "16,1")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 4 ports)";
@@ -114,8 +119,7 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
ffStrEquals(version, "16,8")) return "MacBook Pro (14-inch, 2024, Three Thunderbolt 5 ports)";
if(ffStrEquals(version, "16,7") ||
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 5 ports)";
if(ffStrEquals(version, "16,15") ||
ffStrEquals(version, "16,10")) return "Mac mini (2024)";
if(ffStrEquals(version, "15,14")) return "Mac Studio (M3 Ultra, 2025)";
if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)";
if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)";
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
+1 -1
View File
@@ -72,7 +72,7 @@ const char* ffDetectHost(FFHostResult* host)
ffCleanUpSmbiosValue(&host->family);
}
#if _WIN32 && __x86_64__
#if _WIN64 && __x86_64__ // aarch64 also defines _WIN64
ffHostDetectMac(host);
#endif
+3 -1
View File
@@ -16,6 +16,7 @@ const char* ffDetectInitSystem(FFInitSystemResult* result)
ffStrbufSetStatic(&result->exe, path);
ffStrbufSetStatic(&result->name, "launch_daemon");
result->pid = 0;
team_info teamInfo;
int32 cookie = 0;
@@ -28,7 +29,8 @@ const char* ffDetectInitSystem(FFInitSystemResult* result)
}
}
ffGetFileVersion(path, &result->version);
if (instance.config.general.detectVersion)
ffGetFileVersion(path, &result->version);
return NULL;
}
+45 -4
View File
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <usbhid.h>
#include <sys/kbio.h>
#if __has_include(<dev/usb/usb_ioctl.h>)
#include <dev/usb/usb_ioctl.h> // FreeBSD
@@ -11,16 +12,47 @@
#include <bus/u4b/usb_ioctl.h> // DragonFly
#endif
#define MAX_UHID_JOYS 64
static const char* detectByIoctl(FFlist* devices)
{
keyboard_info_t kbdInfo;
if (ioctl(STDIN_FILENO, KDGKBINFO, &kbdInfo) != 0)
return "ioctl(KDGKBINFO) failed";
const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */)
FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(devices);
switch (kbdInfo.kb_type) {
case KB_84:
ffStrbufInitS(&device->name, "AT 84-key keyboard");
break;
case KB_101:
ffStrbufInitS(&device->name, "AT 101/102-key keyboard");
break;
default:
ffStrbufInitS(&device->name, "Unknown keyboard");
break;
}
ffStrbufAppendF(&device->name, " (kbd%d)", kbdInfo.kb_index);
ffStrbufInit(&device->serial);
return NULL;
}
#define MAX_UHID_KBDS 64
static const char* detectByUsbhid(FFlist* devices)
{
char path[16];
for (int i = 0; i < MAX_UHID_JOYS; i++)
for (int i = 0; i < MAX_UHID_KBDS; i++)
{
snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) continue;
if (fd < 0)
{
if (errno == ENOENT)
break; // No more devices
continue; // Device not found
}
report_desc_t repDesc = hid_get_report_desc(fd);
if (!repDesc) continue;
@@ -43,6 +75,7 @@ const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */)
ffStrbufInitS(&device->name, di.udi_product);
}
}
hid_end_parse(hData);
}
hid_dispose_report_desc(repDesc);
@@ -50,3 +83,11 @@ const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */)
return NULL;
}
const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */)
{
detectByUsbhid(devices);
if (devices->length > 0)
return NULL;
return detectByIoctl(devices);
}
+3 -1
View File
@@ -11,7 +11,7 @@ extern void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t dispatcher, void(^ca
extern void MRMediaRemoteGetNowPlayingClient(dispatch_queue_t dispatcher, void (^callback)(_Nullable id clientObj)) __attribute__((weak_import));
extern CFStringRef MRNowPlayingClientGetBundleIdentifier(id clientObj) __attribute__((weak_import));
extern CFStringRef MRNowPlayingClientGetParentAppBundleIdentifier(id clientObj) __attribute__((weak_import));
void MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_queue_t queue, void (^callback)(BOOL playing));
void MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_queue_t queue, void (^callback)(BOOL playing)) __attribute__((weak_import));
static const char* getMedia(FFMediaResult* result)
{
@@ -20,6 +20,7 @@ static const char* getMedia(FFMediaResult* result)
FF_TEST_FN_EXISTANCE(MRMediaRemoteGetNowPlayingClient);
FF_TEST_FN_EXISTANCE(MRNowPlayingClientGetBundleIdentifier);
FF_TEST_FN_EXISTANCE(MRNowPlayingClientGetParentAppBundleIdentifier);
FF_TEST_FN_EXISTANCE(MRMediaRemoteGetNowPlayingApplicationIsPlaying);
#undef FF_TEST_FN_EXISTANCE
dispatch_group_t group = dispatch_group_create();
@@ -63,6 +64,7 @@ static const char* getMedia(FFMediaResult* result)
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// Don't dispatch_release because we are using ARC
if(result->playerId.length > 0)
{
+2 -2
View File
@@ -129,9 +129,9 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
}
else
{
char str[] = { fileName[1], fileName[2], 0 };
if (str[0] == 0 || str[1] == 0)
if (fileName[1] == 0 || fileName[2] == 0)
break;
char str[] = { fileName[1], fileName[2], 0 };
ffStrbufAppendC(&result->song, (char) strtoul(str, NULL, 16));
fileName += 2;
}
+9 -9
View File
@@ -32,15 +32,15 @@ const char* ffWinrtDetectMedia(FFWinrtMediaResult* result)
{
switch (playbackInfo.PlaybackStatus())
{
#define FF_MEDIA_SET_STATUS(status_code) \
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::status_code: result->status = #status_code; break
FF_MEDIA_SET_STATUS(Closed);
FF_MEDIA_SET_STATUS(Opened);
FF_MEDIA_SET_STATUS(Changing);
FF_MEDIA_SET_STATUS(Stopped);
FF_MEDIA_SET_STATUS(Playing);
FF_MEDIA_SET_STATUS(Paused);
#undef FF_MEDIA_SET_STATUS
#define FF_MEDIA_SET_STATUS(status_code) \
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::status_code: result->status = #status_code; break;
FF_MEDIA_SET_STATUS(Closed)
FF_MEDIA_SET_STATUS(Opened)
FF_MEDIA_SET_STATUS(Changing)
FF_MEDIA_SET_STATUS(Stopped)
FF_MEDIA_SET_STATUS(Playing)
FF_MEDIA_SET_STATUS(Paused)
#undef FF_MEDIA_SET_STATUS
}
}
+9 -4
View File
@@ -11,17 +11,21 @@
#include <bus/u4b/usb_ioctl.h> // DragonFly
#endif
#define MAX_UHID_JOYS 64
#define MAX_UHID_MICE 64
const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */)
{
char path[16];
for (int i = 0; i < MAX_UHID_JOYS; i++)
for (int i = 0; i < MAX_UHID_MICE; i++)
{
snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) continue;
if (fd < 0)
{
if (errno == ENOENT)
break; // No more devices
continue; // Device not found
}
report_desc_t repDesc = hid_get_report_desc(fd);
if (!repDesc) continue;
@@ -43,6 +47,7 @@ const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */)
ffStrbufInitS(&device->name, di.udi_product);
}
}
hid_end_parse(hData);
}
hid_dispose_report_desc(repDesc);
+1
View File
@@ -92,6 +92,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
@@ -123,67 +123,73 @@ const char* ffDetectPhysicalMemory(FFlist* result)
else if (ldevice)
ffStrbufSetS(&device->locator, ldevice);
switch (data->FormFactor)
{
case 0x01: ffStrbufSetStatic(&device->formFactor, "Other"); break;
case 0x02: ffStrbufSetStatic(&device->formFactor, "Unknown"); break;
case 0x03: ffStrbufSetStatic(&device->formFactor, "SIMM"); break;
case 0x04: ffStrbufSetStatic(&device->formFactor, "SIP"); break;
case 0x05: ffStrbufSetStatic(&device->formFactor, "Chip"); break;
case 0x06: ffStrbufSetStatic(&device->formFactor, "DIP"); break;
case 0x07: ffStrbufSetStatic(&device->formFactor, "ZIP"); break;
case 0x08: ffStrbufSetStatic(&device->formFactor, "Proprietary Card"); break;
case 0x09: ffStrbufSetStatic(&device->formFactor, "DIMM"); break;
case 0x0A: ffStrbufSetStatic(&device->formFactor, "TSOP"); break;
case 0x0B: ffStrbufSetStatic(&device->formFactor, "Row of chips"); break;
case 0x0C: ffStrbufSetStatic(&device->formFactor, "RIMM"); break;
case 0x0D: ffStrbufSetStatic(&device->formFactor, "SODIMM"); break;
case 0x0E: ffStrbufSetStatic(&device->formFactor, "SRIMM"); break;
case 0x0F: ffStrbufSetStatic(&device->formFactor, "FBDIMM"); break;
case 0x10: ffStrbufSetStatic(&device->formFactor, "Die"); break;
default: ffStrbufSetF(&device->formFactor, "Unknown (%d)", (int) data->FormFactor); break;
}
const char* formFactorNames[] = {
NULL, // 0x00 (用于索引,实际上没有0x00的类型)
"Other", // 0x01
"Unknown", // 0x02
"SIMM", // 0x03
"SIP", // 0x04
"Chip", // 0x05
"DIP", // 0x06
"ZIP", // 0x07
"Proprietary Card",// 0x08
"DIMM", // 0x09
"TSOP", // 0x0A
"Row of chips", // 0x0B
"RIMM", // 0x0C
"SODIMM", // 0x0D
"SRIMM", // 0x0E
"FBDIMM", // 0x0F
"Die", // 0x10
};
if (data->FormFactor > 0 && data->FormFactor < ARRAY_SIZE(formFactorNames))
ffStrbufSetS(&device->formFactor, formFactorNames[data->FormFactor]);
else
ffStrbufSetF(&device->formFactor, "Unknown (%d)", (int) data->FormFactor);
switch (data->MemoryType)
{
case 0x01: ffStrbufSetStatic(&device->type, "Other"); break;
case 0x02: ffStrbufSetStatic(&device->type, "Unknown"); break;
case 0x03: ffStrbufSetStatic(&device->type, "DRAM"); break;
case 0x04: ffStrbufSetStatic(&device->type, "EDRAM"); break;
case 0x05: ffStrbufSetStatic(&device->type, "VRAM"); break;
case 0x06: ffStrbufSetStatic(&device->type, "SRAM"); break;
case 0x07: ffStrbufSetStatic(&device->type, "RAM"); break;
case 0x08: ffStrbufSetStatic(&device->type, "ROM"); break;
case 0x09: ffStrbufSetStatic(&device->type, "FLASH"); break;
case 0x0A: ffStrbufSetStatic(&device->type, "EEPROM"); break;
case 0x0B: ffStrbufSetStatic(&device->type, "FEPROM"); break;
case 0x0C: ffStrbufSetStatic(&device->type, "EPROM"); break;
case 0x0D: ffStrbufSetStatic(&device->type, "CDRAM"); break;
case 0x0E: ffStrbufSetStatic(&device->type, "3DRAM"); break;
case 0x0F: ffStrbufSetStatic(&device->type, "SDRAM"); break;
case 0x10: ffStrbufSetStatic(&device->type, "SGRAM"); break;
case 0x11: ffStrbufSetStatic(&device->type, "RDRAM"); break;
case 0x12: ffStrbufSetStatic(&device->type, "DDR"); break;
case 0x13: ffStrbufSetStatic(&device->type, "DDR2"); break;
case 0x14: ffStrbufSetStatic(&device->type, "DDR2 FB-DIMM"); break;
case 0x15:
case 0x16:
case 0x17: ffStrbufSetStatic(&device->type, "Reserved"); break;
case 0x18: ffStrbufSetStatic(&device->type, "DDR3"); break;
case 0x19: ffStrbufSetStatic(&device->type, "FBD2"); break;
case 0x1A: ffStrbufSetStatic(&device->type, "DDR4"); break;
case 0x1B: ffStrbufSetStatic(&device->type, "LPDDR"); break;
case 0x1C: ffStrbufSetStatic(&device->type, "LPDDR2"); break;
case 0x1D: ffStrbufSetStatic(&device->type, "LPDDR3"); break;
case 0x1E: ffStrbufSetStatic(&device->type, "LPDDR4"); break;
case 0x1F: ffStrbufSetStatic(&device->type, "Logical non-volatile device"); break;
case 0x20: ffStrbufSetStatic(&device->type, "HBM"); break;
case 0x21: ffStrbufSetStatic(&device->type, "HBM2"); break;
case 0x22: ffStrbufSetStatic(&device->type, "DDR5"); break;
case 0x23: ffStrbufSetStatic(&device->type, "LPDDR5"); break;
case 0x24: ffStrbufSetStatic(&device->type, "HBM3"); break;
default: ffStrbufSetF(&device->type, "Unknown (%d)", (int) data->MemoryType); break;
}
const char* memoryTypeNames[] = {
NULL, // 0x00 (用于索引,实际上没有0x00的类型)
"Other", // 0x01
"Unknown", // 0x02
"DRAM", // 0x03
"EDRAM", // 0x04
"VRAM", // 0x05
"SRAM", // 0x06
"RAM", // 0x07
"ROM", // 0x08
"FLASH", // 0x09
"EEPROM", // 0x0A
"FEPROM", // 0x0B
"EPROM", // 0x0C
"CDRAM", // 0x0D
"3DRAM", // 0x0E
"SDRAM", // 0x0F
"SGRAM", // 0x10
"RDRAM", // 0x11
"DDR", // 0x12
"DDR2", // 0x13
"DDR2 FB-DIMM", // 0x14
"Reserved", // 0x15
"Reserved", // 0x16
"Reserved", // 0x17
"DDR3", // 0x18
"FBD2", // 0x19
"DDR4", // 0x1A
"LPDDR", // 0x1B
"LPDDR2", // 0x1C
"LPDDR3", // 0x1D
"LPDDR4", // 0x1E
"Logical non-volatile device", // 0x1F
"HBM", // 0x20
"HBM2", // 0x21
"DDR5", // 0x22
"LPDDR5", // 0x23
"HBM3", // 0x24
};
if (data->MemoryType > 0 && data->MemoryType < ARRAY_SIZE(memoryTypeNames))
ffStrbufSetStatic(&device->type, memoryTypeNames[data->MemoryType]);
else
ffStrbufSetF(&device->type, "Unknown (%d)", (int) data->MemoryType);
if (data->Header.Length > offsetof(FFSmbiosMemoryDevice, Speed)) // 2.3+
{
+1 -1
View File
@@ -64,7 +64,7 @@ const char* ffDetectSound(FFlist* devices)
return "sioctl_ondesc() failed";
if (bundle.iLevel != bundle.iMute || bundle.iLevel == 0)
return "Unexpecd sioctl_ondesc() result";
return "Unexpected sioctl_ondesc() result";
FFSoundDevice* device = ffListAdd(devices);
ffStrbufInitS(&device->name, bundle.name);
+10 -2
View File
@@ -9,6 +9,14 @@ extern "C" {
#include <endpointvolume.h>
#include <functiondiscoverykeys_devpkey.h>
static void ffCoTaskMemFreeWrapper(void* pptr)
{
assert(pptr != NULL);
void* ptr = *(void**)pptr;
if (ptr) CoTaskMemFree(ptr);
}
#define FF_COTASK_AUTO_FREE __attribute__((__cleanup__(ffCoTaskMemFreeWrapper)))
const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
{
const char* error = ffInitCom();
@@ -20,7 +28,7 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
if (FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void **)&pEnum)))
return "CoCreateInstance(CLSID_MMDeviceEnumerator) failed";
LPWSTR mainDeviceId = NULL;
LPWSTR FF_COTASK_AUTO_FREE mainDeviceId = NULL;
{
IMMDevice* FF_AUTO_RELEASE_COM_OBJECT pDefaultDevice = NULL;
@@ -47,7 +55,7 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
if (FAILED(pDevices->Item(deviceIdx, &immDevice)))
continue;
LPWSTR immDeviceId = NULL;
LPWSTR FF_COTASK_AUTO_FREE immDeviceId = NULL;
if (FAILED(immDevice->GetId(&immDeviceId)))
continue;

Some files were not shown because too many files have changed in this diff Show More