Compare commits

..

124 Commits

Author SHA1 Message Date
Carter Li c0774b89d6 Merge pull request #1184 from fastfetch-cli/dev
Release: v2.21.2
2024-08-14 10:55:42 +08:00
李通洲 030f34d405 Doc: fix changelog [ci skip] 2024-08-14 10:44:40 +08:00
李通洲 cedc93fe7b CI: try fixing FreeBSD 2024-08-14 10:25:59 +08:00
李通洲 e155767289 Logo (Builtin): add GoldenDog Linux
Fix #1183
2024-08-14 10:14:33 +08:00
李通洲 4e41223b81 Colors (Linux): only apply work around in Linux Console 2024-08-14 10:03:12 +08:00
李通洲 2ee4d7daac Release v2.21.2 2024-08-14 09:28:46 +08:00
李通洲 a6a0a03b44 Doc: update changelog 2024-08-14 09:19:27 +08:00
李通洲 4b3241a286 CMake: try fixing detection of pthread_timedjoin_np 2024-08-14 09:02:18 +08:00
李通洲 d37bf7252d Logo (Builtin): trim final new line 2024-08-14 08:45:02 +08:00
李通洲 dd66626165 Display: remove detection of WCG enabled 2024-08-14 08:32:13 +08:00
李通洲 fe7e684e85 GPU (Windows): fix missing GPUs sometimes 2024-08-13 19:25:25 +08:00
李通洲 2281caaff8 Fastfetch: fix bug that stat info is unexpectly printed 2024-08-13 15:28:17 +08:00
李通洲 96c838d3f3 GPU (Windows): code refactor 2024-08-13 14:51:41 +08:00
李通洲 c6e1677369 BootMgr (Windows): ControlSet001 -> CurrentControlSet 2024-08-13 14:46:24 +08:00
李通洲 ea18d93a40 Display / Monitor (macOS): code refactor 2024-08-13 08:41:32 +08:00
李通洲 f6e1e5c96b Fastfetch: support --stat <num> 2024-08-13 08:41:32 +08:00
Carter Li 0b85fc74eb Fastfetch: increase precision of --stat 2024-08-13 08:41:32 +08:00
李通洲 946eb0eacd GPU (Windows): don't skip GPU silently
Ref: #1181
2024-08-13 06:32:38 +08:00
Princess-Sunset-Shimmer a11ec589f0 Logo (Builtin): HyprOS logo (#1180)
* Update builtin.c

* Create hypros.txt
2024-08-12 19:58:09 +08:00
Carter Li a89955b080 Logo (Image): try support tmux (doesn't work yet) 2024-08-12 10:29:31 +08:00
Carter Li df4350666a CPU (Linux): embed the arm part codes of lscpu
Fix #1175
2024-08-12 10:25:54 +08:00
Carter Li 55b1603b83 GPU (BSD): fix build 2024-08-10 23:31:29 +08:00
Carter Li fb1c727641 GPU (Linux): ensure we correctly get the marketing name 2024-08-10 21:59:03 +08:00
李通洲 87d964c7ca GPU (Linux): fix uninited struct fields 2024-08-10 21:08:35 +08:00
李通洲 bdb0a9262c GPU (Linux): fix intel GPU type detection
Ref: #1177
2024-08-10 21:03:56 +08:00
Carter Li e42dfe63c3 GPU (Linux): fix bad Intel Arc GPU name
Fix #1177
2024-08-10 12:13:21 +08:00
Carter Li e8932895e8 CMake (Linux): complain about pthread_timedjoin_np is not found 2024-08-10 07:41:31 +08:00
Carter Li 4091d33c56 Packaging: update debian stuff [ci skip] 2024-08-09 14:28:55 +08:00
Carter Li 5df2a751ea Merge pull request #1173 from fastfetch-cli/dev
Release v2.21.1
2024-08-09 10:49:50 +08:00
李通洲 65b9f0005b TerminalFont (Linux): when detecting st, report an error if fails to load libelf 2024-08-09 10:11:38 +08:00
李通洲 a3e4b4fe22 Release v2.21.1 2024-08-09 09:54:49 +08:00
李通洲 0749704400 Version: report git commit hash 2024-08-09 09:54:49 +08:00
李通洲 9977cb688d Presets: set timeout to publicip
Fix #1170
2024-08-09 08:47:48 +08:00
李通洲 8c26e776c2 InitSystem (Android): don't break build 2024-08-09 08:40:41 +08:00
李通洲 e174eddef1 GPU (Linux): always try directx 2024-08-08 18:53:56 +08:00
李通洲 f866c90687 GPU: defaults to --gpu-detection-method pci on x86 to detect disabled gpus 2024-08-08 16:23:58 +08:00
李通洲 a61a956b84 CI (Linux): fix libelf dep installation on musl 2024-08-08 16:09:48 +08:00
李通洲 ef73c4a97d CI: build with libelf 2024-08-08 15:49:51 +08:00
Carter Li 79c02ebf7c CI: fix build on FreeBSD & SunOS 2024-08-08 15:36:17 +08:00
李通洲 1394a0ae2e InitSystem (macOS): fix compiling 2024-08-08 15:23:40 +08:00
Carter Li e8ebae7ee9 TerminalFont (Linux): improve performance of st terminal font detection 2024-08-08 15:09:37 +08:00
Carter Li 3fae29ba8f InitSystem (Linux): add fast path for systemd version detection 2024-08-08 15:09:37 +08:00
Carter Li a9373fb4e4 Util (Linux): add elf helper 2024-08-08 15:09:37 +08:00
Carter Li 2e2cf64452 Terminal (Linux): add kitty version detection fast path back 2024-08-08 14:58:56 +08:00
Carter Li 7c3835bd9f DBus: increase dbus timeout 2024-08-08 09:01:41 +08:00
Princess-Sunset-Shimmer 945fd3a402 Logo (Builtin): add vanilla OS 2 logo (#1168)
* Create vanilla_small.txt

* Update builtin.c

for new vanilla small logo

* Update builtin.c

* Create 23.jsonc

* Update 23.jsonc

* Update builtin.c

* Create vanilla2.txt

new byte bloat is comming

* Update builtin.c

* Update builtin.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-08-07 19:34:05 +08:00
AlbydS 53d2dbd420 Logo (Builtin): Add support for Linux From Scratch (#1165)
* Add Linux From Scratch logo

Added ASCII logo for Linux From Scratch

* Add Linux From Scratch to builtin.c

I added Linux From Scratch support to builtin.c

* Update builtin.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-08-07 14:46:24 +08:00
李通洲 eaa4721b36 Chore: update editorconfig [ci skip] 2024-08-07 10:59:14 +08:00
TheCourierNV f695ae9116 Locale (Linux): Add LC_ALL check (#1166)
`LC_ALL`, if set, overrides every other locale-related environment
variable.
2024-08-07 10:53:57 +08:00
Princess-Sunset-Shimmer b0270f36f9 Logo (Builtin): add new small vanilla logo (#1167)
* Create vanilla_small.txt

* Update builtin.c

for new vanilla small logo

* Update builtin.c

* Create 23.jsonc

* Update 23.jsonc

* Update builtin.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2024-08-07 10:49:44 +08:00
Carter Li fe5b07e0d0 Colors (Linux): fix light color doesn't work on Linux tty
Ref: https://github.com/fastfetch-cli/fastfetch/issues/1141#issuecomment-2271060911
2024-08-07 10:15:01 +08:00
Carter Li 8396f000e1 DisplayServer (Linux): don't rely on $XDG_SESSION_TYPE for detecting wm protocol
Fix #1162
2024-08-06 16:34:01 +08:00
Carter Li 1361e8cd18 GPU (Linux): fix wrong GPU max frequency on asahi 2024-08-06 10:14:39 +08:00
李通洲 b3ac696312 Wifi (Linux): fix building error without linux/wireless.h
Fix #1160
2024-08-05 22:01:40 +08:00
Linus Dierheimer 2205712bc0 Update FUNDING.yml [ci skip]
So he is shown on the front page
2024-08-05 10:52:40 +02:00
Carter Li f1741c66bf Packaging: update debian stuff [ci skip] 2024-08-05 14:36:44 +08:00
Carter Li 3247aabd74 Merge pull request #1151 from fastfetch-cli/dev
Release v2.21.0
2024-08-05 14:21:00 +08:00
李通洲 312d4cc518 Monitor: improve refreshRate formatting 2024-08-05 13:49:41 +08:00
Carter Li b24877af0b CMake: Release v2.21.0 2024-08-05 10:53:28 +08:00
李通洲 1de97fa3ed Doc: update changelog for v2.21.0 2024-08-05 10:09:40 +08:00
李通洲 6ca65b9166 GPU (BSD): improve type detection for Intel integrated GPUs 2024-08-05 10:07:17 +08:00
李通洲 b2cc5c4f04 CMake: clarify BSD is FreeBSD
Fix #1154
2024-08-05 08:54:25 +08:00
keklick1337 f683351fe3 Logo (Builtin): QTS logo (#1152) 2024-08-04 21:50:49 +08:00
Leah Amelia Chen d81cd50f64 Shell (Linux): don't detect hyfetch as shell on NixOS (#1149)
On NixOS, Hyfetch has been placed in a "wrapper script" in order to set the correct PATH that it needs to run correctly.
As a result, the actual Hyfetch executable has been renamed `.hyfetch-wrapped`, which results in this check failing to detect Hyfetch on NixOS properly.

With this patch the logic has been changed to check if the program name contains the string `hyfetch`, which should work for the NixOS case.
2024-08-04 20:13:28 +08:00
Sergey Fedorov 1101d2e90e Disk (BSD): minor fix for a type, fixes calculation of disk usage on 32-bit (#1150) 2024-08-04 20:08:21 +08:00
李通洲 8284d73cc9 Doc (Logo): metion size requirement [ci skip] 2024-08-04 14:12:32 +08:00
Carter Li 6b0db6fa74 Wifi (Linux): fix compiling without dbus 2024-08-03 22:16:07 +08:00
Carter Li 3a61b31e0a Wifi (Linux): implement libnm stuff with plain dbus calls 2024-08-03 22:06:37 +08:00
Carter Li 493cf8ff6c Media (Linux): detect playing status; update dbus api change 2024-08-03 22:05:29 +08:00
Carter Li e6cf7fdb9f Bluetooth (Linux): update for DBus api changes 2024-08-03 22:04:53 +08:00
Carter Li 831d2a05ce DBus: code cleanup; prepare for future commits 2024-08-03 22:03:34 +08:00
Carter Li d0b72c5457 Shell (Linux): remove version detection for unknown shells
It's a dangerous operation. Should fix #1144
2024-08-03 08:18:43 +08:00
Carter Li 0c82a84266 Global: remove using of libnm 2024-08-03 07:50:15 +08:00
李通洲 d501c8b41a GPU (Windows): fix missing vendor string 2024-08-02 22:23:29 +08:00
李通洲 0354fd5d9d GPU (Windows): use setupapi to find GPU devices
Ref: https://github.com/gpustack/gpustack/pull/97#issuecomment-2264678404
2024-08-02 21:52:24 +08:00
李通洲 a856350416 GPU (MT): fix segfault at program exit 2024-08-02 19:04:53 +08:00
Carter Li 4efe12c0d2 GPU (BSD): correctly detect GPU type 2024-08-02 16:47:57 +08:00
Carter Li 1a66bc4ec0 GPU: code cleanup; port MT specific code to Windows 2024-08-02 16:29:23 +08:00
R0CKSTAR d96d794d1f GPU (Linux): Support Moore Threads GPU (#1142)
* feat: Support Moore Threads GPU

Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>

* Fix spell check

Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>

* Fix frequency and add back util

Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>

* Add name field

Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>

---------

Signed-off-by: Xiaodong Ye <yeahdongcn@gmail.com>
2024-08-02 16:00:54 +08:00
Carter Li 45659854d2 GPU (Linux): don't ignore disabled GPU
Should fix #1140
2024-08-02 15:24:29 +08:00
Carter Li b111626fe9 GPU (Linux): use the device name that driver provides 2024-08-02 15:21:54 +08:00
Carter Li dccbdba242 Wifi (Linux): remove libnm dependency 2024-08-02 15:10:04 +08:00
Carter Li 884fd097c6 GPU (Linux): fix compiling (2) 2024-08-02 14:13:33 +08:00
Carter Li 08dea9fe21 GPU (Linux): fix compiling
oops...
2024-08-02 14:10:07 +08:00
Carter Li 98fc793386 GPU (Linux): embed part of asahi_drm.h code 2024-08-02 14:07:04 +08:00
Carter Li 121e9b911e GPU (Windows): fix bug that assuming pci bus id > 0 2024-08-02 13:48:02 +08:00
李通洲 b9fe2fb4dd Logo (Builtin): update endeavour_small 2024-08-02 10:18:01 +08:00
李通洲 812a13c871 Display (macOS): fix invalid refresh rate in old mac 2024-08-01 16:41:02 +08:00
李通洲 dcbfae7f72 Wifi (macOS): use private property to fetch ssid 2024-08-01 16:04:37 +08:00
李通洲 65883766a0 Display (macOS): don't parse string 2024-08-01 16:02:41 +08:00
李通洲 104cb43158 Wifi: rename macAddress to bssid 2024-08-01 15:45:53 +08:00
李通洲 114cc753d9 Option: print error when finding invalid color code
Fix #1138
2024-08-01 14:19:24 +08:00
李通洲 d68c4cef13 GPU (WSL): fix building 2024-08-01 14:10:07 +08:00
李通洲 c549a5cab8 GPU (macOS): report core usage 2024-08-01 13:54:03 +08:00
李通洲 cbf8fdf3fc GPU (macOS): ensure we only detects GPU
May fix #1066
2024-08-01 08:54:12 +08:00
Carter Li 1e8b9aa461 GPU (Linux): detect if nvidia driver is open source or proprietary 2024-08-01 00:06:22 +08:00
李通洲 5d32eba1a6 GPU (Nvidia): detect GPU core usage 2024-07-31 23:42:02 +08:00
李通洲 2ce7c8c60d GPU (Windows): use pci bus id to match Nvidia cards
Fix multi-gpu device
2024-07-31 22:23:30 +08:00
Carter Li 7eaaed6024 WM (Linux): don't use wl-restart as WM name
Fix #1135
2024-07-31 14:19:42 +08:00
Carter Li bd5012edc8 PhysicalMemory: make sure to detect all memory devices 2024-07-31 11:13:04 +08:00
Carter Li cf0d1cf294 DisplayServer (Linux): don't print unknown as display name 2024-07-31 10:13:29 +08:00
Carter Li a070519721 IO: disallow input echo 2024-07-31 09:40:00 +08:00
Carter Li fa0007ac6f CPU (Android): add SD 4s Gen 2 2024-07-31 08:58:03 +08:00
Carter Li ced67e81a5 DisplayServer (Linux): ensure $XDG_RUNTIME_DIR is set before connecting
wayland
2024-07-30 23:50:19 +08:00
Carter Li 88a7468489 GPU (Linux): fix apple gpu support 2024-07-30 16:43:56 +08:00
李通洲 ec8391f6c6 Global: don't use __has_include
It reports false results in ubuntu 20.04. Details unknown.
2024-07-30 11:06:42 +08:00
李通洲 4371e719ae CI (Linux): build aarch64 version with ubuntu 20.04 2024-07-29 21:47:32 +08:00
李通洲 bbbb493cdf BluetoothRadio (Windows): fix segfault 2024-07-29 18:55:43 +08:00
Carter Li 6cb565e379 BluetoothRadio: don't print unnecessary index 2024-07-29 18:42:24 +08:00
李通洲 2bb988a7f8 CPU: fix freq max formatting 2024-07-29 16:44:54 +08:00
李通洲 0929b940c8 BluetoothRadio (macOS): detect more info 2024-07-29 16:32:36 +08:00
Carter Li c14ba32b82 BluetoothRadio: add more props; remove hciVersion; code cleanup 2024-07-28 15:59:32 +08:00
李通洲 7a75615d9e BluetoothRadio (macOS): add dirty support 2024-07-28 13:06:29 +08:00
Carter Li 96c58148f6 BluetoothRadio (Linux): add support 2024-07-28 10:57:46 +08:00
Carter Li 2c7cd6df98 Bluetooth (Linux): more strict checks 2024-07-28 10:54:49 +08:00
Carter Li db1fbe0a30 DBus: rename ffDBusGetValue to ffDBusGetString; add ffDBusGetUint16 2024-07-28 10:54:26 +08:00
李通洲 a102f0505c CI: silence spell checks 2024-07-28 00:16:30 +08:00
李通洲 8a3af14d22 BluetoothRadio (Windows): new module 2024-07-28 00:12:29 +08:00
李通洲 ce648e9e44 Bluetooth (Windows): tidy; update module description 2024-07-28 00:04:25 +08:00
李通洲 2cc94ee095 DisplayServer (Linux): fix build with no wayland support 2024-07-27 19:53:25 +08:00
李通洲 16dd9fb213 Terminal (Windows): fix build 2024-07-27 18:52:17 +08:00
Carter Li 873285b083 TerminalShell: improve SSH detection 2024-07-26 23:53:46 +08:00
李通洲 ce43f06863 DisplayServer (Linux): don't try to connect wayland and X11 in tty mode
Fix #1110
2024-07-26 23:53:18 +08:00
李通洲 3c92e7013d Doc: fix changelog [ci skip] 2024-07-26 13:47:10 +08:00
444 changed files with 3751 additions and 1454 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
check-filenames =
builtin = clear,rare,usage,informal
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,conexant
+2 -2
View File
@@ -7,10 +7,10 @@ tab_width = 4
insert_final_newline = true
trim_trailing_whitespace = true
[*.{md,fflogo}]
[*.md]
trim_trailing_whitespace = false
[*.{fflogo}]
[*.txt]
insert_final_newline = false
[*.yml]
+1 -1
View File
@@ -1 +1 @@
github: [LinusDierheimer, CarterLi]
github: [CarterLi, LinusDierheimer]
+3
View File
@@ -15,6 +15,9 @@ Paste content of /etc/os-release and /etc/lsb-release here. If none of these fil
```
# Ascii
An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
```
Paste ascii art here.
```
+9 -9
View File
@@ -35,7 +35,7 @@ jobs:
run: uname -a
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_LIBNM=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
- name: build project
run: cmake --build . --target package --verbose -j4
@@ -74,7 +74,7 @@ jobs:
run: uname -a
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev
- name: install linuxbrew packages
run: |
@@ -138,11 +138,11 @@ jobs:
id: runcmd
with:
arch: aarch64
distro: ubuntu22.04
distro: ubuntu20.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -181,7 +181,7 @@ jobs:
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
dpkg -i *.deb
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -216,7 +216,7 @@ jobs:
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
@@ -247,7 +247,7 @@ jobs:
run: |
cat /etc/alpine-release
uname -a
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev gcc g++
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
shell: alpine.sh --root {0}
- name: build
@@ -288,7 +288,7 @@ jobs:
run: |
cat /etc/alpine-release
uname -a
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev gcc g++
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
shell: alpine.sh --root {0}
- name: build
@@ -422,7 +422,7 @@ jobs:
run: |
uname -a
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
+82 -1
View File
@@ -1,3 +1,84 @@
# 2.21.2
Features:
* Support `--stat <num_in_ms>` to display long running modules in yellow or red
Bugfixes:
* Fix bad Intel Arc GPU name and type detection (GPU, Linux)
* Fix uninited struct fields (GPU, Linux)
* Skip cpu model smbios detection on ARM platforms (CPU, Linux)
* Always use `CurrentControlSet` instead of `ControlSet001` when querying registry (Windows)
* Fix NVIDIA GPUs are missing in GPU detection sometimes (GPU, Windows)
* Fixing detection of `pthread_timedjoin_np` (Linux)
Logos:
* Add HyprOS
* Add GoldenDog Linux
# 2.21.1
Hotfix for a regression that breaks WM detection when running `startx` from TTY (Regression from 2.21.0, #1172 / #1162)
Changes:
* On Linux, FreeBSD and SunOS, a new recommended dependency `libelf` is introduced to extract strings in ELF binary, used for
* st term font detection when the term font is compiled directly into the binary
* fast path of systemd version detection
Features:
* Improve performance of
* kitty version detection (Terminal, Linux)
* st term font detection (TerminalFont, Linux)
* systemd version detection (InitSystem, Linux)
Bugfixes:
* Fix building error without `linux/wireless.h` (Wifi, Linux)
* Fix wrong GPU max frequency on Asahi Linux (GPU, Linux)
* Don't rely `$XDG_SESSION_TYPE` for detecting wm protocol (#1172 / #1162, WM, Linux)
* Fix light color doesn't work on Linux console (Colors, Linux)
* `LC_ALL`, if set, overrides every other locale-related environment variable (Locale)
* Increase timeout of DBus calls (Linux)
Logos:
* Add vanilla_small and vanilla2
* Add LFS (Linux From Scratch)
# 2.21.0
Changes:
* We no longer use `libnm` for Wifi detection on Linux. Instead, we use `libdbus` to communicate with NetworkManager directly
* To package managers: libnm dependency should be removed
Features:
* Add module `BluetoothRadio` that prints bluetooth radios installed on the system
* Don't confuse with module `Bluetooth` which lists connected bluetooth devices
* Detect more information when `--gpu-driver-specific` is used (GPU)
* Detect which type of nvidia driver (open source or proprietary) is used (GPU, Linux)
* `--gpu-driver-specific` adds supports for Moore Threads GPU (#1142, GPU, Linux / Windows)
* Use SetupAPI for detecting GPUs to support GPU detection when running fastfetch as a Windows Service (GPU, Windows)
* See https://github.com/gpustack/gpustack/pull/97#issuecomment-2264699787 for detail
* Detect playback status (Media, Linux)
Bugfixes:
* Don't try to connect display server in tty mode (Linux, #1110)
* Improve ssh detection
* Fix max frequency printing in custom format (CPU)
* Fix displaying random characters when detecting kitty term font (#1136 / #1145, TerminalFont, Linux)
* Make sure to detect all physical memory devices (#1137)
* Don't detect `wl-restart` as WM (#1135, WM, Linux)
* Use PCI bus ID to match Nvidia cards; fix multi-GPU detection (GPU)
* Ignore invalid GPU (#1066, GPU, macOS)
* Print error when invalid color code is found (#1138)
* Fix invalid refresh rate detection on old macOS versions (Display, macOS)
* Fix disk size detection on 32-bit systems (Disk, BSD)
* Don't ignore disabled GPUs (#1140, GPU, Linux)
* Fix GPU type detection on FreeBSD (GPU, FreeBSD)
* Remove shell version detection for unknown shells (#1144, Shell)
* Don't detect hyfetch as shell on NixOS (Shell, NixOS)
Logos:
* Update EndeavourOS_small
* Add QTS
# 2.20.0
This release fixes regression of `2.19.0` on M1 MacBook Air. It also introduces a new option `--key-type icon` to display predefined icons in keys (requires newest nerd font). See `fastfetch -h key-type` for detail.
@@ -6,7 +87,7 @@ Changes:
* JSON option `display.keyWidth` has been renamed to `display.key.width`
* Previously: `{ "display": { "keyWidth": 3 } }`
* Now: `{ "display": { "key": { "width": 3 } } }`
* Windows Terminal font detection **in WSL** has been removed due to [issue #1113](https://github.com/fastfetch/fastfetch/issues/1113)
* Windows Terminal font detection **in WSL** has been removed due to [issue #1113](https://github.com/fastfetch-cli/fastfetch/issues/1113)
Features:
* Add option `display.key.type: <enum>` to print icons in keys
+78 -33
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.20.0
VERSION 2.21.2
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -17,7 +17,7 @@ if(ANDROID)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
set(BSD TRUE CACHE BOOL "..." FORCE)
set(FreeBSD TRUE CACHE BOOL "..." FORCE)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
set(SunOS TRUE CACHE BOOL "..." FORCE)
elseif(NOT APPLE AND NOT WIN32)
@@ -44,32 +44,32 @@ include(CheckIncludeFile)
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD OR APPLE OR SunOS" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF)
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE OR SunOS" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR APPLE OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF)
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR WIN32 OR SunOS" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
@@ -202,10 +202,10 @@ if (SET_TWEAK AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git describe --tags
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE PROJECT_VERSION_TWEAK
OUTPUT_VARIABLE PROJECT_VERSION_GIT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}")
string(REGEX MATCH "-[0-9]+" PROJECT_VERSION_TWEAK "${PROJECT_VERSION_GIT}")
endif()
if(PROJECT_VERSION_TWEAK)
string(REGEX MATCH "[0-9]+" PROJECT_VERSION_TWEAK_NUM "${PROJECT_VERSION_TWEAK}")
@@ -294,6 +294,7 @@ set(LIBFASTFETCH_SRC
src/common/properties.c
src/common/settings.c
src/common/temps.c
src/detection/bluetoothradio/bluetoothradio.c
src/detection/bootmgr/bootmgr.c
src/detection/chassis/chassis.c
src/detection/cpu/cpu.c
@@ -326,6 +327,7 @@ set(LIBFASTFETCH_SRC
src/modules/battery/battery.c
src/modules/bios/bios.c
src/modules/bluetooth/bluetooth.c
src/modules/bluetoothradio/bluetoothradio.c
src/modules/board/board.c
src/modules/bootmgr/bootmgr.c
src/modules/brightness/brightness.c
@@ -421,6 +423,7 @@ if(LINUX)
src/detection/cpuusage/cpuusage_linux.c
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/disk/disk_linux.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_linux.c
@@ -478,6 +481,7 @@ if(LINUX)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
@@ -488,6 +492,7 @@ elseif(ANDROID)
src/detection/battery/battery_android.c
src/detection/bios/bios_android.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_android.c
src/detection/bootmgr/bootmgr_nosupport.c
src/detection/brightness/brightness_nosupport.c
@@ -539,7 +544,7 @@ elseif(ANDROID)
src/detection/camera/camera_android.c
src/util/platform/FFPlatform_unix.c
)
elseif(BSD)
elseif(FreeBSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
@@ -550,6 +555,7 @@ elseif(BSD)
src/detection/battery/battery_bsd.c
src/detection/bios/bios_bsd.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/bluetoothradio/bluetoothradio_linux.c
src/detection/board/board_bsd.c
src/detection/bootmgr/bootmgr_bsd.c
src/detection/brightness/brightness_bsd.c
@@ -615,6 +621,7 @@ elseif(BSD)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
@@ -626,6 +633,7 @@ elseif(APPLE)
src/detection/battery/battery_apple.c
src/detection/bios/bios_apple.c
src/detection/bluetooth/bluetooth_apple.m
src/detection/bluetoothradio/bluetoothradio_apple.m
src/detection/board/board_apple.c
src/detection/bootmgr/bootmgr_apple.c
src/detection/brightness/brightness_apple.c
@@ -689,6 +697,7 @@ elseif(WIN32)
src/detection/battery/battery_windows.c
src/detection/bios/bios_windows.c
src/detection/bluetooth/bluetooth_windows.c
src/detection/bluetoothradio/bluetoothradio_windows.c
src/detection/board/board_windows.c
src/detection/bootmgr/bootmgr_windows.c
src/detection/brightness/brightness_windows.cpp
@@ -763,6 +772,7 @@ elseif(SunOS)
src/detection/cpuusage/cpuusage_sunos.c
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/disk/disk_sunos.c
src/detection/dns/dns_linux.c
src/detection/physicaldisk/physicaldisk_nosupport.c
@@ -819,6 +829,7 @@ elseif(SunOS)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
)
endif()
@@ -828,14 +839,14 @@ if(ENABLE_DIRECTX_HEADERS)
endif()
# Proprietary GPU driver APIs
if(LINUX OR BSD OR WIN32)
if(LINUX OR FreeBSD OR WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_mthreads.c)
endif()
if(WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c)
endif()
include(CheckFunctionExists)
check_function_exists(wcwidth HAVE_WCWIDTH)
if(NOT HAVE_WCWIDTH)
@@ -888,7 +899,7 @@ if(APPLE AND EXISTS "/usr/bin/otool")
target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(BSD AND EXISTS "/usr/local/bin/objdump")
if(FreeBSD AND EXISTS "/usr/local/bin/objdump")
execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[^ )]*' -o | sort -Vru | head -1"
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
@@ -1056,10 +1067,6 @@ ff_lib_enable(OPENCL
"OpenCL"
"OpenCL"
)
ff_lib_enable(LIBNM
"libnm"
"libnm"
)
ff_lib_enable(FREETYPE
"freetype2"
"FreeType2"
@@ -1072,6 +1079,10 @@ ff_lib_enable(DDCUTIL
"ddcutil"
"Ddcutil"
)
ff_lib_enable(ELF
"libelf"
"libelf"
)
ff_lib_enable(DIRECTX_HEADERS
"DirectX-Headers"
"DirectX-Headers"
@@ -1125,7 +1136,7 @@ elseif(WIN32)
PRIVATE "hid"
PRIVATE "wtsapi32"
)
elseif(BSD)
elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "usbhid"
@@ -1178,7 +1189,41 @@ if(WIN32)
PRIVATE "-static" # stdc++, winpthread, gcc_s, etc.
)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)
endif()
if(LINUX)
CHECK_INCLUDE_FILE("linux/videodev2.h" HAVE_LINUX_VIDEODEV2)
if(HAVE_LINUX_VIDEODEV2)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LINUX_VIDEODEV2=1)
endif()
CHECK_INCLUDE_FILE("linux/wireless.h" HAVE_LINUX_WIRELESS)
if(HAVE_LINUX_WIRELESS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LINUX_WIRELESS=1)
endif()
endif()
if(NOT WIN32)
CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX)
if(HAVE_UTMPX)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1)
endif()
CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP)
if(HAVE_WORDEXP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1)
endif()
if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT)
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
if(HAVE_PTHREAD_NP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_PTHREAD_NP=1)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} pthread_np.h)
endif()
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} Threads::Threads)
check_function_exists("pthread_timedjoin_np" HAVE_TIMEDJOIN_NP)
if(HAVE_TIMEDJOIN_NP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_TIMEDJOIN_NP=1)
else()
message(WARNING "pthread_timedjoin_np was not found; networking timeout will not work")
endif()
endif()
endif()
######################
+18
View File
@@ -1,3 +1,21 @@
fastfetch (2.21.1) jammy; urgency=medium
* Update to 2.21.1
-- Carter Li <zhangsongcui@live.cn> Fri, 09 Aug 2024 14:27:10 +0800
fastfetch (2.21.0) jammy; urgency=medium
* Update to 2.21.0
-- Carter Li <zhangsongcui@live.cn> Mon, 05 Aug 2024 14:35:43 +0800
fastfetch (2.20.0) jammy; urgency=medium
* Update to 2.20.0
-- Carter Li <zhangsongcui@live.cn> Fri, 26 Jul 2024 14:02:50 +0800
fastfetch (2.19.1) jammy; urgency=medium
* Update to 2.19.1
+1 -1
View File
@@ -2,7 +2,7 @@ Source: fastfetch
Section: universe/utils
Priority: optional
Maintainer: Carter Li <zhangsongcui@live.cn>
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Standards-Version: 4.0.0
Homepage: https://github.com/fastfetch-cli/fastfetch
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.19.1_source.buildinfo universe/utils optional
fastfetch_2.21.1_source.buildinfo universe/utils optional
+46 -4
View File
@@ -357,9 +357,17 @@
"additionalProperties": false,
"properties": {
"stat": {
"type": "boolean",
"description": "Show time usage (in ms) for individual modules",
"default": false
"description": "Show time usage (in ms) for individual modules with optional threshold",
"oneOf": [
{
"type": "boolean",
"default": false
},
{
"type": "integer",
"minimum": 1
}
]
},
"pipe": {
"type": "boolean",
@@ -730,6 +738,10 @@
"ddcutil": {
"description": "Used for brightness detection of external displays (Linux)",
"type": "string"
},
"elf": {
"description": "Used for st terminal font detection and systemd version detection (Linux)",
"type": "string"
}
}
},
@@ -745,6 +757,7 @@
"battery",
"bios",
"bluetooth",
"bluetoothradio",
"board",
"bootmgr",
"break",
@@ -1049,7 +1062,7 @@
"additionalProperties": false,
"properties": {
"type": {
"description": "List bluetooth devices",
"description": "List (connected) bluetooth devices",
"const": "bluetooth"
},
"showDisconnected": {
@@ -1080,6 +1093,35 @@
}
}
},
{
"title": "Bluetooth Radio",
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"description": "List bluetooth radios width supported version and vendor",
"const": "bluetoothradio"
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyIcon": {
"$ref": "#/$defs/keyIcon"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"outputColor": {
"$ref": "#/$defs/outputColor"
},
"format": {
"$ref": "#/$defs/format"
}
}
},
{
"title": "Brightness",
"type": "object",
+5 -1
View File
@@ -58,7 +58,10 @@
"poweradapter",
"player",
"media",
"publicip",
{
"type": "publicip",
"timeout": 1000
},
{
"type": "localip",
"showIpv6": true,
@@ -73,6 +76,7 @@
"opencl",
"users",
"bluetooth",
"bluetoothradio",
"sound",
"camera",
"gamepad",
+2 -1
View File
@@ -75,7 +75,8 @@
},
{
"type": "publicip",
"key": "WAN IP"
"key": "WAN IP",
"timeout": 1000
}
]
}
+5 -1
View File
@@ -60,7 +60,10 @@
"poweradapter",
"player",
"media",
"publicip",
{
"type": "publicip",
"timeout": 1000
},
{
"type": "localip",
"showIpv6": true,
@@ -75,6 +78,7 @@
"opencl",
"users",
"bluetooth",
"bluetoothradio",
"sound",
"camera",
"gamepad",
+2 -1
View File
@@ -97,7 +97,8 @@
{
"key": "Public IP ",
"keyColor": "cyan",
"type": "publicip"
"type": "publicip",
"timeout": 1000
},
"break",
{
+4 -1
View File
@@ -66,7 +66,10 @@
"type": "localip",
"compact": true
},
"publicip",
{
"type": "publicip",
"timeout": 1000
},
{
"type": "wifi",
"format": "{ssid}"
+1 -1
View File
@@ -106,7 +106,7 @@
{
"type": "cpu",
"key": "│ CPU FREQ │{$1}",
"format": "{freq-max}{/freq-max}{freq-base}{/} GHz"
"format": "{freq-max}{/freq-max}{freq-base}{/}"
},
{
"type": "loadavg",
+57
View File
@@ -0,0 +1,57 @@
// designed for presenting Vanilla Linux
// inspired from imstilllearnin's Vanilla Logo Ultra
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "small"
},
"display": {
"color": {
"output": "cyan"
},
"separator": ""
},
"modules": [
{
"type": "kernel",
"key": "Vanilla ",
"keyColor": "blue"
},
{
"type": "packages",
"key": " [_Packages_> ",
"keyColor": "green"
},
{
"type": "localip",
"key": " [_Local_IP_> ",
"keyColor": "green"
},
{
"type": "cpu",
"key": " [_CPU______> ",
"keyColor": "magenta"
},
{
"type": "memory",
"key": " [_RAM______> ",
"keyColor": "magenta"
},
{
"type": "swap",
"key": " [_SWAP_____> ",
"keyColor": "magenta"
},
{
"type": "disk",
"key": " [_Disk_____> ",
"keyColor": "magenta"
},
"break",
{
"type":"colors",
"paddingLeft": 9,
"symbol": "circle"
}
]
}
+2 -1
View File
@@ -161,7 +161,8 @@
{
"type": "publicip",
"key": "├─󰩠",
"keyColor": "blue"
"keyColor": "blue",
"timeout": 1000
},
{
"type": "wifi",
+11 -7
View File
@@ -1,4 +1,5 @@
#include "commandoption.h"
#include "common/color.h"
#include "common/printing.h"
#include "common/time.h"
#include "common/jsonconfig.h"
@@ -105,32 +106,35 @@ static void parseStructureCommand(
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
{
//Parse the structure and call the modules
int32_t thres = instance.config.display.stat;
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
uint64_t ms = 0;
if(instance.config.display.stat)
double ms = 0;
if(thres >= 0)
ms = ffTimeGetTick();
parseStructureCommand(data->structure.chars + startIndex, genJsonResult, jsonDoc);
if(instance.config.display.stat)
if(thres >= 0)
{
ms = ffTimeGetTick() - ms;
if (jsonDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
}
else
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
char str[64];
int len = snprintf(str, sizeof str, "%.3fms", ms);
if (thres > 0)
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_RED), ms);
printf("\e[s\e[1A\e[9999999C\e[%dD%s\e[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
}
+64 -29
View File
@@ -10,9 +10,8 @@ static bool loadLibSymbols(FFDBusLibrary* lib)
FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_append_args, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false)
@@ -20,10 +19,6 @@ static bool loadLibSymbols(FFDBusLibrary* lib)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false)
dbus = NULL; // don't auto dlclose
return true;
}
@@ -56,11 +51,11 @@ const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data)
return NULL;
}
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_STRING)
if(argType == DBUS_TYPE_STRING || argType == DBUS_TYPE_OBJECT_PATH)
{
const char* value = NULL;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
@@ -72,6 +67,14 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
return true;
}
if (argType == DBUS_TYPE_BYTE)
{
uint8_t value;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
ffStrbufAppendC(result, (char) value);
return false; // Don't append a comma
}
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
return false;
@@ -79,7 +82,7 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
return ffDBusGetValue(dbus, &subIter, result);
return ffDBusGetString(dbus, &subIter, result);
//At this point we have an array
@@ -87,13 +90,16 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
while(true)
{
if(ffDBusGetValue(dbus, &subIter, result))
if(ffDBusGetString(dbus, &subIter, result))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(dbus, &subIter);
if(!dbus->lib->ffdbus_message_iter_next(&subIter))
break;
else
continue;
}
if(foundAValue)
@@ -122,11 +128,27 @@ bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result)
return ffDBusGetBool(dbus, &subIter, result);
}
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_BYTE)
{
uint8_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if(argType == DBUS_TYPE_UINT16)
{
uint16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if(argType == DBUS_TYPE_UINT32)
{
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
return true;
@@ -137,15 +159,18 @@ bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetByte(dbus, &subIter, result);
return ffDBusGetUint(dbus, &subIter, result);
}
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method)
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg)
{
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
if(message == NULL)
return NULL;
if (arg)
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
dbus->lib->ffdbus_message_unref(message);
@@ -159,20 +184,10 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
if(message == NULL)
return NULL;
DBusMessageIter requestIterator;
dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator);
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
dbus->lib->ffdbus_message_unref(message);
return NULL;
}
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
dbus->lib->ffdbus_message_unref(message);
return NULL;
}
dbus->lib->ffdbus_message_append_args(message,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
@@ -194,7 +209,27 @@ bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char*
return false;
}
bool ret = ffDBusGetValue(dbus, &rootIterator, result);
bool ret = ffDBusGetString(dbus, &rootIterator, result);
dbus->lib->ffdbus_message_unref(reply);
return ret;
}
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result)
{
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
if(reply == NULL)
return false;
DBusMessageIter rootIterator;
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
dbus->lib->ffdbus_message_unref(reply);
return false;
}
bool ret = ffDBusGetUint(dbus, &rootIterator, result);
dbus->lib->ffdbus_message_unref(reply);
+6 -18
View File
@@ -6,23 +6,14 @@
#include "util/FFstrbuf.h"
#include "common/library.h"
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
{ \
if(!(dbus)->lib->ffdbus_message_iter_has_next(iterator)) \
break; \
(dbus)->lib->ffdbus_message_iter_next(iterator); \
continue; \
}
#define FF_DBUS_TIMEOUT_MILLISECONDS 100
typedef struct FFDBusLibrary
{
FF_LIBRARY_SYMBOL(dbus_bus_get)
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
FF_LIBRARY_SYMBOL(dbus_message_append_args)
FF_LIBRARY_SYMBOL(dbus_message_iter_init)
FF_LIBRARY_SYMBOL(dbus_message_iter_init_append)
FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic)
FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type)
FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic)
FF_LIBRARY_SYMBOL(dbus_message_iter_recurse)
@@ -30,10 +21,6 @@ typedef struct FFDBusLibrary
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
FF_LIBRARY_SYMBOL(dbus_message_unref)
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
FF_LIBRARY_SYMBOL(dbus_connection_flush)
FF_LIBRARY_SYMBOL(dbus_pending_call_block)
FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply)
FF_LIBRARY_SYMBOL(dbus_pending_call_unref)
} FFDBusLibrary;
typedef struct FFDBusData
@@ -43,11 +30,12 @@ typedef struct FFDBusData
} FFDBusData;
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result);
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method);
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result);
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg);
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
#endif // FF_HAVE_DBUS
+32 -32
View File
@@ -173,94 +173,94 @@ void ffDestroyInstance(void)
void ffListFeatures(void)
{
fputs(
#ifdef FF_HAVE_THREADS
#if FF_HAVE_THREADS
"threads\n"
#endif
#ifdef FF_HAVE_VULKAN
#if FF_HAVE_VULKAN
"vulkan\n"
#endif
#ifdef FF_HAVE_WAYLAND
#if FF_HAVE_WAYLAND
"wayland\n"
#endif
#ifdef FF_HAVE_XCB_RANDR
#if FF_HAVE_XCB_RANDR
"xcb-randr\n"
#endif
#ifdef FF_HAVE_XCB
#if FF_HAVE_XCB
"xcb\n"
#endif
#ifdef FF_HAVE_XRANDR
#if FF_HAVE_XRANDR
"xrandr\n"
#endif
#ifdef FF_HAVE_X11
#if FF_HAVE_X11
"x11\n"
#endif
#ifdef FF_HAVE_DRM
#if FF_HAVE_DRM
"drm\n"
#endif
#ifdef FF_HAVE_GIO
#if FF_HAVE_GIO
"gio\n"
#endif
#ifdef FF_HAVE_DCONF
#if FF_HAVE_DCONF
"dconf\n"
#endif
#ifdef FF_HAVE_DBUS
#if FF_HAVE_DBUS
"dbus\n"
#endif
#ifdef FF_HAVE_IMAGEMAGICK7
#if FF_HAVE_IMAGEMAGICK7
"imagemagick7\n"
#endif
#ifdef FF_HAVE_IMAGEMAGICK6
#if FF_HAVE_IMAGEMAGICK6
"imagemagick6\n"
#endif
#ifdef FF_HAVE_CHAFA
#if FF_HAVE_CHAFA
"chafa\n"
#endif
#ifdef FF_HAVE_ZLIB
#if FF_HAVE_ZLIB
"zlib\n"
#endif
#ifdef FF_HAVE_XFCONF
#if FF_HAVE_XFCONF
"xfconf\n"
#endif
#ifdef FF_HAVE_SQLITE3
#if FF_HAVE_SQLITE3
"sqlite3\n"
#endif
#ifdef FF_HAVE_RPM
#if FF_HAVE_RPM
"rpm\n"
#endif
#ifdef FF_HAVE_EGL
#if FF_HAVE_EGL
"egl\n"
#endif
#ifdef FF_HAVE_GLX
#if FF_HAVE_GLX
"glx\n"
#endif
#ifdef FF_HAVE_OSMESA
#if FF_HAVE_OSMESA
"osmesa\n"
#endif
#ifdef FF_HAVE_OPENCL
#if FF_HAVE_OPENCL
"opencl\n"
#endif
#ifdef FF_HAVE_FREETYPE
#if FF_HAVE_FREETYPE
"freetype\n"
#endif
#ifdef FF_HAVE_PULSE
#if FF_HAVE_PULSE
"libpulse\n"
#endif
#ifdef FF_HAVE_LIBNM
"libnm\n"
#endif
#ifdef FF_HAVE_DDCUTIL
#if FF_HAVE_DDCUTIL
"libddcutil\n"
#endif
#ifdef FF_HAVE_DIRECTX_HEADERS
#if FF_HAVE_ELF
"libelf\n"
#endif
#if FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
#ifdef FF_USE_SYSTEM_YYJSON
#if FF_USE_SYSTEM_YYJSON
"System yyjson\n"
#endif
#if __has_include(<linux/videodev2.h>)
#if FF_HAVE_LINUX_VIDEODEV2
"linux/videodev2\n"
#endif
#if __has_include(<linux/wireless.h>)
#if FF_HAVE_LINUX_WIRELESS
"linux/wireless\n"
#endif
""
+28 -33
View File
@@ -8,8 +8,10 @@
#include <dirent.h>
#include <errno.h>
#if __has_include(<wordexp.h>)
#include <wordexp.h>
#if FF_HAVE_WORDEXP
#include <wordexp.h>
#else
#warning "<wordexp.h> not available"
#endif
static void createSubfolders(const char* fileName)
@@ -112,7 +114,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
{
bool result = false;
#if __has_include(<wordexp.h>) // https://github.com/termux/termux-packages/pull/7056
#if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056
wordexp_t exp;
if(wordexp(in, &exp, 0) != 0)
@@ -131,46 +133,39 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
return result;
}
static int ftty = -1;
static struct termios oldTerm;
void restoreTerm(void)
{
tcsetattr(ftty, TCSAFLUSH, &oldTerm);
}
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
{
int fin = STDIN_FILENO, fout = STDOUT_FILENO;
FF_AUTO_CLOSE_FD int ftty = -1;
if (ftty < 0)
{
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
if (ftty < 0)
return "open(\"/dev/tty\", O_RDWR | O_NOCTTY | O_CLOEXEC) failed";
if (!isatty(STDIN_FILENO))
{
if (ftty < 0)
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
fin = ftty;
}
if (!isatty(STDOUT_FILENO))
{
if (ftty < 0)
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
fout = ftty;
if(tcgetattr(ftty, &oldTerm) == -1)
return "tcgetattr(STDIN_FILENO, &oldTerm) failed";
struct termios newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(ftty, TCSAFLUSH, &newTerm) == -1)
return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)";
atexit(restoreTerm);
}
struct termios oldTerm;
if(tcgetattr(fin, &oldTerm) == -1)
return "tcgetattr(STDIN_FILENO, &oldTerm) failed";
struct termios newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(fin, TCSAFLUSH, &newTerm) == -1)
return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)";
ffWriteFDData(fout, strlen(request), request);
ffWriteFDData(ftty, strlen(request), request);
//Give the terminal some time to respond
if(poll(&(struct pollfd) { .fd = fin, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
{
tcsetattr(fin, TCSANOW, &oldTerm);
if(poll(&(struct pollfd) { .fd = ftty, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
return "poll() timeout or failed";
}
char buffer[512];
ssize_t bytesRead = read(fin, buffer, sizeof(buffer) - 1);
tcsetattr(fin, TCSANOW, &oldTerm);
ssize_t bytesRead = read(ftty, buffer, sizeof(buffer) - 1);
if(bytesRead <= 0)
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
+11 -7
View File
@@ -1,4 +1,5 @@
#include "fastfetch.h"
#include "common/color.h"
#include "common/jsonconfig.h"
#include "common/printing.h"
#include "common/io/io.h"
@@ -181,12 +182,13 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
if (!modules) return NULL;
if (!yyjson_is_arr(modules)) return "Property 'modules' must be an array of strings or objects";
int32_t thres = instance.config.display.stat;
yyjson_val* item;
size_t idx, max;
yyjson_arr_foreach(modules, idx, max, item)
{
uint64_t ms = 0;
if(!prepare && instance.config.display.stat)
double ms = 0;
if(!prepare && thres >= 0)
ms = ffTimeGetTick();
yyjson_val* module = item;
@@ -208,19 +210,21 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
else if(!parseModuleJsonObject(type, module, jsonDoc))
return "Unknown module type";
if(!prepare && instance.config.display.stat)
if(!prepare && thres >= 0)
{
ms = ffTimeGetTick() - ms;
if (jsonDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
}
else
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
char str[64];
int len = snprintf(str, sizeof str, "%.3fms", ms);
if (thres > 0)
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_RED), ms);
printf("\e[s\e[1A\e[9999999C\e[%dD%s\e[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
}
+1
View File
@@ -8,6 +8,7 @@ static FFModuleBaseInfo* B[] = {
(void*) &instance.config.modules.battery,
(void*) &instance.config.modules.bios,
(void*) &instance.config.modules.bluetooth,
(void*) &instance.config.modules.bluetoothRadio,
(void*) &instance.config.modules.board,
(void*) &instance.config.modules.bootmgr,
(void*) &instance.config.modules.break_,
+5
View File
@@ -206,6 +206,11 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
else FF_APPEND_COLOR_PROP_COND(title, colorTitle)
else FF_APPEND_COLOR_PROP_COND(output, colorOutput)
else FF_APPEND_COLOR_PROP_COND(separator, colorSeparator)
else
{
fprintf(stderr, "Error: invalid color code found: %s\n", value);
exit(479);
}
}
ffStrbufAppendC(buffer, *value);
++value;
+2 -2
View File
@@ -33,7 +33,7 @@
#else
#include <pthread.h>
#include <signal.h>
#if __has_include(<pthread_np.h>)
#if FF_HAVE_PTHREAD_NP
#include <pthread_np.h>
#endif
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
@@ -51,7 +51,7 @@
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
static inline bool ffThreadJoin(FFThreadType thread, FF_MAYBE_UNUSED uint32_t timeout)
{
#if (defined(__linux__) && !defined(__ANDROID__)) || __has_include(<pthread_np.h>)
#if HAVE_TIMEDJOIN_NP
if (timeout > 0)
{
struct timespec ts;
+4 -4
View File
@@ -9,22 +9,22 @@
#include <sysinfoapi.h>
#endif
static inline uint64_t ffTimeGetTick() //In msec
static inline double ffTimeGetTick(void) //In msec
{
#ifdef _WIN32
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
LARGE_INTEGER start;
QueryPerformanceCounter(&start);
return (uint64_t)(start.QuadPart * 1000 / frequency.QuadPart);
return (double) start.QuadPart * 1000 / (double) frequency.QuadPart;
#else
struct timespec timeNow;
clock_gettime(CLOCK_MONOTONIC, &timeNow);
return (uint64_t)(((uint64_t) timeNow.tv_sec * 1000u) + ((uint64_t) timeNow.tv_nsec / 1000000u));
return (double) timeNow.tv_sec * 1000. + (double) timeNow.tv_nsec / 1000000.;
#endif
}
static inline uint64_t ffTimeGetNow()
static inline uint64_t ffTimeGetNow(void)
{
#ifdef _WIN32
uint64_t timeNow;
+7
View File
@@ -935,6 +935,13 @@
"arg": {
"type": "path"
}
},
{
"long": "lib-elf",
"desc": "Used for st terminal font detection and systemd version detection",
"arg": {
"type": "path"
}
}
],
"Module specific": [
+19 -18
View File
@@ -61,13 +61,17 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(ffStrEquals(deviceProperty, "Address"))
ffDBusGetValue(dbus, &dictIter, &device->address);
ffDBusGetString(dbus, &dictIter, &device->address);
else if(ffStrEquals(deviceProperty, "Name"))
ffDBusGetValue(dbus, &dictIter, &device->name);
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Icon"))
ffDBusGetValue(dbus, &dictIter, &device->type);
ffDBusGetString(dbus, &dictIter, &device->type);
else if(ffStrEquals(deviceProperty, "Percentage"))
ffDBusGetByte(dbus, &dictIter, &device->battery);
{
uint32_t percentage;
if (ffDBusGetUint(dbus, &dictIter, &percentage))
device->battery = (uint8_t) percentage;
}
else if(ffStrEquals(deviceProperty, "Connected"))
ffDBusGetBool(dbus, &dictIter, &device->connected);
}
@@ -86,8 +90,8 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL)
return; //We don't care about other properties
if(!ffStrContains(propertyType, ".Device") && !ffStrContains(propertyType, ".Battery"))
return; // We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
@@ -97,11 +101,10 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
while(true)
do
{
detectBluetoothValue(dbus, &arrayIter, device);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
@@ -118,8 +121,8 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We don't want adapter objects
if(strstr(objectPath, "dev_") == NULL)
// We don't want adapter objects
if(!ffStrContains(objectPath, "/dev_"))
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
@@ -137,11 +140,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
device->battery = 0;
device->connected = false;
while(true)
do
{
detectBluetoothProperty(dbus, &arrayIter, device);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
@@ -160,11 +162,10 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
while(true)
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices)
@@ -174,7 +175,7 @@ static const char* detectBluetooth(FFlist* devices)
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
if(!managedObjects)
return "Failed to call GetManagedObjects";
+13 -21
View File
@@ -15,43 +15,35 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextDevice)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindDeviceClose)
BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = {
BLUETOOTH_DEVICE_INFO btdi = {
.dwSize = sizeof(btdi)
};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) {
.fReturnConnected = TRUE,
.fReturnRemembered = TRUE,
.fReturnAuthenticated = TRUE,
.fReturnUnknown = TRUE,
.dwSize = sizeof(btsp)
};
BLUETOOTH_DEVICE_INFO btdi = {
.dwSize = sizeof(btdi)
};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&btsp, &btdi);
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)
}, &btdi);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return "No Bluetooth devices found";
else
return "BluetoothFindFirstDevice() failed";
return "BluetoothFindFirstDevice() failed";
}
do {
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
ffStrbufSetWS(&device->name, btdi.szName);
ffStrbufAppendF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
ffStrbufInitWS(&device->name, btdi.szName);
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
btdi.Address.rgBytes[0],
btdi.Address.rgBytes[1],
btdi.Address.rgBytes[2],
btdi.Address.rgBytes[3],
btdi.Address.rgBytes[4],
btdi.Address.rgBytes[5]);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
if(BitTest(&btdi.ulClassofDevice, 13))
@@ -0,0 +1,112 @@
#include "bluetoothradio.h"
// https://github.com/ziglang/zig/blob/a84951465b409495095a9598db0cae745f34fa7b/lib/libc/include/any-windows-any/bthdef.h#L187-L236
#define BTH_MFG_ERICSSON 0
#define BTH_MFG_NOKIA 1
#define BTH_MFG_INTEL 2
#define BTH_MFG_IBM 3
#define BTH_MFG_TOSHIBA 4
#define BTH_MFG_3COM 5
#define BTH_MFG_MICROSOFT 6
#define BTH_MFG_LUCENT 7
#define BTH_MFG_MOTOROLA 8
#define BTH_MFG_INFINEON 9
#define BTH_MFG_CSR 10
#define BTH_MFG_SILICONWAVE 11
#define BTH_MFG_DIGIANSWER 12
#define BTH_MFG_TI 13
#define BTH_MFG_PARTHUS 14
#define BTH_MFG_BROADCOM 15
#define BTH_MFG_MITEL 16
#define BTH_MFG_WIDCOMM 17
#define BTH_MFG_ZEEVO 18
#define BTH_MFG_ATMEL 19
#define BTH_MFG_MITSIBUSHI 20
#define BTH_MFG_RTX_TELECOM 21
#define BTH_MFG_KC_TECHNOLOGY 22
#define BTH_MFG_NEWLOGIC 23
#define BTH_MFG_TRANSILICA 24
#define BTH_MFG_ROHDE_SCHWARZ 25
#define BTH_MFG_TTPCOM 26
#define BTH_MFG_SIGNIA 27
#define BTH_MFG_CONEXANT 28
#define BTH_MFG_QUALCOMM 29
#define BTH_MFG_INVENTEL 30
#define BTH_MFG_AVM_BERLIN 31
#define BTH_MFG_BANDSPEED 32
#define BTH_MFG_MANSELLA 33
#define BTH_MFG_NEC 34
#define BTH_MFG_WAVEPLUS_TECHNOLOGY_CO 35
#define BTH_MFG_ALCATEL 36
#define BTH_MFG_PHILIPS_SEMICONDUCTOR 37
#define BTH_MFG_C_TECHNOLOGIES 38
#define BTH_MFG_OPEN_INTERFACE 39
#define BTH_MFG_RF_MICRO_DEVICES 40
#define BTH_MFG_HITACHI 41
#define BTH_MFG_SYMBOL_TECHNOLOGIES 42
#define BTH_MFG_TENOVIS 43
#define BTH_MFG_MACRONIX_INTERNATIONAL 44
#define BTH_MFG_MARVELL 72
#define BTH_MFG_APPLE 76
#define BTH_MFG_NORDIC_SEMICONDUCTORS_ASA 89
#define BTH_MFG_ARUBA_NETWORKS 283
#define BTH_MFG_INTERNAL_USE 65535
const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId)
{
switch (manufacturerId)
{
case BTH_MFG_ERICSSON: return "Ericsson";
case BTH_MFG_NOKIA: return "Nokia";
case BTH_MFG_INTEL: return "Intel";
case BTH_MFG_IBM: return "IBM";
case BTH_MFG_TOSHIBA: return "Toshiba";
case BTH_MFG_3COM: return "3Com";
case BTH_MFG_MICROSOFT: return "Microsoft";
case BTH_MFG_LUCENT: return "Lucent";
case BTH_MFG_MOTOROLA: return "Motorola";
case BTH_MFG_INFINEON: return "Infineon";
case BTH_MFG_CSR: return "CSR";
case BTH_MFG_SILICONWAVE: return "Silicon-Wave";
case BTH_MFG_DIGIANSWER: return "Digi-Answer";
case BTH_MFG_TI: return "Ti";
case BTH_MFG_PARTHUS: return "Parthus";
case BTH_MFG_BROADCOM: return "Broadcom";
case BTH_MFG_MITEL: return "Mitel";
case BTH_MFG_WIDCOMM: return "Widcomm";
case BTH_MFG_ZEEVO: return "Zeevo";
case BTH_MFG_ATMEL: return "Atmel";
case BTH_MFG_MITSIBUSHI: return "Mitsubishi";
case BTH_MFG_RTX_TELECOM: return "RTX Telecom";
case BTH_MFG_KC_TECHNOLOGY: return "KC Technology";
case BTH_MFG_NEWLOGIC: return "Newlogic";
case BTH_MFG_TRANSILICA: return "Transilica";
case BTH_MFG_ROHDE_SCHWARZ: return "Rohde-Schwarz";
case BTH_MFG_TTPCOM: return "TTPCom";
case BTH_MFG_SIGNIA: return "Signia";
case BTH_MFG_CONEXANT: return "Conexant";
case BTH_MFG_QUALCOMM: return "Qualcomm";
case BTH_MFG_INVENTEL: return "Inventel";
case BTH_MFG_AVM_BERLIN: return "AVM Berlin";
case BTH_MFG_BANDSPEED: return "Bandspeed";
case BTH_MFG_MANSELLA: return "Mansella";
case BTH_MFG_NEC: return "NEC";
case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: return "Waveplus";
case BTH_MFG_ALCATEL: return "Alcatel";
case BTH_MFG_PHILIPS_SEMICONDUCTOR: return "Philips Semiconductors";
case BTH_MFG_C_TECHNOLOGIES: return "C Technologies";
case BTH_MFG_OPEN_INTERFACE: return "Open Interface";
case BTH_MFG_RF_MICRO_DEVICES: return "RF Micro Devices";
case BTH_MFG_HITACHI: return "Hitachi";
case BTH_MFG_SYMBOL_TECHNOLOGIES: return "Symbol Technologies";
case BTH_MFG_TENOVIS: return "Tenovis";
case BTH_MFG_MACRONIX_INTERNATIONAL: return "Macronix International";
case BTH_MFG_MARVELL: return "Marvell";
case BTH_MFG_APPLE: return "Apple";
case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: return "Nordic Semiconductor ASA";
case BTH_MFG_ARUBA_NETWORKS: return "Aruba Networks";
case BTH_MFG_INTERNAL_USE: return "Internal Use";
default: return "Unknown";
}
}
@@ -0,0 +1,18 @@
#pragma once
#include "fastfetch.h"
typedef struct FFBluetoothRadioResult
{
FFstrbuf name;
FFstrbuf address;
FFstrbuf vendor;
int32_t lmpVersion;
int32_t lmpSubversion;
bool enabled;
bool discoverable;
bool connectable;
} FFBluetoothRadioResult;
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */);
const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId);
@@ -0,0 +1,69 @@
#include "bluetoothradio.h"
#include "common/processing.h"
#import <IOBluetooth/IOBluetooth.h>
// For some reason the official declaration of IOBluetoothHostController don't include property `controllers`
@interface IOBluetoothHostController()
+ (id)controllers;
@end
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */)
{
NSArray<IOBluetoothHostController*>* ctrls = IOBluetoothHostController.controllers;
if(!ctrls)
return "IOBluetoothHostController.controllers returns nil";
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffProcessAppendStdOut(&buffer, (char* const[]) {
"system_profiler",
"SPBluetoothDataType",
"-xml",
"-detailLevel",
"basic",
NULL
}) != NULL)
return "Starting `system_profiler SPBluetoothDataType -xml -detailLevel basic` failed";
NSArray* arr = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytes:buffer.chars length:buffer.length]
options:NSPropertyListImmutable
format:nil
error:nil];
if (!arr || !arr.count)
return "system_profiler SPBluetoothDataType returned an empty array";
for (IOBluetoothHostController* ctrl in ctrls)
{
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String);
ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String);
ffStrbufInitStatic(&device->vendor, "Apple");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON;
device->discoverable = false;
device->connectable = true;
for (NSDictionary* itemDict in arr[0][@"_items"])
{
NSDictionary* props = itemDict[@"controller_properties"];
if (!props) continue;
if (![ctrl.addressAsString isEqualToString:props[@"controller_address"]]) continue;
NSString* services = props[@"controller_supportedServices"];
if ([services containsString:@" LEA "])
device->lmpVersion = -11;
else if ([services containsString:@" GATT "])
device->lmpVersion = -6;
device->discoverable = ![props[@"controller_discoverable"] isEqualToString:@"attrib_off"];
ffStrbufSetS(&device->vendor, ((NSString*) props[@"controller_vendorID"]).UTF8String);
ffStrbufSubstrAfterFirstC(&device->vendor, '(');
ffStrbufTrimRight(&device->vendor, ')');
break;
}
}
return NULL;
}
@@ -0,0 +1,207 @@
#include "bluetoothradio.h"
#include "util/stringUtils.h"
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
dict entry(
object path "/org/bluez/hci0"
array [
dict entry(
string "org.bluez.Adapter1"
array [
dict entry(
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "xxxxxxxx"
)
dict entry(
string "Powered"
variant boolean true
)
dict entry(
string "PowerState"
variant string "on"
)
dict entry(
string "Manufacturer"
variant uint16 2
)
dict entry(
string "Version"
variant byte 12
)
]
)
]
)
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(ffStrEquals(deviceProperty, "Address"))
ffDBusGetString(dbus, &dictIter, &device->address);
else if(ffStrEquals(deviceProperty, "Alias"))
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Manufacturer"))
{
uint32_t vendorId;
if (ffDBusGetUint(dbus, &dictIter, &vendorId))
ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(vendorId));
}
else if(ffStrEquals(deviceProperty, "Version"))
ffDBusGetUint(dbus, &dictIter, (uint32_t*) &device->lmpVersion);
else if(ffStrEquals(deviceProperty, "Powered"))
ffDBusGetBool(dbus, &dictIter, &device->enabled);
else if(ffStrEquals(deviceProperty, "Discoverable"))
ffDBusGetBool(dbus, &dictIter, &device->discoverable);
else if(ffStrEquals(deviceProperty, "Pairable"))
ffDBusGetBool(dbus, &dictIter, &device->connectable);
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(!ffStrContains(propertyType, ".Adapter"))
return; //We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
do
{
detectBluetoothValue(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We want adapter objects
if(!ffStrStartsWith(objectPath, "/org/bluez/hci") || ffStrContains(objectPath, "/dev_"))
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
do
{
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
--devices->length;
}
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices)
{
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
if(!managedObjects)
return "Failed to call GetManagedObjects";
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
{
dbus.lib->ffdbus_message_unref(managedObjects);
return "Failed to get root iterator of GetManagedObjects";
}
detectBluetoothRoot(devices, &dbus, &rootIter);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
#endif
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
#else
return "Fastfetch was compiled without DBus support";
#endif
}
@@ -0,0 +1,6 @@
#include "bluetoothradio.h"
const char* ffDetectBluetoothRadio(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothRadioResult */)
{
return "Not supported on this platform";
}
@@ -0,0 +1,105 @@
#include "bluetoothradio.h"
#include "common/library.h"
#include "common/io/io.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <bluetoothapis.h>
#include <winioctl.h>
// #include <bthioctl.h>
#define BTH_IOCTL_BASE 0
#define BTH_CTL(id) CTL_CODE(FILE_DEVICE_BLUETOOTH, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_BTH_GET_LOCAL_INFO BTH_CTL(BTH_IOCTL_BASE+0x00)
#define LMP_LE_SUPPORTED(x) ((x >> 38) & 1)
typedef struct _BTH_RADIO_INFO
{
// Supported LMP features of the radio. Use LMP_XXX() to extract
// the desired bits.
ULONGLONG lmpSupportedFeatures;
// Manufacturer ID (possibly BTH_MFG_XXX)
USHORT mfg;
// LMP subversion
USHORT lmpSubversion;
// LMP version
UCHAR lmpVersion;
} __attribute__((__packed__)) BTH_RADIO_INFO;
typedef struct _BTH_LOCAL_RADIO_INFO
{
// Local BTH_ADDR, class of device, and radio name
BTH_DEVICE_INFO localInfo;
// Combo of LOCAL_RADIO_XXX values
ULONG flags;
// HCI revision, see core spec
USHORT hciRevision;
// HCI version, see core spec
UCHAR hciVersion;
// More information about the local radio (LMP, MFG)
BTH_RADIO_INFO radioInfo;
} __attribute__((__packed__)) BTH_LOCAL_RADIO_INFO;
static_assert(sizeof(BTH_LOCAL_RADIO_INFO) == 292, "BTH_LOCAL_RADIO_INFO should be 292 bytes");
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
// Actually bluetoothapis.dll, but it's missing on Windows 7
FF_LIBRARY_LOAD(bluetoothapis, NULL, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsConnectable)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsDiscoverable)
HANDLE hRadio = NULL;
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstRadio(&(BLUETOOTH_FIND_RADIO_PARAMS) {
.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS)
}, &hRadio);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return "No Bluetooth radios found or service disabled";
else
return "BluetoothFindFirstRadio() failed";
}
do {
BTH_LOCAL_RADIO_INFO blri;
DWORD returned;
if (!DeviceIoControl(hRadio, IOCTL_BTH_GET_LOCAL_INFO, NULL, 0, &blri, sizeof(blri), &returned, NULL))
continue;
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, blri.localInfo.name);
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
addr.rgBytes[0],
addr.rgBytes[1],
addr.rgBytes[2],
addr.rgBytes[3],
addr.rgBytes[4],
addr.rgBytes[5]);
device->lmpVersion = blri.radioInfo.lmpVersion;
device->lmpSubversion = blri.radioInfo.lmpSubversion;
ffStrbufInitStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg));
device->enabled = true;
device->connectable = ffBluetoothIsConnectable(hRadio);
device->discoverable = ffBluetoothIsDiscoverable(hRadio);
} while (ffBluetoothFindNextRadio(hFind, &hRadio));
ffBluetoothFindRadioClose(hFind);
return NULL;
}
+1 -1
View File
@@ -46,7 +46,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result);
DWORD uefiSecureBootEnabled = 0, bufSize = 0;
if (RegGetValueW(HKEY_LOCAL_MACHINE, L"SYSTEM\\ControlSet001\\Control\\SecureBoot\\State", L"UEFISecureBootEnabled", RRF_RT_REG_DWORD, NULL, &uefiSecureBootEnabled, &bufSize) == ERROR_SUCCESS)
if (RegGetValueW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\SecureBoot\\State", L"UEFISecureBootEnabled", RRF_RT_REG_DWORD, NULL, &uefiSecureBootEnabled, &bufSize) == ERROR_SUCCESS)
result->secureBoot = !!uefiSecureBootEnabled;
return NULL;
+2 -2
View File
@@ -5,13 +5,13 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#if __has_include(<linux/videodev2.h>)
#if FF_HAVE_LINUX_VIDEODEV2
#include <linux/videodev2.h>
#endif
const char* ffDetectCamera(FFlist* result)
{
#if __has_include(<linux/videodev2.h>)
#if FF_HAVE_LINUX_VIDEODEV2
char path[] = "/dev/videoN";
for (uint32_t i = 0; i <= 9; ++i)
+358
View File
@@ -0,0 +1,358 @@
#pragma once
#include "fastfetch.h"
// https://github.com/util-linux/util-linux/blob/master/sys-utils/lscpu-arm.c
// We use the util-linux's data but not its code. Call me if it violates util-linux's GPL license.
static const char* hwImplId2Vendor(uint32_t implId)
{
switch (implId)
{
case 0x41: return "ARM";
case 0x42: return "Broadcom";
case 0x43: return "Cavium";
case 0x44: return "DEC";
case 0x46: return "FUJITSU";
case 0x48: return "HiSilicon";
case 0x49: return "Infineon";
case 0x4d: return "Motorola";
case 0x4e: return "NVIDIA";
case 0x50: return "APM";
case 0x51: return "Qualcomm";
case 0x53: return "Samsung";
case 0x56: return "Marvell";
case 0x61: return "Apple";
case 0x66: return "Faraday";
case 0x69: return "Intel";
case 0x6D: return "Microsoft";
case 0x70: return "Phytium";
case 0xc0: return "Ampere";
default: return 0;
}
}
static const char* armPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x810: return "ARM810";
case 0x920: return "ARM920";
case 0x922: return "ARM922";
case 0x926: return "ARM926";
case 0x940: return "ARM940";
case 0x946: return "ARM946";
case 0x966: return "ARM966";
case 0xa20: return "ARM1020";
case 0xa22: return "ARM1022";
case 0xa26: return "ARM1026";
case 0xb02: return "ARM11 MPCore";
case 0xb36: return "ARM1136";
case 0xb56: return "ARM1156";
case 0xb76: return "ARM1176";
case 0xc05: return "Cortex-A5";
case 0xc07: return "Cortex-A7";
case 0xc08: return "Cortex-A8";
case 0xc09: return "Cortex-A9";
case 0xc0d: return "Cortex-A17"; /* Originally A12 */
case 0xc0f: return "Cortex-A15";
case 0xc0e: return "Cortex-A17";
case 0xc14: return "Cortex-R4";
case 0xc15: return "Cortex-R5";
case 0xc17: return "Cortex-R7";
case 0xc18: return "Cortex-R8";
case 0xc20: return "Cortex-M0";
case 0xc21: return "Cortex-M1";
case 0xc23: return "Cortex-M3";
case 0xc24: return "Cortex-M4";
case 0xc27: return "Cortex-M7";
case 0xc60: return "Cortex-M0+";
case 0xd01: return "Cortex-A32";
case 0xd02: return "Cortex-A34";
case 0xd03: return "Cortex-A53";
case 0xd04: return "Cortex-A35";
case 0xd05: return "Cortex-A55";
case 0xd06: return "Cortex-A65";
case 0xd07: return "Cortex-A57";
case 0xd08: return "Cortex-A72";
case 0xd09: return "Cortex-A73";
case 0xd0a: return "Cortex-A75";
case 0xd0b: return "Cortex-A76";
case 0xd0c: return "Neoverse-N1";
case 0xd0d: return "Cortex-A77";
case 0xd0e: return "Cortex-A76AE";
case 0xd13: return "Cortex-R52";
case 0xd15: return "Cortex-R82";
case 0xd16: return "Cortex-R52+";
case 0xd20: return "Cortex-M23";
case 0xd21: return "Cortex-M33";
case 0xd22: return "Cortex-M55";
case 0xd23: return "Cortex-M85";
case 0xd40: return "Neoverse-V1";
case 0xd41: return "Cortex-A78";
case 0xd42: return "Cortex-A78AE";
case 0xd43: return "Cortex-A65AE";
case 0xd44: return "Cortex-X1";
case 0xd46: return "Cortex-A510";
case 0xd47: return "Cortex-A710";
case 0xd48: return "Cortex-X2";
case 0xd49: return "Neoverse-N2";
case 0xd4a: return "Neoverse-E1";
case 0xd4b: return "Cortex-A78C";
case 0xd4c: return "Cortex-X1C";
case 0xd4d: return "Cortex-A715";
case 0xd4e: return "Cortex-X3";
case 0xd4f: return "Neoverse-V2";
case 0xd80: return "Cortex-A520";
case 0xd81: return "Cortex-A720";
case 0xd82: return "Cortex-X4";
default: return "Unknown";
}
}
static const char* brcmPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x0f: return "Brahma-B15";
case 0x100: return "Brahma-B53";
case 0x516: return "ThunderX2";
default: return "Unknown";
}
}
static const char* decPartId2name(uint32_t partId)
{
switch (partId)
{
case 0xa10: return "SA110";
case 0xa11: return "SA1100";
default: return "Unknown";
}
}
static const char* caviumPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x0a0: return "ThunderX";
case 0x0a1: return "ThunderX-88XX";
case 0x0a2: return "ThunderX-81XX";
case 0x0a3: return "ThunderX-83XX";
case 0x0af: return "ThunderX2-99xx";
case 0x0b0: return "OcteonTX2";
case 0x0b1: return "OcteonTX2-98XX";
case 0x0b2: return "OcteonTX2-96XX";
case 0x0b3: return "OcteonTX2-95XX";
case 0x0b4: return "OcteonTX2-95XXN";
case 0x0b5: return "OcteonTX2-95XXMM";
case 0x0b6: return "OcteonTX2-95XXO";
case 0x0b8: return "ThunderX3-T110";
default: return "Unknown";
}
}
static const char* apmPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x000: return "X-Gene";
default: return "Unknown";
}
}
static const char* qcomPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x001: return "Oryon";
case 0x00f: return "Scorpion";
case 0x02d: return "Scorpion";
case 0x04d: return "Krait";
case 0x06f: return "Krait";
case 0x201: return "Kryo";
case 0x205: return "Kryo";
case 0x211: return "Kryo";
case 0x800: return "Falkor-V1/Kryo";
case 0x801: return "Kryo-V2";
case 0x802: return "Kryo-3XX-Gold";
case 0x803: return "Kryo-3XX-Silver";
case 0x804: return "Kryo-4XX-Gold";
case 0x805: return "Kryo-4XX-Silver";
case 0xc00: return "Falkor";
case 0xc01: return "Saphira";
default: return "Unknown";
}
}
static const char* samsungPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x001: return "exynos-m1";
case 0x002: return "exynos-m3";
case 0x003: return "exynos-m4";
case 0x004: return "exynos-m5";
default: return "Unknown";
}
}
static const char* nvidiaPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x000: return "Denver";
case 0x003: return "Denver 2";
case 0x004: return "Carmel";
default: return "Unknown";
}
}
static const char* marvellPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x131: return "Feroceon-88FR131";
case 0x581: return "PJ4/PJ4b";
case 0x584: return "PJ4B-MP";
default: return "Unknown";
}
}
static const char* applePartId2name(uint32_t partId)
{
switch (partId)
{
case 0x000: return "Swift";
case 0x001: return "Cyclone";
case 0x002: return "Typhoon";
case 0x003: return "Typhoon/Capri";
case 0x004: return "Twister";
case 0x005: return "Twister/Elba/Malta";
case 0x006: return "Hurricane";
case 0x007: return "Hurricane/Myst";
case 0x008: return "Monsoon";
case 0x009: return "Mistral";
case 0x00b: return "Vortex";
case 0x00c: return "Tempest";
case 0x00f: return "Tempest-M9";
case 0x010: return "Vortex/Aruba";
case 0x011: return "Tempest/Aruba";
case 0x012: return "Lightning";
case 0x013: return "Thunder";
case 0x020: return "Icestorm-A14";
case 0x021: return "Firestorm-A14";
case 0x022: return "Icestorm-M1";
case 0x023: return "Firestorm-M1";
case 0x024: return "Icestorm-M1-Pro";
case 0x025: return "Firestorm-M1-Pro";
case 0x026: return "Thunder-M10";
case 0x028: return "Icestorm-M1-Max";
case 0x029: return "Firestorm-M1-Max";
case 0x030: return "Blizzard-A15";
case 0x031: return "Avalanche-A15";
case 0x032: return "Blizzard-M2";
case 0x033: return "Avalanche-M2";
case 0x034: return "Blizzard-M2-Pro";
case 0x035: return "Avalanche-M2-Pro";
case 0x036: return "Sawtooth-A16";
case 0x037: return "Everest-A16";
case 0x038: return "Blizzard-M2-Max";
case 0x039: return "Avalanche-M2-Max";
default: return "Unknown";
}
}
static const char* faradayPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x526: return "FA526";
case 0x626: return "FA626";
default: return "Unknown";
}
}
static const char* intelPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x200: return "i80200";
case 0x210: return "PXA250A";
case 0x212: return "PXA210A";
case 0x242: return "i80321-400";
case 0x243: return "i80321-600";
case 0x290: return "PXA250B/PXA26x";
case 0x292: return "PXA210B";
case 0x2c2: return "i80321-400-B0";
case 0x2c3: return "i80321-600-B0";
case 0x2d0: return "PXA250C/PXA255/PXA26x";
case 0x2d2: return "PXA210C";
case 0x411: return "PXA27x";
case 0x41c: return "IPX425-533";
case 0x41d: return "IPX425-400";
case 0x41f: return "IPX425-266";
case 0x682: return "PXA32x";
case 0x683: return "PXA930/PXA935";
case 0x688: return "PXA30x";
case 0x689: return "PXA31x";
case 0xb11: return "SA1110";
case 0xc12: return "IPX1200";
default: return "Unknown";
}
}
static const char* fujitsuPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x001: return "A64FX";
default: return "Unknown";
}
}
static const char* hisiPartId2name(uint32_t partId)
{
switch (partId)
{
case 0xd01: return "TaiShan-v110"; /* used in Kunpeng-920 SoC */
case 0xd02: return "TaiShan-v120"; /* used in Kirin 990A and 9000S SoCs */
case 0xd40: return "Cortex-A76"; /* HiSilicon uses this ID though advertises A76 */
case 0xd41: return "Cortex-A77"; /* HiSilicon uses this ID though advertises A77 */
default: return "Unknown";
}
}
static const char* amperePartId2name(uint32_t partId)
{
switch (partId)
{
case 0xac3: return "Ampere-1";
case 0xac4: return "Ampere-1a";
default: return "Unknown";
}
}
static const char* ftPartId2name(uint32_t partId)
{
switch (partId)
{
case 0x303: return "FTC310";
case 0x660: return "FTC660";
case 0x661: return "FTC661";
case 0x662: return "FTC662";
case 0x663: return "FTC663";
case 0x664: return "FTC664";
case 0x862: return "FTC862";
default: return "Unknown";
}
}
static const char* msPartId2name(uint32_t partId)
{
switch (partId)
{
case 0xd49: return "Azure-Cobalt-100";
default: return "Unknown";
}
}
+84 -102
View File
@@ -46,6 +46,8 @@ static void detectQualcomm(FFCPUResult* cpu)
else if (ffStrbufEqualS(&cpu->name, "SM6450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6 Gen 1 [SM6450]");
else if (ffStrbufEqualS(&cpu->name, "SM4635"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4s Gen 2 [SM4635]");
else if (ffStrbufEqualS(&cpu->name, "SM4450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 2 [SM4450]");
else if (ffStrbufEqualS(&cpu->name, "SM4375"))
@@ -72,19 +74,67 @@ static void detectAndroid(FFCPUResult* cpu)
}
#endif
static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz, FFstrbuf* cpuIsa, FFstrbuf* cpuUarch)
{
FF_AUTO_CLOSE_FILE FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
return "fopen(\"/proc/cpuinfo\", \"r\") failed";
#ifdef __aarch64__
#include "cpu_arm.h"
static void detectArmName(FILE* cpuinfo, FFCPUResult* cpu, uint32_t implId)
{
FF_AUTO_FREE char* line = NULL;
rewind(cpuinfo);
size_t len = 0;
const char* lastName = NULL;
uint32_t num = 0;
while(getline(&line, &len, cpuinfo) != -1)
{
if (!ffStrStartsWith(line, "CPU part\t: ")) continue;
uint32_t partId = (uint32_t) strtoul(line + strlen("CPU part\t: "), NULL, 16);
const char* name = NULL;
switch (implId)
{
case 0x41: name = armPartId2name(partId); break;
case 0x42: name = brcmPartId2name(partId); break;
case 0x43: name = caviumPartId2name(partId); break;
case 0x44: name = decPartId2name(partId); break;
case 0x46: name = fujitsuPartId2name(partId); break;
case 0x48: name = hisiPartId2name(partId); break;
case 0x4e: name = nvidiaPartId2name(partId); break;
case 0x50: name = apmPartId2name(partId); break;
case 0x51: name = qcomPartId2name(partId); break;
case 0x53: name = samsungPartId2name(partId); break;
case 0x56: name = marvellPartId2name(partId); break;
case 0x61: name = applePartId2name(partId); break;
case 0x66: name = faradayPartId2name(partId); break;
case 0x69: name = intelPartId2name(partId); break;
case 0x6d: name = msPartId2name(partId); break;
case 0x70: name = ftPartId2name(partId); break;
case 0xc0: name = amperePartId2name(partId); break;
default: name = "Unknown"; break;
}
if (lastName != name)
{
if (lastName)
{
if (num > 1)
ffStrbufAppendF(&cpu->name, "*%u", num);
ffStrbufAppendS(&cpu->name, " + ");
}
ffStrbufAppendS(&cpu->name, name);
lastName = name;
num = 1;
}
else
++num;
}
if (num > 1)
ffStrbufAppendF(&cpu->name, "*%u", num);
}
#endif
static const char* parseCpuInfo(FILE* cpuinfo, FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz, FFstrbuf* cpuIsa, FFstrbuf* cpuUarch, FFstrbuf* cpuImplementer)
{
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
#ifdef __aarch64__
FF_STRBUF_AUTO_DESTROY implementer = ffStrbufCreate();
#endif
while(getline(&line, &len, cpuinfo) != -1)
{
//Stop after the first CPU
@@ -99,35 +149,22 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
ffParsePropLine(line, "isa :", cpuIsa) ||
ffParsePropLine(line, "uarch :", cpuUarch) ||
#ifdef __aarch64__
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", &implementer)) ||
#if __aarch64__
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) ||
#endif
#if __ANDROID__
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
#endif
#if __powerpc__ || __powerpc
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
#endif
#if __mips__
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) || //For MIPS
#endif
false
);
}
#ifdef __aarch64__
// https://github.com/util-linux/util-linux/blob/2cd89de14549d2b2c079a4f8b73f75500d229fee/sys-utils/lscpu-arm.c#L286
if (cpu->vendor.length == 0 && implementer.length > 2 /* 0xX */)
{
uint32_t implId = (uint32_t) strtoul(implementer.chars, NULL, 16);
switch (implId)
{
case 0x41: ffStrbufSetStatic(&cpu->vendor, "ARM"); break;
case 0x42: ffStrbufSetStatic(&cpu->vendor, "Broadcom"); break;
case 0x48: ffStrbufSetStatic(&cpu->vendor, "HiSilicon"); break;
case 0x4e: ffStrbufSetStatic(&cpu->vendor, "Nvidia"); break;
case 0x51: ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); break;
case 0x53: ffStrbufSetStatic(&cpu->vendor, "Samsung"); break;
case 0x61: ffStrbufSetStatic(&cpu->vendor, "Apple"); break;
case 0x69: ffStrbufSetStatic(&cpu->vendor, "Intel"); break;
}
}
#endif
return NULL;
}
@@ -277,14 +314,19 @@ void detectAsahi(FFCPUResult* cpu)
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
FF_AUTO_CLOSE_FILE FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo == NULL)
return "fopen(\"/proc/cpuinfo\", \"r\") failed";
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY cpuIsa = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY cpuUarch = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY cpuImplementerStr = ffStrbufCreate();
const char* error = parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch);
const char* error = parseCpuInfo(cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr);
if (error) return error;
cpu->coresLogical = (uint16_t) get_nprocs_conf();
@@ -309,83 +351,23 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffStrbufAppend(&cpu->name, &cpuIsa);
}
#ifdef __aarch64__
uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16);
ffStrbufSetStatic(&cpu->vendor, hwImplId2Vendor(cpuImplementer));
#endif
#ifdef __ANDROID__
detectAndroid(cpu);
#endif
#if defined(__linux__) && defined(__aarch64__)
#if defined(__linux__) && defined(__aarch64__) && !defined(__ANDROID__)
detectAsahi(cpu);
#endif
#ifdef __aarch64__
if (cpu->name.length == 0)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL }) == NULL)
{
char* pstart = buffer.chars;
if (cpu->vendor.length == 0)
{
pstart = strstr(pstart, "Vendor ID:");
if (pstart)
{
pstart += strlen("Vendor ID:");
while (isspace(*pstart)) ++pstart;
if (*pstart)
{
char* pend = strchr(pstart, '\n');
if (pend != NULL)
ffStrbufAppendNS(&cpu->vendor, (uint32_t) (pend - pstart), pstart);
else
{
ffStrbufAppendS(&cpu->vendor, pstart);
}
pstart = pend + 1;
if (pstart >= buffer.chars + buffer.length)
return NULL;
}
}
else
{
pstart = buffer.chars;
}
}
while ((pstart = strstr(pstart, "Model name:")))
{
pstart += strlen("Model name:");
while (isspace(*pstart)) ++pstart;
if (*pstart == '\0')
break;
if (cpu->name.length > 0)
ffStrbufAppendS(&cpu->name, " + ");
if (*pstart == '-')
{
if (cpu->vendor.length > 0)
ffStrbufAppend(&cpu->name, &cpu->vendor);
else
ffStrbufAppendS(&cpu->name, "Unknown");
++pstart;
continue;
}
char* pend = strchr(pstart, '\n');
if (pend != NULL)
ffStrbufAppendNS(&cpu->name, (uint32_t) (pend - pstart), pstart);
else
{
ffStrbufAppendS(&cpu->name, pstart);
break;
}
pstart = pend + 1;
if (pstart >= buffer.chars + buffer.length)
return NULL;
}
}
}
detectArmName(cpuinfo, cpu, cpuImplementer);
#endif
return NULL;
}
+1 -1
View File
@@ -123,7 +123,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
FFDisk* disk = ffListAdd(disks);
disk->bytesTotal = fs->f_blocks * fs->f_bsize;
disk->bytesTotal = (uint64_t)fs->f_blocks * fs->f_bsize;
disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize;
disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize;
disk->bytesUsed = 0; // To be filled in ./disk.c
@@ -34,7 +34,6 @@ FFDisplayResult* ffdsAppendDisplay(
display->bitDepth = 0;
display->hdrEnabled = false;
display->wcgEnabled = false;
return display;
}
@@ -64,7 +64,6 @@ typedef struct FFDisplayResult
bool primary;
uint8_t bitDepth;
bool hdrEnabled;
bool wcgEnabled;
} FFDisplayResult;
typedef struct FFDisplayServerResult
@@ -8,10 +8,11 @@
#include <CoreGraphics/CGDirectDisplay.h>
#include <CoreVideo/CVDisplayLink.h>
#ifdef MAC_OS_X_VERSION_10_15
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
#ifndef MAC_OS_X_VERSION_10_15
#import <IOKit/graphics/IOGraphicsLib.h>
extern CFDictionaryRef CoreDisplay_IODisplayCreateInfoDictionary(io_service_t framebuffer, IOOptionBits options) __attribute__((weak_import));
extern Boolean CoreDisplay_Display_IsHDRModeEnabled(CGDirectDisplayID display) __attribute__((weak_import));
#else
#include <IOKit/graphics/IOGraphicsLib.h>
#endif
static void detectDisplays(FFDisplayServerResult* ds)
@@ -37,36 +38,28 @@ static void detectDisplays(FFDisplayServerResult* ds)
{
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
if (!(time.flags & kCVTimeIsIndefinite))
refreshRate = time.timeScale / (double) time.timeValue + 0.5; //59.97...
refreshRate = time.timeScale / (double) time.timeValue; //59.97...
CVDisplayLinkRelease(link);
}
}
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = NULL;
#ifdef MAC_OS_X_VERSION_10_15
if(CoreDisplay_DisplayCreateInfoDictionary)
{
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
if(displayInfo)
{
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
}
}
displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
#else
if(CoreDisplay_IODisplayCreateInfoDictionary)
{
io_service_t servicePort = CGDisplayIOServicePort(screen);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
if(displayInfo)
{
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
}
displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
}
#endif
if(displayInfo)
{
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
}
CGSize size = CGDisplayScreenSize(screen);
@@ -86,21 +79,20 @@ static void detectDisplays(FFDisplayServerResult* ds)
);
if (display)
{
// Shitty code
uint8_t bitDepth = 0;
FF_CFTYPE_AUTO_RELEASE CFStringRef desc = CFCopyDescription(mode);
CFRange start = CFStringFind(desc, CFSTR("BitsPerSample = "), 0);
if (start.location != kCFNotFound)
// https://stackoverflow.com/a/33519316/9976392
// Also shitty, but better than parsing `CFCopyDescription(mode)`
CFDictionaryRef dict = (CFDictionaryRef) *((int64_t *)mode + 2);
if (CFGetTypeID(dict) == CFDictionaryGetTypeID())
{
for (CFIndex idx = start.location + start.length; idx < CFStringGetLength(desc); ++idx)
{
UniChar ch = CFStringGetCharacterAtIndex(desc, idx);
if (!ffCharIsDigit((char) ch))
break;
bitDepth = (uint8_t) (bitDepth * 10 + (ch - '0'));
}
int32_t bitDepth;
ffCfDictGetInt(dict, kCGDisplayBitsPerSample, &bitDepth);
display->bitDepth = (uint8_t) bitDepth;
}
if (CoreDisplay_Display_IsHDRModeEnabled)
{
display->hdrEnabled = CoreDisplay_Display_IsHDRModeEnabled(screen);
}
display->bitDepth = bitDepth;
}
CGDisplayModeRelease(mode);
}
@@ -178,7 +178,6 @@ static void detectDisplays(FFDisplayServerResult* ds)
if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS)
{
display->hdrEnabled = !!advColorInfo.advancedColorEnabled;
display->wcgEnabled = !!advColorInfo.wideColorEnforced;
display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel;
}
}
@@ -7,6 +7,43 @@
#include "common/settings.h"
#endif
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
{
const char* env = getenv("XDG_SESSION_TYPE");
if(env)
{
if(ffStrEqualsIgnCase(env, "wayland"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
else if(ffStrEqualsIgnCase(env, "x11") || ffStrEqualsIgnCase(env, "xorg"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
else if(ffStrEqualsIgnCase(env, "tty"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
else
ffStrbufSetS(&result->wmProtocolName, env);
return;
}
if(getenv("WAYLAND_DISPLAY") != NULL || getenv("WAYLAND_SOCKET") != NULL)
{
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
return;
}
if(getenv("DISPLAY") != NULL) // XWayland also set this
{
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
return;
}
env = getenv("TERM");
if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux"))
{
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
return;
}
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE)
@@ -57,8 +94,14 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
#endif
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(ds);
if (ds->wmProtocolName.length == 0)
getWMProtocolNameFromEnv(ds);
if(!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY))
{
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(ds);
}
}
bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName)
@@ -7,8 +7,7 @@
bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName);
const char* ffdsConnectWlroots(FFDisplayServerResult* result);
void ffdsConnectWayland(FFDisplayServerResult* result);
const char* ffdsConnectWayland(FFDisplayServerResult* result);
void ffdsConnectXcbRandr(FFDisplayServerResult* result);
void ffdsConnectXcb(FFDisplayServerResult* result);
@@ -122,7 +122,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
display.edidName.length
? &display.edidName
// Try ignoring `eDP-1-unknown`, where `unknown` is localized
: display.description.length && !(ffStrbufStartsWithS(&display.description, display.name.chars) && display.description.chars[display.name.length] == '-')
: display.description.length && !ffStrbufContain(&display.description, &display.name)
? &display.description
: &display.name,
display.type,
@@ -119,12 +119,6 @@ static void waylandKdeHdrListener(void *data, FF_MAYBE_UNUSED struct kde_output_
display->hdrEnabled = !!hdr_enabled;
}
static void waylandKdeWcgListener(void *data, FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2, uint32_t wcg_enabled)
{
WaylandDisplay* display = data;
display->wcgEnabled = !!wcg_enabled;
}
static struct kde_output_device_v2_listener outputListener = {
.geometry = waylandKdeGeometryListener,
.current_mode = waylandKdeCurrentModeListener,
@@ -143,7 +137,7 @@ static struct kde_output_device_v2_listener outputListener = {
.name = waylandKdeNameListener,
.high_dynamic_range = waylandKdeHdrListener,
.sdr_brightness = (void*) stubListener,
.wide_color_gamut = waylandKdeWcgListener,
.wide_color_gamut = (void*) stubListener,
.auto_rotate_policy = (void*) stubListener,
.icc_profile_path = (void*) stubListener,
.brightness_metadata = (void*) stubListener,
@@ -202,7 +196,6 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry,
if (item)
{
item->hdrEnabled = display.hdrEnabled;
item->wcgEnabled = display.wcgEnabled;
}
ffStrbufDestroy(&display.description);
@@ -22,14 +22,27 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
{
struct ucred ucred;
socklen_t len = sizeof(struct ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1 || ucred.pid <= 0)
return false;
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate();
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
ffReadFileBuffer(procPath.chars, &result->wmProcessName);
if (!ffReadFileBuffer(procPath.chars, &result->wmProcessName))
return false;
// #1135: wl-restart is a special case
const char* filename = strrchr(result->wmProcessName.chars, '/');
if (filename)
filename++;
else
filename = result->wmProcessName.chars;
if (ffStrEquals(filename, "wl-restart"))
ffStrbufSubstrAfterFirstC(&result->wmProcessName, '\0');
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
return true;
}
#else
@@ -69,27 +82,93 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u
}
}
bool detectWayland(FFDisplayServerResult* result)
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
{
WaylandDisplay* display = data;
if (display->id) return;
display->type = ffdsGetDisplayType(name);
if (!display->edidName.length)
ffdsMatchDrmConnector(name, &display->edidName);
display->id = ffWaylandGenerateIdFromName(name);
ffStrbufAppendS(&display->name, name);
}
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description)
{
WaylandDisplay* display = data;
if (display->description.length) return;
while (*description == ' ') ++description;
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)"))
ffStrbufAppendS(&display->description, description);
}
uint32_t ffWaylandHandleRotation(WaylandDisplay* display)
{
uint32_t rotation;
switch(display->transform)
{
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_90:
rotation = 90;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
case WL_OUTPUT_TRANSFORM_180:
rotation = 180;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
case WL_OUTPUT_TRANSFORM_270:
rotation = 270;
break;
default:
rotation = 0;
break;
}
switch(rotation)
{
case 90:
case 270: {
int32_t temp = display->width;
display->width = display->height;
display->height = temp;
temp = display->physicalWidth;
display->physicalWidth = display->physicalHeight;
display->physicalHeight = temp;
break;
}
default:
break;
}
return rotation;
}
const char* ffdsConnectWayland(FFDisplayServerResult* result)
{
if (getenv("XDG_RUNTIME_DIR") == NULL)
return "Wayland requires $XDG_RUNTIME_DIR being set";
FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_connect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_get_fd)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_proxy_marshal_constructor)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_disconnect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_registry_interface)
WaylandData data = {};
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false)
FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_marshal_constructor_versioned)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_add_listener)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_destroy)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_display_roundtrip)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_output_interface)
data.display = ffwl_display_connect(NULL);
if(data.display == NULL)
return false;
return "wl_display_connect returned NULL";
waylandDetectWM(ffwl_display_get_fd(data.display), result);
@@ -97,7 +176,7 @@ bool detectWayland(FFDisplayServerResult* result)
if(registry == NULL)
{
ffwl_display_disconnect(data.display);
return false;
return "wl_display_get_registry returned NULL";
}
data.result = result;
@@ -192,97 +271,15 @@ bool detectWayland(FFDisplayServerResult* result)
//We successfully connected to wayland and detected the display.
//So we can set set the session type to wayland.
//This is used as an indicator that we are running wayland by the x11 backends.
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
return true;
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
return NULL;
}
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
#else
const char* ffdsConnectWayland(FF_MAYBE_UNUSED FFDisplayServerResult* result)
{
WaylandDisplay* display = data;
if (display->id) return;
display->type = ffdsGetDisplayType(name);
if (!display->edidName.length)
ffdsMatchDrmConnector(name, &display->edidName);
display->id = ffWaylandGenerateIdFromName(name);
ffStrbufAppendS(&display->name, name);
return "Fastfetch was compiled without Wayland support";
}
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description)
{
WaylandDisplay* display = data;
if (display->description.length) return;
while (*description == ' ') ++description;
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)"))
ffStrbufAppendS(&display->description, description);
}
uint32_t ffWaylandHandleRotation(WaylandDisplay* display)
{
uint32_t rotation;
switch(display->transform)
{
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_90:
rotation = 90;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
case WL_OUTPUT_TRANSFORM_180:
rotation = 180;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
case WL_OUTPUT_TRANSFORM_270:
rotation = 270;
break;
default:
rotation = 0;
break;
}
switch(rotation)
{
case 90:
case 270: {
int32_t temp = display->width;
display->width = display->height;
display->height = temp;
temp = display->physicalWidth;
display->physicalWidth = display->physicalHeight;
display->physicalHeight = temp;
break;
}
default:
break;
}
return rotation;
}
#endif
void ffdsConnectWayland(FFDisplayServerResult* result)
{
//Wayland requires this to be set
if(getenv("XDG_RUNTIME_DIR") == NULL)
return;
#ifdef FF_HAVE_WAYLAND
if(detectWayland(result))
return;
#endif
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
//If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session.
if(xdgSessionType != NULL && !ffStrEqualsIgnCase(xdgSessionType, "wayland"))
return;
//If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY or WAYLAND_SOCKET is set.
//If not, there is no indicator for a wayland session
if(xdgSessionType == NULL && getenv("WAYLAND_DISPLAY") == NULL && getenv("WAYLAND_SOCKET") == NULL)
return;
//We are probably running a wayland compositor at this point,
//but fastfetch was compiled without the required library, or loading the library failed.
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
}
@@ -47,7 +47,6 @@ typedef struct WaylandDisplay
FFstrbuf edidName;
uint64_t id;
bool hdrEnabled;
bool wcgEnabled;
void* internal;
} WaylandDisplay;
@@ -131,7 +131,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
rotation,
display.edidName.length
? &display.edidName
: display.description.length
: display.description.length && !ffStrbufContain(&display.description, &display.name)
? &display.description
: &display.name,
display.type,
-41
View File
@@ -240,38 +240,6 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
}
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
{
//This is only called if all connection attempts to a display server failed
//We don't need to check for wayland here, as the wayland code will always set the protocol name to wayland
const char* env = getenv("XDG_SESSION_TYPE");
if(ffStrSet(env))
{
if(ffStrEqualsIgnCase(env, "x11"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
else if(ffStrEqualsIgnCase(env, "tty"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
else
ffStrbufSetS(&result->wmProtocolName, env);
return;
}
env = getenv("DISPLAY");
if(ffStrSet(env))
{
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
return;
}
env = getenv("TERM");
if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux"))
{
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
return;
}
}
static const char* getFromProcesses(FFDisplayServerResult* result)
{
@@ -396,15 +364,6 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
void ffdsDetectWMDE(FFDisplayServerResult* result)
{
//If all connections failed, use the environment variables to detect protocol name
if(result->wmProtocolName.length == 0)
getWMProtocolNameFromEnv(result);
//We don't want to detect anything in TTY
//This can't happen if a connection succeeded, so we don't need to clear wmProcessName
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
return;
const char* env = parseEnv();
if(result->wmProcessName.length > 0)
+5
View File
@@ -7,6 +7,7 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
const char* FF_GPU_VENDOR_NAME_MTHREADS = "Moore Threads";
const char* FF_GPU_VENDOR_NAME_QUALCOMM = "Qualcomm";
const char* FF_GPU_VENDOR_NAME_MTK = "MTK";
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
@@ -24,6 +25,7 @@ const char* ffGetGPUVendorString(unsigned vendorId)
case 0x1002: case 0x1022: return FF_GPU_VENDOR_NAME_AMD;
case 0x8086: case 0x8087: case 0x03e7: return FF_GPU_VENDOR_NAME_INTEL;
case 0x0955: case 0x10de: case 0x12d2: return FF_GPU_VENDOR_NAME_NVIDIA;
case 0x1ed5: return FF_GPU_VENDOR_NAME_MTHREADS;
case 0x5143: return FF_GPU_VENDOR_NAME_QUALCOMM;
case 0x14c3: return FF_GPU_VENDOR_NAME_MTK;
case 0x15ad: return FF_GPU_VENDOR_NAME_VMWARE;
@@ -56,6 +58,7 @@ const char* detectByOpenGL(FFlist* gpus)
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0};
gpu->deviceId = 0;
@@ -70,6 +73,8 @@ const char* detectByOpenGL(FFlist* gpus)
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if (ffStrbufContainS(&gpu->name, "MTT"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
}
+4 -1
View File
@@ -6,11 +6,13 @@
#define FF_GPU_CORE_COUNT_UNSET -1
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1)
#define FF_GPU_FREQUENCY_UNSET 0
#define FF_GPU_CORE_USAGE_UNSET (0/0.0)
extern const char* FF_GPU_VENDOR_NAME_APPLE;
extern const char* FF_GPU_VENDOR_NAME_AMD;
extern const char* FF_GPU_VENDOR_NAME_INTEL;
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
extern const char* FF_GPU_VENDOR_NAME_MTHREADS;
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
@@ -31,6 +33,7 @@ typedef struct FFGPUResult
FFstrbuf driver;
FFstrbuf platformApi;
double temperature;
double coreUsage;
int32_t coreCount;
uint32_t frequency; // Maximum time clock frequency in MHz
FFGPUMemory dedicated;
@@ -44,5 +47,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
const char* ffGetGPUVendorString(unsigned vendorId);
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu, FFstrbuf* coreName);
#endif
+43 -3
View File
@@ -76,8 +76,12 @@ static const char* detectFrequency(FFGPUResult* gpu)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
{
CFMutableDictionaryRef matches = IOServiceMatching(kIOAcceleratorClassName);
CFDictionaryAddValue(matches, CFSTR("IOMatchCategory"), CFSTR(kIOAcceleratorClassName));
if (IOServiceGetMatchingServices(MACH_PORT_NULL, matches, &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
}
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
@@ -103,6 +107,31 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = 0.0/0.0;
CFDictionaryRef perfStatistics = NULL;
uint64_t vramUsed = 0, vramTotal = 0;
if (ffCfDictGetDict(properties, CFSTR("PerformanceStatistics"), &perfStatistics) == NULL)
{
int64_t utilization;
if (ffCfDictGetInt64(perfStatistics, CFSTR("Device Utilization %"), &utilization) == NULL)
gpu->coreUsage = (double) utilization;
else if (ffCfDictGetInt64(perfStatistics, CFSTR("GPU Core Utilization"), &utilization) == NULL)
gpu->coreUsage = (double) utilization / 10000000.; // Nvidia?
if (ffCfDictGetInt64(perfStatistics, CFSTR("Alloc system memory"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("In use system memory"), (int64_t*) &vramUsed) != NULL)
vramTotal = 0;
}
else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramUsed) == NULL)
vramTotal += vramUsed;
else
vramTotal = 0;
}
}
ffStrbufInit(&gpu->name);
//IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs.
//Still needs testing for AMD's
@@ -123,7 +152,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->vendor);
int vendorId;
if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId))
if(ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL)
{
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
ffStrbufAppendS(&gpu->vendor, vendorStr);
@@ -136,6 +165,17 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE)
detectFrequency(gpu);
#endif
if (gpu->type == FF_GPU_TYPE_INTEGRATED)
{
gpu->shared.total = vramTotal;
gpu->shared.used = vramUsed;
}
else
{
gpu->dedicated.total = vramTotal;
gpu->dedicated.used = vramUsed;
}
}
gpu->temperature = options->temp ? detectGpuTemp(&gpu->name) : FF_GPU_TEMP_UNSET;
-11
View File
@@ -44,17 +44,6 @@ const char* ffGpuDetectMetal(FFlist* gpus)
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#endif
if (gpu->type == FF_GPU_TYPE_INTEGRATED)
{
gpu->shared.total = device.recommendedMaxWorkingSetSize;
gpu->shared.used = device.currentAllocatedSize;
}
else
{
gpu->dedicated.total = device.recommendedMaxWorkingSetSize;
gpu->dedicated.used = device.currentAllocatedSize;
}
}
return NULL;
}
+30 -3
View File
@@ -3,6 +3,7 @@
#include "common/io/io.h"
#include "common/properties.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include <dev/pci/pcireg.h>
#include <sys/pciio.h>
@@ -57,6 +58,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func;
@@ -69,11 +71,12 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
}
FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate();
if (gpu->name.length == 0)
{
if (pciids.length == 0)
loadPciIds(&pciids);
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu, &coreName);
}
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
@@ -92,10 +95,34 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.type = &gpu->type,
.frequency = &gpu->frequency,
.coreUsage = &gpu->coreUsage,
.name = options->driverSpecific ? &gpu->name : NULL,
}, "libnvidia-ml.so");
}
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
if ((coreName.chars[0] == 'D' || coreName.chars[0] == 'S') &&
coreName.chars[1] == 'G' &&
ffCharIsDigit(coreName.chars[2]))
gpu->type = FF_GPU_TYPE_DISCRETE; // DG1 / DG2 / SG1
else
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
}
}
+53
View File
@@ -40,10 +40,63 @@ typedef struct FFGpuDriverResult
double* temp;
FFGPUMemory* memory;
uint32_t* coreCount;
double* coreUsage;
FFGPUType* type;
uint32_t* frequency;
FFstrbuf* name;
} FFGpuDriverResult;
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
{
*pDetectFn = ffDetectNvidiaGpuInfo;
#ifdef _WIN32
*pDllName = "nvml.dll";
#else
*pDllName = "libnvidia-ml.so";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_MTHREADS)
{
*pDetectFn = ffDetectMthreadsGpuInfo;
#ifdef _WIN32
*pDllName = "mtml.dll";
#else
*pDllName = "libmtml.so";
#endif
}
#ifdef _WIN32
else if (vendor == FF_GPU_VENDOR_NAME_INTEL)
{
*pDetectFn = ffDetectIntelGpuInfo;
#ifdef _WIN64
*pDllName = "ControlLib.dll";
#else
*pDllName = "ControlLib32.dll";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_AMD)
{
*pDetectFn = ffDetectAmdGpuInfo;
#ifdef _WIN64
*pDllName = "amd_ags_x64.dll";
#else
*pDllName = "amd_ags_x86.dll";
#endif
}
#endif
else
{
*pDetectFn = NULL;
*pDllName = NULL;
return false;
}
return true;
}
+142 -46
View File
@@ -7,29 +7,93 @@
#include "common/properties.h"
#include "util/stringUtils.h"
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#include <inttypes.h>
#if __has_include(<drm/drm.h>)
#include <drm/drm.h>
#define FF_HAVE_DRM_H 1
#elif __has_include(<libdrm/drm.h>)
#include <libdrm/drm.h>
#define FF_HAVE_DRM_H 1
#endif
#if FF_HAVE_DRM_H
#if __aarch64__ && FF_HAVE_DRM
#include <drm.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#if __aarch64__ && __has_include(<drm/asahi_drm.h>)
#include <drm/asahi_drm.h>
#define FF_HAVE_ASAHI_DRM_H 1
#endif
// https://github.com/AsahiLinux/linux/blob/asahi/include/uapi/drm/asahi_drm.h
/* SPDX-License-Identifier: MIT */
/* Copyright (C) The Asahi Linux Contributors */
#define DRM_ASAHI_UNSTABLE_UABI_VERSION 10011
#define DRM_ASAHI_GET_PARAMS 0x00
#define DRM_ASAHI_MAX_CLUSTERS 32
struct drm_asahi_params_global
{
__u32 unstable_uabi_version;
__u32 pad0;
__u64 feat_compat;
__u64 feat_incompat;
__u32 gpu_generation;
__u32 gpu_variant;
__u32 gpu_revision;
__u32 chip_id;
__u32 num_dies;
__u32 num_clusters_total;
__u32 num_cores_per_cluster;
__u32 num_frags_per_cluster;
__u32 num_gps_per_cluster;
__u32 num_cores_total_active;
__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
__u32 vm_page_size;
__u32 pad1;
__u64 vm_user_start;
__u64 vm_user_end;
__u64 vm_usc_start;
__u64 vm_usc_end;
__u64 vm_kernel_min_size;
__u32 max_syncs_per_submission;
__u32 max_commands_per_submission;
__u32 max_commands_in_flight;
__u32 max_attachments;
__u32 timer_frequency_hz;
__u32 min_frequency_khz;
__u32 max_frequency_khz;
__u32 max_power_mw;
__u32 result_render_size;
__u32 result_compute_size;
__u32 firmware_version[4];
};
struct drm_asahi_get_params
{
/** @extensions: Pointer to the first extension struct, if any */
__u64 extensions;
/** @param: Parameter group to fetch (MBZ) */
__u32 param_group;
/** @pad: MBZ */
__u32 pad;
/** @value: User pointer to write parameter struct */
__u64 pointer;
/** @value: Size of user buffer, max size supported on return */
__u64 size;
};
enum
{
DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params),
};
#endif
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
{
uint32_t pciDirLength = pciDir->length;
@@ -45,6 +109,17 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
}
if (ffStrbufEqualS(&gpu->driver, "nvidia"))
{
if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer))
{
if (ffStrbufContainS(buffer, " Open "))
ffStrbufAppendS(&gpu->driver, " (open source)");
else
ffStrbufAppendS(&gpu->driver, " (proprietary)");
}
}
if (instance.config.general.detectVersion)
{
ffStrbufAppendS(pciDir, "/module/version");
@@ -124,14 +199,20 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
}
}
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const FFstrbuf* coreName)
{
// Works for Intel GPUs
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
if (ffStrbufStartsWithS(&gpu->name, "Intel "))
ffStrbufSubstrAfter(&gpu->name, (uint32_t) strlen("Intel "));
gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
if ((coreName->chars[0] == 'D' || coreName->chars[0] == 'S') &&
coreName->chars[1] == 'G' &&
ffCharIsDigit(coreName->chars[2]))
gpu->type = FF_GPU_TYPE_DISCRETE; // DG1 / DG2 / SG1
else
gpu->type = FF_GPU_TYPE_INTEGRATED;
if (ffStrbufEqualS(&gpu->driver, "xe"))
{
@@ -212,20 +293,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
return "Invalid PCI device path";
ffStrbufAppendS(deviceDir, "/enable");
if (ffReadFileBuffer(deviceDir->chars, buffer))
{
if (!ffStrbufStartsWithC(buffer, '1'))
return "GPU disabled";
}
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
@@ -255,6 +329,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
}
FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate();
if (gpu->name.length == 0)
{
static FFstrbuf pciids;
@@ -263,7 +338,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
ffStrbufInit(&pciids);
loadPciIds(&pciids);
}
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu, &coreName);
}
pciDetectDriver(gpu, deviceDir, buffer, drmKey);
@@ -276,14 +351,16 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
pciDetectIntelSpecific(gpu, deviceDir, buffer);
pciDetectIntelSpecific(gpu, deviceDir, buffer, &coreName);
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
else
{
if (options->temp || options->driverSpecific)
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* soName;
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
detectFn(&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.pciBusId = {
.domain = pciDomain,
@@ -295,23 +372,35 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
}, "libnvidia-ml.so");
.name = options->driverSpecific ? &gpu->name : NULL,
}, soName);
}
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
gpu->type = FF_GPU_TYPE_DISCRETE;
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
{
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
gpu->type = FF_GPU_TYPE_DISCRETE;
}
}
}
return NULL;
}
#if __aarch64__
FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey)
{
uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t");
@@ -326,13 +415,14 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F
ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_INTEGRATED;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
pciDetectDriver(gpu, drmDir, buffer, drmKey);
#if FF_HAVE_ASAHI_DRM_H
#if FF_HAVE_DRM
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
@@ -345,15 +435,21 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F
.size = sizeof(paramsGlobal),
}) >= 0)
{
gpu->coreCount = (int) paramsGlobal.num_cores_total_active;
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
// FIXME: They will introduce ABI breaking changes. Always check the latest version
// https://www.reddit.com/r/AsahiLinux/comments/1ei2qiv/comment/lgm0v5s/
if (paramsGlobal.unstable_uabi_version == DRM_ASAHI_UNSTABLE_UABI_VERSION)
{
gpu->coreCount = (int) paramsGlobal.num_cores_total_active;
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
}
}
}
#endif
return NULL;
}
#endif
static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
@@ -436,14 +532,14 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
#ifdef FF_HAVE_DIRECTX_HEADERS
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
if (ffGPUDetectByDirectX(options, gpus) == NULL)
return NULL;
#endif
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
{
#ifdef FF_HAVE_DIRECTX_HEADERS
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
if (ffGPUDetectByDirectX(options, gpus) == NULL)
return NULL;
#endif
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0)
return NULL;
}
+198
View File
@@ -0,0 +1,198 @@
#include "gpu_driver_specific.h"
#include "common/library.h"
#include "mtml.h"
struct FFMtmlData
{
FF_LIBRARY_SYMBOL(mtmlDeviceGetBrand)
FF_LIBRARY_SYMBOL(mtmlDeviceGetIndex)
FF_LIBRARY_SYMBOL(mtmlDeviceGetName)
FF_LIBRARY_SYMBOL(mtmlDeviceGetPciInfo)
FF_LIBRARY_SYMBOL(mtmlDeviceGetUUID)
FF_LIBRARY_SYMBOL(mtmlDeviceInitGpu)
FF_LIBRARY_SYMBOL(mtmlDeviceInitMemory)
FF_LIBRARY_SYMBOL(mtmlGpuGetMaxClock)
FF_LIBRARY_SYMBOL(mtmlGpuGetTemperature)
FF_LIBRARY_SYMBOL(mtmlGpuGetUtilization)
FF_LIBRARY_SYMBOL(mtmlLibraryCountDevice)
FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByIndex)
FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByPciSbdf)
FF_LIBRARY_SYMBOL(mtmlLibraryInitSystem)
FF_LIBRARY_SYMBOL(mtmlMemoryGetTotal)
FF_LIBRARY_SYMBOL(mtmlMemoryGetUsed)
FF_LIBRARY_SYMBOL(mtmlMemoryGetUtilization)
FF_LIBRARY_SYMBOL(mtmlLibraryShutDown)
bool inited;
MtmlLibrary *lib;
MtmlSystem *sys;
} mtmlData;
static void shutdownMtml()
{
mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
}
const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDriverResult result, const char *soName)
{
#ifndef FF_DISABLE_DLOPEN
if (!mtmlData.inited)
{
mtmlData.inited = true;
FF_LIBRARY_LOAD(libmtml, NULL, "dlopen mtml failed", soName, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryInit)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetBrand)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetIndex)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetName)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetPciInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetUUID)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitGpu)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitMemory)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetMaxClock)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetTemperature)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetUtilization)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryCountDevice)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByIndex)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByPciSbdf)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitSystem)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetTotal)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUsed)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUtilization)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryShutDown)
if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS)
{
mtmlData.ffmtmlLibraryInitSystem = NULL;
return "mtmlLibraryInit failed";
}
if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS)
{
mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
mtmlData.ffmtmlLibraryInitSystem = NULL;
return "mtmlLibraryInitSystem failed";
}
atexit(shutdownMtml);
libmtml = NULL; // don't close mtml
}
if (mtmlData.ffmtmlLibraryInitSystem == NULL)
return "loading mtml library failed";
MtmlDevice *device = NULL;
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
char pciBusIdStr[32];
snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
MtmlReturn ret = mtmlData.ffmtmlLibraryInitDeviceByPciSbdf(mtmlData.lib, pciBusIdStr, &device);
if (ret != MTML_SUCCESS)
return "mtmlLibraryInitDeviceByPciSbdf() failed";
}
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
{
uint32_t count;
if (mtmlData.ffmtmlLibraryCountDevice(mtmlData.lib, &count) != MTML_SUCCESS)
return "mtmlLibraryCountDevice() failed";
for (uint32_t i = 0; i < count; i++, device = NULL)
{
if (mtmlData.ffmtmlLibraryInitDeviceByIndex(mtmlData.lib, i, &device) != MTML_SUCCESS)
continue;
MtmlPciInfo pciInfo;
if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) != MTML_SUCCESS)
continue;
if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
pciInfo.pciSubsystemId != cond->pciDeviceId.subSystemId)
continue;
break;
}
if (!device)
return "Device not found";
}
else
{
return "Unknown condition type";
}
MtmlBrandType brand;
if (mtmlData.ffmtmlDeviceGetBrand(device, &brand) == MTML_SUCCESS)
{
switch (brand)
{
case MTML_BRAND_MTT:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
}
}
if (result.temp)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
uint32_t value;
if (mtmlData.ffmtmlGpuGetTemperature(gpu, &value) == MTML_SUCCESS)
*result.temp = value;
}
}
if (result.memory)
{
MtmlMemory *mem = NULL;
if (mtmlData.ffmtmlDeviceInitMemory(device, &mem) == MTML_SUCCESS)
{
unsigned long long total;
if (mtmlData.ffmtmlMemoryGetTotal(mem, &total) == MTML_SUCCESS)
result.memory->total = total;
unsigned long long used;
if (mtmlData.ffmtmlMemoryGetUsed(mem, &used) == MTML_SUCCESS)
result.memory->used = used;
}
}
if (result.frequency)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
uint32_t clockMHz;
if (mtmlData.ffmtmlGpuGetMaxClock(gpu, &clockMHz) == MTML_SUCCESS)
*result.frequency = clockMHz;
}
}
if (result.coreUsage)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
unsigned int utilization;
if (mtmlData.ffmtmlGpuGetUtilization(gpu, &utilization) == MTML_SUCCESS)
*result.coreUsage = utilization;
}
}
if (result.name)
{
char name[MTML_DEVICE_NAME_BUFFER_SIZE];
if (mtmlData.ffmtmlDeviceGetName(device, name, sizeof(name)) == MTML_SUCCESS)
ffStrbufSetS(result.name, name);
}
return NULL;
#else
FF_UNUSED(cond, result, soName);
return "dlopen is disabled";
#endif
}
+18
View File
@@ -12,7 +12,9 @@ struct FFNvmlData {
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates)
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
FF_LIBRARY_SYMBOL(nvmlDeviceGetName)
bool inited;
} nvmlData;
@@ -35,7 +37,9 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetName)
if (ffnvmlInit_v2() != NVML_SUCCESS)
{
@@ -124,6 +128,20 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
if (result.frequency)
nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency);
if (result.coreUsage)
{
nvmlUtilization_t utilization;
if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &utilization) == NVML_SUCCESS)
*result.coreUsage = utilization.gpu;
}
if (result.name)
{
char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE];
if (nvmlData.ffnvmlDeviceGetName(device, name, sizeof(name)) == NVML_SUCCESS)
ffStrbufSetS(result.name, name);
}
return NULL;
#else
+13 -6
View File
@@ -1,6 +1,6 @@
#include "gpu.h"
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu, FFstrbuf* coreName)
{
if (content->length)
{
@@ -44,13 +44,20 @@ void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint
if (!end)
end = content->chars + content->length;
char* openingBracket = memchr(start, '[', (uint32_t) (end - start));
if (openingBracket)
char* closingBracket = end - 1;
if (*closingBracket == ']')
{
openingBracket++;
char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket));
if (closingBracket)
char* openingBracket = memrchr(start, '[', (size_t) (closingBracket - start));
if (openingBracket)
{
openingBracket++;
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
if (coreName)
{
ffStrbufSetNS(coreName, (uint32_t) (openingBracket - start) - 1, start);
ffStrbufTrimRight(coreName, ' ');
}
}
}
if (!gpu->name.length)
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
+2 -1
View File
@@ -59,6 +59,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = 0;
@@ -75,7 +76,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
{
if (pciids.length == 0)
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu, NULL);
}
}
+92 -91
View File
@@ -3,99 +3,60 @@
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
#include <inttypes.h>
#define INITGUID
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>
static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
{
return ffStrbufEqual(&gpu->name, name);
if(*hdev)
SetupDiDestroyDeviceInfoList(*hdev);
}
static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
{
*pDetectFn = ffDetectNvidiaGpuInfo;
*pDllName = "nvml.dll";
}
else if (vendor == FF_GPU_VENDOR_NAME_INTEL)
{
*pDetectFn = ffDetectIntelGpuInfo;
#ifdef _WIN64
*pDllName = "ControlLib.dll";
#else
*pDllName = "ControlLib32.dll";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_AMD)
{
*pDetectFn = ffDetectAmdGpuInfo;
#ifdef _WIN64
*pDllName = "amd_ags_x64.dll";
#else
*pDllName = "amd_ags_x86.dll";
#endif
}
else
{
*pDetectFn = NULL;
*pDllName = NULL;
return false;
}
#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}"
enum { FF_GUID_STRLEN = sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1 };
return true;
}
wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR;
const uint32_t regDirectxKeyPrefixLength = (uint32_t) __builtin_strlen("SOFTWARE\\Microsoft\\DirectX\\");
wchar_t regDriverKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\" FF_EMPTY_GUID_STR L"\\0000";
const uint32_t regDriverKeyPrefixLength = (uint32_t) __builtin_strlen("SYSTEM\\CurrentControlSet\\Control\\Class\\");
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) };
wchar_t regDirectxKey[MAX_PATH] = L"SOFTWARE\\Microsoft\\DirectX\\{";
const uint32_t regDirectxKeyPrefixLength = (uint32_t) wcslen(regDirectxKey);
wchar_t regControlVideoKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{";
const uint32_t regControlVideoKeyPrefixLength = (uint32_t) wcslen(regControlVideoKey);
const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regControlVideoKeyPrefixLength;
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i)
if(hdev == INVALID_HANDLE_VALUE)
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed";
SP_DEVINFO_DATA did = { .cbSize = sizeof(did) };
for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev)
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue;
const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey);
if (__builtin_expect(deviceKeyLength == 100, true))
{
if (wmemcmp(&displayDevice.DeviceKey[deviceKeyLength - 4], L"0000", 4) != 0) continue;
}
else
{
// DeviceKey can be empty. See #484
FF_STRBUF_AUTO_DESTROY gpuName = ffStrbufCreateWS(displayDevice.DeviceString);
if (ffListContains(gpus, &gpuName, (void*) isGpuNameEqual)) continue;
}
// See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html
// displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1"
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
ffStrbufInitWS(&gpu->name, displayDevice.DeviceString);
ffStrbufInit(&gpu->vendor);
ffStrbufInit(&gpu->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitStatic(&gpu->platformApi, "Direct3D");
ffStrbufInitStatic(&gpu->platformApi, "SetupAPI");
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{')
wchar_t buffer[256];
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
ffStrbufSetWS(&gpu->name, buffer);
FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
if (!hVideoIdKey) continue;
DWORD bufferLen = sizeof(buffer);
if (RegGetValueW(hVideoIdKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, buffer, &bufferLen) == ERROR_SUCCESS &&
bufferLen == (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
{
wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}\\0000"));
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue;
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}"));
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, buffer, FF_GUID_STRLEN);
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
{
@@ -118,24 +79,43 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8);
else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel)
ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8);
}
else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL))
{
uint32_t vmem = 0;
if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL))
gpu->dedicated.total = vmem;
gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
if (gpu->vendor.length == 0)
uint64_t driverVersion = 0;
if(ffRegReadUint64(hDirectxKey, L"DriverVersion", &driverVersion, NULL) && driverVersion)
{
ffStrbufSetF(&gpu->driver, "%u.%u.%u.%u",
(unsigned) (driverVersion >> 48) & 0xFFFF,
(unsigned) (driverVersion >> 32) & 0xFFFF,
(unsigned) (driverVersion >> 16) & 0xFFFF,
(unsigned) (driverVersion >> 0) & 0xFFFF
);
}
uint32_t vendorId = 0;
if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId)
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
}
}
if (gpu->vendor.length == 0)
{
bufferLen = sizeof(buffer);
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DRIVER, NULL, (PBYTE) buffer, sizeof(buffer), &bufferLen) && bufferLen == (FF_GUID_STRLEN + strlen("\\0000") + 1) * 2)
{
ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL);
if (ffStrbufContainS(&gpu->vendor, "Intel"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if (ffStrbufContainS(&gpu->vendor, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
wmemcpy(regDriverKey + regDriverKeyPrefixLength, buffer, FF_GUID_STRLEN + strlen("\\0000"));
FF_HKEY_AUTO_DESTROY hRegDriverKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDriverKey, &hRegDriverKey, NULL))
{
if (ffRegReadStrbuf(hRegDriverKey, L"ProviderName", &gpu->vendor, NULL))
{
if (ffStrbufContainS(&gpu->vendor, "Intel"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if (ffStrbufContainS(&gpu->vendor, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
}
}
}
}
@@ -144,23 +124,44 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific))
{
if (vendorId && deviceId && subSystemId)
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) buffer, sizeof(buffer), NULL))
{
swscanf(buffer, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId));
}
uint32_t pciBus, pciAddr;
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) &&
SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL))
{
uint32_t pciDev = (pciAddr >> 16) & 0xFFFF;
uint32_t pciFunc = pciAddr & 0xFFFF;
detectFn(
&(FFGpuDriverCondition) {
.type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | FF_GPU_DRIVER_CONDITION_TYPE_LUID,
.type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID
| (gpu->deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0)
| (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0),
.pciDeviceId = {
.deviceId = deviceId,
.vendorId = vendorId,
.subSystemId = subSystemId,
.revId = revId,
},
.pciBusId = {
.domain = 0,
.bus = pciBus,
.device = pciDev,
.func = pciFunc,
},
.luid = gpu->deviceId,
},
(FFGpuDriverResult) {
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
},
+5 -1
View File
@@ -28,7 +28,7 @@ private:
extern "C"
const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
FF_LIBRARY_LOAD(libdxcore, nullptr, "dlopen libdxcore.so failed. Make sure WSLg is enabled", "/usr/lib/wsl/lib/libdxcore" FF_LIBRARY_EXTENSION, 4)
FF_LIBRARY_LOAD(libdxcore, nullptr, "dlopen libdxcore.so failed", "/usr/lib/wsl/lib/libdxcore" FF_LIBRARY_EXTENSION, 4)
// DXCoreCreateAdapterFactory is a reloaded function, so we can't use FF_LIBRARY_LOAD_SYMBOL_MESSAGE here
typedef HRESULT (*DXCoreCreateAdapterFactory_t)(REFIID riid, void** ppvFactory);
@@ -71,8 +71,10 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitS(&gpu->name, desc);
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->deviceId = 0;
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
ffStrbufInit(&gpu->driver);
@@ -119,8 +121,10 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = options->driverSpecific ? &gpu->name : NULL,
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
}
}
+116
View File
@@ -0,0 +1,116 @@
#pragma once
// DISCLAIMER:
// THIS FILE IS CREATED FROM SCRATCH, BY READING THE OFFICIAL MTML API
// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT.
#define MTML_API __attribute__((visibility("default")))
#define MTML_DEVICE_PCI_SBDF_BUFFER_SIZE 32
#define MTML_DEVICE_NAME_BUFFER_SIZE 32
#define MTML_DEVICE_UUID_BUFFER_SIZE 48
/**
* Return values for MTML API calls.
*/
typedef enum
{
MTML_SUCCESS = 0,
} MtmlReturn;
/**
* The brand of the device.
*/
typedef enum
{
MTML_BRAND_MTT = 0, //!< MTT series.
MTML_BRAND_UNKNOWN, //!< An unknown brand.
// Keep this on the last line.
MTML_BRAND_COUNT //!< The number of brands.
} MtmlBrandType;
typedef struct MtmlLibrary MtmlLibrary;
typedef struct MtmlSystem MtmlSystem;
typedef struct MtmlDevice MtmlDevice;
typedef struct MtmlGpu MtmlGpu;
typedef struct MtmlMemory MtmlMemory;
/**
* PCI information about a device.
*/
typedef struct
{
char sbdf[MTML_DEVICE_PCI_SBDF_BUFFER_SIZE]; //!< The tuple segment:bus:device.function PCI identifier (&amp; NULL terminator).
unsigned int segment; //!< The PCI segment group(domain) on which the device's bus resides, 0 to 0xffffffff.
unsigned int bus; //!< The bus on which the device resides, 0 to 0xff.
unsigned int device; //!< The device ID on the bus, 0 to 31.
unsigned int pciDeviceId; //!< The combined 16-bit device ID and 16-bit vendor ID.
unsigned int pciSubsystemId; //!< The 32-bit sub system device ID.
unsigned int busWidth; //!< @deprecated This value set to zero.
float pciMaxSpeed; //!< The maximum link speed (transfer rate per lane) of the device. The unit is GT/s.
float pciCurSpeed; //!< The current link speed (transfer rate per lane) of the device. The unit is GT/s.
unsigned int pciMaxWidth; //!< The maximum link width of the device.
unsigned int pciCurWidth; //!< The current link width of the device.
unsigned int pciMaxGen; //!< The maximum supported generation of the device.
unsigned int pciCurGen; //!< The current generation of the device.
int rsvd[6]; //!< Reserved for future extension.
} MtmlPciInfo;
// Retrieves the brand of a device.
MtmlReturn MTML_API mtmlDeviceGetBrand(const MtmlDevice *dev, MtmlBrandType *type);
// Retrieves the index associated with the specified device.
MtmlReturn MTML_API mtmlDeviceGetIndex(const MtmlDevice *dev, unsigned int *index);
// Retrieves the name of a device.
MtmlReturn MTML_API mtmlDeviceGetName(const MtmlDevice *dev, char *name, unsigned int length);
// Retrieves the PCI attributes of a device.
MtmlReturn MTML_API mtmlDeviceGetPciInfo(const MtmlDevice *dev, MtmlPciInfo *pci);
/**
* Retrieves the UUID of a specified device. The UUID is a hexadecimal string in the
* form of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where each 'x' is an ASCII character that represents a hexadecimal
* digit. The UUID is globally unique for every single device thus can be used to identify different devices
* physically.
*/
MtmlReturn MTML_API mtmlDeviceGetUUID(const MtmlDevice *dev, char *uuid, unsigned int length);
// Initializes a GPU opaque object to represent a specific graphic core on the target device that is designated by its index.
MtmlReturn MTML_API mtmlDeviceInitGpu(const MtmlDevice *dev, MtmlGpu **gpu);
// Initializes a memory opaque object to represent the memory on the target device.
MtmlReturn MTML_API mtmlDeviceInitMemory(const MtmlDevice *dev, MtmlMemory **mem);
// Retrieves the maximum supported clock speed for the device's graphic core.
MtmlReturn MTML_API mtmlGpuGetMaxClock(const MtmlGpu *gpu, unsigned int *clockMhz);
// Retrieves the current temperature readings for the device's graphic core, in degrees Celsius.
MtmlReturn MTML_API mtmlGpuGetTemperature(const MtmlGpu *gpu, unsigned int *temp);
// Retrieves the current utilization rate for the device's graphic core.
MtmlReturn MTML_API mtmlGpuGetUtilization(const MtmlGpu *gpu, unsigned int *utilization);
// Retrieves the number of devices that can be accessed by the library opaque object.
MtmlReturn MTML_API mtmlLibraryCountDevice(const MtmlLibrary *lib, unsigned int *count);
/**
* Initializes a device opaque object to represent a device that is designated by its index.
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
*/
MtmlReturn MTML_API mtmlLibraryInit(MtmlLibrary **lib);
/**
* Initializes a device opaque object to represent a device that is designated by its index.
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
*/
MtmlReturn MTML_API mtmlLibraryInitDeviceByIndex(const MtmlLibrary *lib, unsigned int index, MtmlDevice **dev);
/**
* Initializes a device opaque object to represent a device that is designated by its PCI Sbdf.
* The PCI Sbdf format like 00000000:3a:00.0 refer to \ref MtmlPciInfo::sbdf.
*/
MtmlReturn MTML_API mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary *lib, const char *pciSbdf, MtmlDevice **dev);
// Initializes a MtmlSystem opaque pointer that is bound to a library opaque object.
MtmlReturn MTML_API mtmlLibraryInitSystem(const MtmlLibrary *lib, MtmlSystem **sys);
/**
* Shuts down the library opaque object that is previously initialized by \ref mtmlLibraryInit() and releases its resources.
* The \a lib pointer cannot be used anymore after this function returns.
*/
MtmlReturn MTML_API mtmlLibraryShutDown(MtmlLibrary *lib);
// Retrieves the amount of total memory available on the device, in bytes.
MtmlReturn MTML_API mtmlMemoryGetTotal(const MtmlMemory *mem, unsigned long long *total);
// Retrieves the amount of used memory on the device, in bytes.
MtmlReturn MTML_API mtmlMemoryGetUsed(const MtmlMemory *mem, unsigned long long *used);
// Retrieves the current memory utilization rate for the device.
MtmlReturn MTML_API mtmlMemoryGetUtilization(const MtmlMemory *mem, unsigned int *utilization);
+15
View File
@@ -7,6 +7,7 @@
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceStructs.html
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE 32
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE 16
#define NVML_DEVICE_NAME_V2_BUFFER_SIZE 96
typedef enum { NVML_SUCCESS = 0 } nvmlReturn_t;
typedef struct nvmlDevice_t* nvmlDevice_t;
@@ -94,6 +95,16 @@ typedef enum {
NVML_BRAND_COUNT,
} nvmlBrandType_t;
// https://docs.nvidia.com/deploy/nvml-api/structnvmlUtilization__t.html#structnvmlUtilization__t
// Utilization information for a device.
typedef struct
{
// Percent of time over the past second during which one or more kernels was executing on the GPU
unsigned int gpu;
// Percent of time over the past second during which global (device) memory was being read or written
unsigned int memory;
} nvmlUtilization_t;
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlInitializationAndCleanup.html#group__nvmlInitializationAndCleanup
// Initialize NVML, but don't initialize any GPUs yet
nvmlReturn_t nvmlInit_v2(void);
@@ -119,3 +130,7 @@ extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int*
extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int* clock);
// Retrieves the brand of this device
extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type);
// Retrieves the current utilization rates for the device
extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization);
// Retrieves the name of this device.
extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length);
+33 -11
View File
@@ -1,7 +1,22 @@
#include "initsystem.h"
#include "common/processing.h"
#include "util/linux/elf.h"
#include <unistd.h>
FF_MAYBE_UNUSED static bool elfExtractStringsCallBack(const char* str, uint32_t len, void* data)
{
if (len > strlen("systemd 0.0 running in ") && memcmp(str, "systemd ", strlen("systemd ")) == 0)
{
const char* pend = memmem(str + strlen("systemd "), len - strlen("systemd "), " running in ", strlen(" running in "));
if (pend)
{
ffStrbufSetNS((FFstrbuf*) data, (uint32_t) (pend - str) - (uint32_t) strlen("systemd "), str + strlen("systemd "));
return false;
}
}
return true;
}
const char* ffDetectInitSystem(FFInitSystemResult* result)
{
const char* error = ffProcessGetBasicInfoLinux((int) result->pid, &result->name, NULL, NULL);
@@ -31,24 +46,30 @@ const char* ffDetectInitSystem(FFInitSystemResult* result)
if (instance.config.general.detectVersion)
{
#if __linux__ && !__ANDROID__
if (ffStrbufEqualS(&result->name, "systemd"))
{
if (ffProcessAppendStdOut(&result->version, (char* const[]) {
ffStrbufEndsWithS(&result->exe, "/systemd") ? result->exe.chars : "systemctl", // use exe path in case users have another systemd installed
"--version",
NULL,
}) == NULL && result->version.length)
ffElfExtractStrings(result->exe.chars, elfExtractStringsCallBack, &result->version);
if (result->version.length == 0)
{
uint32_t iStart = ffStrbufFirstIndexC(&result->version, '(');
if (iStart < result->version.length)
if (ffProcessAppendStdOut(&result->version, (char* const[]) {
ffStrbufEndsWithS(&result->exe, "/systemd") ? result->exe.chars : "systemctl", // use exe path in case users have another systemd installed
"--version",
NULL,
}) == NULL && result->version.length)
{
uint32_t iEnd = ffStrbufNextIndexC(&result->version, iStart + 1, ')');
ffStrbufSubstrBefore(&result->version, iEnd);
ffStrbufSubstrAfter(&result->version, iStart);
uint32_t iStart = ffStrbufFirstIndexC(&result->version, '(');
if (iStart < result->version.length)
{
uint32_t iEnd = ffStrbufNextIndexC(&result->version, iStart + 1, ')');
ffStrbufSubstrBefore(&result->version, iEnd);
ffStrbufSubstrAfter(&result->version, iStart);
}
}
}
}
else if (ffStrbufEqualS(&result->name, "launchd"))
#elif __APPLE__
if (ffStrbufEqualS(&result->name, "launchd"))
{
if (ffProcessAppendStdOut(&result->version, (char* const[]) {
"/bin/launchctl",
@@ -66,6 +87,7 @@ const char* ffDetectInitSystem(FFInitSystemResult* result)
}
}
}
#endif
}
return NULL;
+4
View File
@@ -4,6 +4,10 @@
void ffDetectLocale(FFstrbuf* result)
{
ffStrbufAppendS(result, getenv("LC_ALL"));
if(result->length > 0)
return;
ffStrbufAppendS(result, getenv("LC_MESSAGES"));
if(result->length > 0)
return;
+14 -6
View File
@@ -5,12 +5,18 @@
#include <string.h>
#define FF_DBUS_MPRIS_PREFIX "org.mpris.MediaPlayer2."
#define FF_DBUS_TIMEOUT_MILLISECONDS 35
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/library.h"
#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \
{ \
if(!(dbus)->lib->ffdbus_message_iter_next(iterator)) \
break; \
continue; \
}
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
{
DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata");
@@ -61,13 +67,13 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
data->lib->ffdbus_message_iter_next(&dictIterator);
if(ffStrEquals(key, "xesam:title"))
ffDBusGetValue(data, &dictIterator, &result->song);
ffDBusGetString(data, &dictIterator, &result->song);
else if(ffStrEquals(key, "xesam:album"))
ffDBusGetValue(data, &dictIterator, &result->album);
ffDBusGetString(data, &dictIterator, &result->album);
else if(ffStrEquals(key, "xesam:artist"))
ffDBusGetValue(data, &dictIterator, &result->artist);
ffDBusGetString(data, &dictIterator, &result->artist);
else if(ffStrEquals(key, "xesam:url"))
ffDBusGetValue(data, &dictIterator, &result->url);
ffDBusGetString(data, &dictIterator, &result->url);
if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0)
break;
@@ -85,6 +91,8 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
return false;
}
ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "PlaybackStatus", &result->status);
//Set short bus name
ffStrbufAppendS(&result->playerId, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1);
@@ -119,7 +127,7 @@ static void getBestBus(FFDBusData* data, FFMediaResult* result)
getBusProperties(data, FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result)
) return;
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames");
DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL);
if(reply == NULL)
return;
+5 -6
View File
@@ -7,11 +7,10 @@
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#ifdef MAC_OS_X_VERSION_10_15
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
#ifndef MAC_OS_X_VERSION_10_15
#import <IOKit/graphics/IOGraphicsLib.h>
extern CFDictionaryRef CoreDisplay_IODisplayCreateInfoDictionary(io_service_t framebuffer, IOOptionBits options) __attribute__((weak_import));
#else
#include <IOKit/graphics/IOGraphicsLib.h>
#endif
static bool detectHdrSupportWithNSScreen(FFDisplayResult* display)
@@ -57,7 +56,7 @@ const char* ffDetectMonitor(FFlist* results)
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
#else
io_service_t servicePort = CGDisplayIOServicePort((CGDirectDisplayID) display->id);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
#endif
if(!displayInfo) continue;
@@ -67,7 +66,7 @@ const char* ffDetectMonitor(FFlist* results)
uint8_t edidData[128] = {};
uint32_t edidLength = 0;
if (ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength) == NULL)
if (ffCfDictGetData(displayInfo, CFSTR(kIODisplayEDIDKey), 0, sizeof(edidData), edidData, &edidLength) == NULL)
{
uint32_t width, height;
ffEdidGetPhysicalResolution(edidData, &width, &height);
+1
View File
@@ -81,6 +81,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = (size_t) deviceID;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS)
{
@@ -23,6 +23,12 @@ static inline const char* getVendorString(unsigned vendorId)
void FFPhysicalMemoryUpdateVendorString(FFPhysicalMemoryResult* device)
{
if (ffStrbufEqualS(&device->vendor, "Unknown"))
{
ffStrbufClear(&device->vendor);
return;
}
char vendorIdStr[5];
if (ffStrbufStartsWithS(&device->vendor, "0x"))
{
@@ -75,10 +75,10 @@ const char* ffDetectPhysicalMemory(FFlist* result)
if (!data)
return "Memory device is not found in SMBIOS data";
for (; data->Header.Type == FF_SMBIOS_TYPE_MEMORY_DEVICE;
data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header))
for (; data->Header.Type < FF_SMBIOS_TYPE_END_OF_TABLE;
data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header))
{
if (data->Size == 0) continue;
if (data->Header.Type != FF_SMBIOS_TYPE_MEMORY_DEVICE || data->Size == 0) continue;
const char* strings = (const char*) data + data->Header.Length;
+13 -17
View File
@@ -8,6 +8,7 @@
#include "detection/displayserver/displayserver.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include "util/linux/elf.h"
static const char* getSystemMonospaceFont(void)
{
@@ -286,6 +287,13 @@ static void detectXterm(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
static bool elfExtractStringsCallBack(const char* str, uint32_t len, void* userData)
{
if (!ffStrContains(str, "size=")) return true;
ffStrbufSetNS((FFstrbuf*) userData, len, str);
return false;
}
static void detectSt(FFTerminalFontResult* terminalFont, const FFTerminalResult* terminal)
{
FF_STRBUF_AUTO_DESTROY size = ffStrbufCreateF("/proc/%u/cmdline", terminal->pid);
@@ -306,30 +314,18 @@ static void detectSt(FFTerminalFontResult* terminalFont, const FFTerminalResult*
else
{
ffStrbufClear(&font);
if (ffProcessAppendStdOut(&font, (char* const[]) {
"strings",
terminal->exePath.chars,
NULL,
}) != NULL || font.length == 0)
const char* error = ffElfExtractStrings(terminal->exePath.chars, elfExtractStringsCallBack, &font);
if (error)
{
ffStrbufAppendS(&terminalFont->error, "Failed to run `strings st`");
ffStrbufAppendS(&terminalFont->error, error);
return;
}
// Search font config string in st binary
uint32_t middleIndex = ffStrbufFirstIndexS(&font, "size=");
if (middleIndex == font.length)
if (font.length == 0)
{
ffStrbufAppendS(&terminalFont->error, "No font config found in st binary");
return;
}
uint32_t startIndex = ffStrbufPreviousIndexC(&font, middleIndex, '\n');
if (startIndex == font.length) startIndex = 0;
uint32_t endIndex = ffStrbufNextIndexC(&font, middleIndex, '\n');
ffStrbufSubstrBefore(&font, endIndex);
ffStrbufSubstrAfter(&font, startIndex);
}
// JetBrainsMono Nerd Font Mono:pixelsize=12:antialias=true:autohint=true
+29 -24
View File
@@ -200,28 +200,6 @@ static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
NULL
}) == NULL;
}
#else
static bool getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
{
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreate();
ffStrbufAppendS(&command, "printf \"%s\" \"$");
ffStrbufAppendTransformS(&command, exeName, toupper);
ffStrbufAppendS(&command, "_VERSION\"");
if (ffProcessAppendStdOut(version, (char* const[]) {
"env",
"-i",
exe->chars,
"-c",
command.chars,
NULL
}) != NULL)
return false;
ffStrbufSubstrBeforeFirstC(version, '(');
ffStrbufRemoveStrings(version, 2, (const char*[]) { "-release", "release" });
return true;
}
#endif
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
@@ -261,9 +239,9 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
return getShellVersionWinPowerShell(exe, version);
return getFileVersion(exe->chars, version);
#else
return getShellVersionGeneric(exe, exeName, version);
#endif
return false;
}
FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version)
@@ -507,6 +485,33 @@ static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version)
#ifndef _WIN32
static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
{
#if defined(__linux__) || defined(__FreeBSD__)
char buffer[1024] = {};
if (
#ifdef __linux__
ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) ||
ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer)
#else
ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer)
#endif
)
{
// Starts from version 0.17.0
// https://github.com/kovidgoyal/kitty/blob/master/kitty/constants.py#L25
const char* p = memmem(buffer, sizeof(buffer) - 1, "version: Version = Version(", strlen("version: Version = Version("));
if (p)
{
p += strlen("version: Version = Version(");
int major, minor, patch;
if (sscanf(p, "%d,%d,%d", &major, &minor, &patch) == 3)
{
ffStrbufSetF(version, "%d.%d.%d", major, minor, patch);
return true;
}
}
}
#endif
char versionHex[64];
// https://github.com/fastfetch-cli/fastfetch/discussions/1030#discussioncomment-9845233
if (ffGetTerminalResponse(
@@ -42,7 +42,6 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "sudo") ||
ffStrbufEqualS(&result->processName, "su") ||
ffStrbufEqualS(&result->processName, "strace") ||
ffStrbufEqualS(&result->processName, "sshd") ||
ffStrbufEqualS(&result->processName, "gdb") ||
ffStrbufEqualS(&result->processName, "lldb") ||
ffStrbufEqualS(&result->processName, "lldb-mi") ||
@@ -51,7 +50,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "perf") ||
ffStrbufEqualS(&result->processName, "guake-wrapped") ||
ffStrbufEqualS(&result->processName, "time") ||
ffStrbufEqualS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend
ffStrbufContainS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend
ffStrbufEqualS(&result->processName, "clifm") || //https://github.com/leo-arch/clifm/issues/289
ffStrbufEqualS(&result->processName, "valgrind") ||
ffStrbufEqualS(&result->processName, "fastfetch") || //994
@@ -102,7 +101,6 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "oil.ovm") ||
ffStrbufEqualS(&result->processName, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
ffStrbufEqualS(&result->processName, "login") ||
ffStrbufEqualS(&result->processName, "sshd") ||
ffStrbufEqualS(&result->processName, "clifm") || // https://github.com/leo-arch/clifm/issues/289
ffStrbufEqualS(&result->processName, "chezmoi") || // #762
#ifdef __linux__
@@ -314,6 +312,8 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
ffStrbufInitStatic(&result->prettyName, "tmux");
else if(ffStrbufStartsWithS(&result->processName, "screen-"))
ffStrbufInitStatic(&result->prettyName, "screen");
else if(ffStrbufEqualS(&result->processName, "sshd") || ffStrbufStartsWithS(&result->processName, "sshd-"))
ffStrbufInitCopy(&result->prettyName, &result->tty);
#if defined(__ANDROID__)
@@ -53,7 +53,6 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
if(
ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "su") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables
@@ -155,7 +154,7 @@ static bool getTerminalFromEnv(FFTerminalResult* result)
}
//SSH
if(getenv("SSH_CONNECTION") != NULL)
if(getenv("SSH_TTY") != NULL)
term = getenv("SSH_TTY");
//Windows Terminal
@@ -315,6 +314,11 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
ffStrbufSetStatic(&result->prettyName, "Windows Explorer");
else if(ffStrbufEqualS(&result->prettyName, "wezterm-gui"))
ffStrbufSetStatic(&result->prettyName, "WezTerm");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || ffStrbufStartsWithIgnCaseS(&result->prettyName, "sshd-"))
{
const char* tty = getenv("SSH_TTY");
if (tty) ffStrbufSetS(&result->prettyName, tty);
}
}
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
+1 -1
View File
@@ -1,7 +1,7 @@
#include "fastfetch.h"
#include "users.h"
#if __has_include(<utmpx.h>)
#if FF_HAVE_UTMPX
#include <utmpx.h>
#else
//for Android compatibility
+1
View File
@@ -44,6 +44,7 @@ FFVersionResult ffVersionResult = {
.architecture = FF_ARCHITECTURE,
.version = FASTFETCH_PROJECT_VERSION,
.versionTweak = FASTFETCH_PROJECT_VERSION_TWEAK,
.versionGit = FASTFETCH_PROJECT_VERSION_GIT,
.cmakeBuiltType = FASTFETCH_PROJECT_CMAKE_BUILD_TYPE,
.compileTime = __DATE__ ", " __TIME__,
.compiler =
+1
View File
@@ -9,6 +9,7 @@ typedef struct FFVersionResult
const char* architecture;
const char* version;
const char* versionTweak;
const char* versionGit;
const char* cmakeBuiltType;
const char* compileTime;
const char* compiler;
+1
View File
@@ -237,6 +237,7 @@ static const char* detectVulkan(FFVulkanResult* result)
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
next:
continue;
+1 -1
View File
@@ -12,7 +12,7 @@ struct FFWifiConnection
{
FFstrbuf status;
FFstrbuf ssid;
FFstrbuf macAddress;
FFstrbuf bssid;
FFstrbuf protocol;
FFstrbuf security;
double signalQuality; // Percentage
+4 -4
View File
@@ -37,7 +37,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -53,12 +53,12 @@ const char* ffDetectWifi(FFlist* result)
if(!ffStrbufEqualS(&item->inf.status, "COMPLETED"))
return NULL;
double rssi = yyjson_get_num(yyjson_obj_get(root, "rssi"));
item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2;
ffStrbufAppendS(&item->inf.description, yyjson_get_str(yyjson_obj_get(root, "ip")));
ffStrbufAppendS(&item->conn.macAddress, yyjson_get_str(yyjson_obj_get(root, "bssid")));
ffStrbufAppendS(&item->conn.bssid, yyjson_get_str(yyjson_obj_get(root, "bssid")));
ffStrbufAppendS(&item->conn.ssid, yyjson_get_str(yyjson_obj_get(root, "ssid")));
return NULL;
+14 -18
View File
@@ -6,21 +6,17 @@
struct Apple80211; // https://code.google.com/archive/p/iphone-wireless/wikis/Apple80211.wiki
// 0 is successful; < 0 is failure
int Apple80211Open(struct Apple80211 **handle) __attribute__((weak_import));
int Apple80211BindToInterface(struct Apple80211 *handle, CFStringRef interface) __attribute__((weak_import));
int Apple80211GetInfoCopy(struct Apple80211 *handle, CFDictionaryRef *info) __attribute__((weak_import));
int Apple80211Close(struct Apple80211 *handle) __attribute__((weak_import));
static NSDictionary* getWifiInfoByApple80211(NSString* ifName)
@interface CWInterface()
@property (readonly) struct Apple80211* device;
@end
static NSDictionary* getWifiInfoByApple80211(CWInterface* inf)
{
if (!Apple80211Open || !Apple80211BindToInterface || !Apple80211GetInfoCopy || !Apple80211Close) return NULL;
struct Apple80211* handle = NULL;
if (Apple80211Open(&handle) < 0) return NULL;
if (Apple80211BindToInterface(handle, (__bridge CFStringRef)ifName) < 0) return NULL;
CFDictionaryRef result;
if (Apple80211GetInfoCopy(handle, &result) < 0) return NULL;
Apple80211Close(handle);
if (!Apple80211GetInfoCopy) return NULL;
CFDictionaryRef result = NULL;
if (Apple80211GetInfoCopy(inf.device, &result) < 0) return NULL;
return CFBridgingRelease(result);
}
@@ -37,7 +33,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -57,15 +53,15 @@ const char* ffDetectWifi(FFlist* result)
if (inf.ssid) // https://developer.apple.com/forums/thread/732431
ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String);
else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName)))
else if (apple || (apple = getWifiInfoByApple80211(inf)))
ffStrbufAppendS(&item->conn.ssid, [[apple valueForKey:@"SSID_STR"] UTF8String]);
else
ffStrbufSetStatic(&item->conn.ssid, "<unknown ssid>"); // https://developer.apple.com/forums/thread/732431
if (inf.bssid)
ffStrbufAppendS(&item->conn.macAddress, inf.bssid.UTF8String);
else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName)))
ffStrbufAppendS(&item->conn.macAddress, [[apple valueForKey:@"BSSID"] UTF8String]);
ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String);
else if (apple || (apple = getWifiInfoByApple80211(inf)))
ffStrbufAppendS(&item->conn.bssid, [[apple valueForKey:@"BSSID"] UTF8String]);
switch(inf.activePHYMode)
{
@@ -152,7 +148,7 @@ const char* ffDetectWifi(FFlist* result)
break;
case kCWSecurityUnknown:
// Sonoma...
if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName)))
if (apple || (apple = getWifiInfoByApple80211(inf)))
{
NSDictionary* authType = [apple valueForKey:@"AUTH_TYPE"];
if (authType)
+2 -2
View File
@@ -28,7 +28,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -42,7 +42,7 @@ const char* ffDetectWifi(FFlist* result)
if (ibssid < item->conn.ssid.length)
{
ibssid += (uint32_t) strlen(" bssid ");
ffStrbufSetS(&item->conn.macAddress, item->conn.ssid.chars + ibssid);
ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + ibssid);
}
ffStrbufSubstrBeforeFirstC(&item->conn.ssid, ' ');
+227 -262
View File
@@ -1,184 +1,96 @@
#include "wifi.h"
#include "util/stringUtils.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef FF_HAVE_LIBNM
#include "common/dbus.h"
#include "common/io/io.h"
#include "common/processing.h"
#include "common/properties.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include <glib.h>
#define NM_NO_INCLUDE_EXTRA_HEADERS 1
#include <NetworkManager.h>
#include <net/if.h>
//https://developer-old.gnome.org/libnm/stable/libnm-nm-dbus-interface.html
#ifndef NM_VERSION_1_26
#define NM_802_11_AP_SEC_KEY_MGMT_OWE 0x00000800
#define NM_802_11_AP_SEC_KEY_MGMT_OWE_TM 0x00001000
#endif
#ifdef FF_HAVE_DBUS
// https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApFlags
typedef enum {
NM_802_11_AP_FLAGS_NONE = 0x00000000,
NM_802_11_AP_FLAGS_PRIVACY = 0x00000001,
NM_802_11_AP_FLAGS_WPS = 0x00000002,
NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004,
NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008,
} NM80211ApFlags;
static const char* detectWifiWithLibnm(FFlist* result)
// https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApSecurityFlags
typedef enum {
NM_802_11_AP_SEC_NONE = 0x00000000,
NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001,
NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002,
NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004,
NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008,
NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010,
NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020,
NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040,
NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080,
NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100,
NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200,
NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400,
NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800,
NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000,
NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000,
} NM80211ApSecurityFlags;
static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer)
{
FF_LIBRARY_LOAD(nm, &instance.config.library.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_new);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_get_devices);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_iface);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_state);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_type);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_active_access_point);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_ssid);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_utils_ssid_to_utf8);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_bssid);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_strength);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_max_bitrate);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_flags);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_wpa_flags);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_rsn_flags);
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_type_check_instance_is_a);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_size);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_data);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_free);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_object_unref);
NMClient* client = ffnm_client_new(NULL, NULL);
if(!client)
return "Could not create NMClient";
/* Get all devices managed by NetworkManager */
const GPtrArray* devices = ffnm_client_get_devices(client);
/* Go through the array and process Wi-Fi devices */
for (guint i = 0; i < devices->len; i++)
{
NMDevice *device = g_ptr_array_index(devices, i);
if (!({
GTypeInstance *inst = (GTypeInstance*) device;
GType type = ffnm_device_wifi_get_type();
gboolean return_value;
if (!inst)
return_value = FALSE;
else if (inst->g_class && inst->g_class->g_type == type)
return_value = TRUE;
else
return_value = ffg_type_check_instance_is_a (inst, type);
return_value;
}) //NM_IS_DEVICE_WIFI(device)
)
continue;
DBusMessage* device = ffDBusGetMethodReply(&dbus, "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", "GetDeviceByIpIface", item->inf.description.chars);
if(!device)
return "Failed to call GetDeviceByIpIface";
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
ffStrbufInit(&item->inf.description);
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
ffStrbufAppendS(&item->inf.description, ffnm_device_get_iface(device));
NMDeviceState state = ffnm_device_get_state(device);
switch(state)
ffStrbufClear(buffer);
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(device, &rootIter) || !ffDBusGetString(&dbus, &rootIter, buffer))
{
case NM_DEVICE_STATE_UNKNOWN:
ffStrbufSetStatic(&item->inf.status, "Unknown");
break;
case NM_DEVICE_STATE_UNMANAGED:
ffStrbufSetStatic(&item->inf.status, "Unmanaged");
break;
case NM_DEVICE_STATE_UNAVAILABLE:
ffStrbufSetStatic(&item->inf.status, "Unavailable");
break;
case NM_DEVICE_STATE_DISCONNECTED:
ffStrbufSetStatic(&item->inf.status, "Disconnected");
break;
case NM_DEVICE_STATE_PREPARE:
ffStrbufSetStatic(&item->inf.status, "Prepare");
break;
case NM_DEVICE_STATE_CONFIG:
ffStrbufSetStatic(&item->inf.status, "Config");
break;
case NM_DEVICE_STATE_NEED_AUTH:
ffStrbufSetStatic(&item->inf.status, "Need auth");
break;
case NM_DEVICE_STATE_IP_CONFIG:
ffStrbufSetStatic(&item->inf.status, "IP config");
break;
case NM_DEVICE_STATE_IP_CHECK:
ffStrbufSetStatic(&item->inf.status, "IP check");
break;
case NM_DEVICE_STATE_SECONDARIES:
ffStrbufSetStatic(&item->inf.status, "Secondaries");
break;
case NM_DEVICE_STATE_ACTIVATED:
ffStrbufSetStatic(&item->inf.status, "Activated");
break;
case NM_DEVICE_STATE_DEACTIVATING:
ffStrbufSetStatic(&item->inf.status, "Deactivating");
break;
case NM_DEVICE_STATE_FAILED:
ffStrbufSetStatic(&item->inf.status, "Failed");
break;
dbus.lib->ffdbus_message_unref(device);
return "Failed to get device path";
}
if(state != NM_DEVICE_STATE_ACTIVATED)
continue;
dbus.lib->ffdbus_message_unref(device);
}
NMAccessPoint* ap = ffnm_device_wifi_get_active_access_point((NMDeviceWifi *) device);
if (!ap)
continue;
if (item->conn.txRate != item->conn.txRate)
{
uint32_t bitrate;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", buffer->chars, "org.freedesktop.NetworkManager.Device.Wireless", "Bitrate", &bitrate))
item->conn.txRate = bitrate / 1000.;
}
ffStrbufSetStatic(&item->conn.status, "Connected");
FF_STRBUF_AUTO_DESTROY apPath = ffStrbufCreate();
if (!ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", buffer->chars, "org.freedesktop.NetworkManager.Device.Wireless", "ActiveAccessPoint", &apPath))
return "Failed to get active access point path";
GBytes* activeSsid = ffnm_access_point_get_ssid(ap);
if (activeSsid)
{
char* ssid = ffnm_utils_ssid_to_utf8(ffg_bytes_get_data(activeSsid, NULL), ffg_bytes_get_size(activeSsid));
ffStrbufAppendS(&item->conn.ssid, ssid);
ffg_free(ssid);
}
if (!item->conn.status.length)
ffStrbufSetStatic(&item->conn.status, "connected");
ffStrbufAppendS(&item->conn.macAddress, ffnm_access_point_get_bssid(ap));
item->conn.signalQuality = ffnm_access_point_get_strength(ap);
item->conn.rxRate = ffnm_access_point_get_max_bitrate(ap);
if (!item->conn.ssid.length)
ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Ssid", &item->conn.ssid);
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
if(!ffProcessAppendStdOut(&output, (char* const[]){
"iw",
"dev",
item->inf.description.chars,
"link",
NULL
}))
{
if(ffParsePropLines(output.chars, "rx bitrate: ", &item->conn.protocol))
{
sscanf(item->conn.protocol.chars, "%lf", &item->conn.rxRate);
}
if(ffParsePropLines(output.chars, "tx bitrate: ", &item->conn.protocol))
{
if(ffStrbufContainS(&item->conn.protocol, " HE-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else if(ffStrbufContainS(&item->conn.protocol, " VHT-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if(ffStrbufContainS(&item->conn.protocol, " MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
else
ffStrbufClear(&item->conn.protocol);
if (!item->conn.bssid.length)
ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "HwAddress", &item->conn.bssid);
sscanf(item->conn.protocol.chars, "%lf", &item->conn.txRate);
}
}
NM80211ApFlags flags = ffnm_access_point_get_flags(ap);
NM80211ApSecurityFlags wpaFlags = ffnm_access_point_get_wpa_flags(ap);
NM80211ApSecurityFlags rsnFlags = ffnm_access_point_get_rsn_flags(ap);
if (item->conn.signalQuality != item->conn.signalQuality)
{
uint32_t strengthPercent;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Strength", &strengthPercent))
item->conn.signalQuality = strengthPercent;
}
NM80211ApFlags flags;
NM80211ApSecurityFlags wpaFlags, rsnFlags;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Flags", &flags) &&
ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "WpaFlags", &wpaFlags) &&
ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars , "org.freedesktop.NetworkManager.AccessPoint", "RsnFlags", &rsnFlags))
{
if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE)
&& (rsnFlags == NM_802_11_AP_SEC_NONE))
ffStrbufAppendS(&item->conn.security, "WEP/");
@@ -205,36 +117,165 @@ static const char* detectWifiWithLibnm(FFlist* result)
ffStrbufTrimRight(&item->conn.security, '/');
}
ffg_object_unref(client);
return NULL;
}
#endif // FF_HAVE_DBUS
static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer)
{
const char* error = NULL;
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
if((error = ffProcessAppendStdOut(&output, (char* const[]){
"iw",
"dev",
item->inf.description.chars,
"link",
NULL
})))
return error;
if(output.length == 0)
return "iw command execution failed";
if(!ffParsePropLines(output.chars, "Connected to ", &item->conn.bssid))
{
ffStrbufAppendS(&item->conn.status, "disconnected");
return NULL;
}
ffStrbufAppendS(&item->conn.status, "connected");
ffStrbufSubstrBeforeFirstC(&item->conn.bssid, ' ');
ffStrbufUpperCase(&item->conn.bssid);
ffParsePropLines(output.chars, "SSID: ", &item->conn.ssid);
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "signal: ", buffer))
{
int level = (int) ffStrbufToSInt(buffer, INT_MAX);
if (level != INT_MAX)
item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2;
}
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "rx bitrate: ", buffer))
item->conn.rxRate = ffStrbufToDouble(buffer);
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "tx bitrate: ", buffer))
{
item->conn.txRate = ffStrbufToDouble(buffer);
if(ffStrbufContainS(buffer, " HE-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else if(ffStrbufContainS(buffer, " VHT-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if(ffStrbufContainS(buffer, " MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
}
return NULL;
}
#endif
#if __has_include(<linux/wireless.h>)
#define FF_DETECT_WIFI_WITH_IOCTLS
#include "common/io/io.h"
#include <net/if.h>
#if FF_HAVE_LINUX_WIRELESS
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/wireless.h> //TODO: Don't depend on kernel headers
#include <linux/wireless.h>
static const char* detectWifiWithIoctls(FFlist* result)
static const char* detectWifiWithIoctls(FFWifiResult* item)
{
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if(sock < 0)
return "socket() failed";
struct iwreq iwr;
strncpy(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ);
ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE);
iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars;
iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1;
iwr.u.essid.flags = 0;
if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0)
{
ffStrbufSetStatic(&item->conn.status, "connected");
ffStrbufRecalculateLength(&item->conn.ssid);
}
if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11"))
{
if(ffStrStartsWithIgnCase(iwr.u.name, "IEEE "))
ffStrbufSetS(&item->conn.protocol, iwr.u.name + strlen("IEEE "));
else
ffStrbufSetS(&item->conn.protocol, iwr.u.name);
}
if(ioctl(sock, SIOCGIWAP, &iwr) >= 0)
{
for(int i = 0; i < 6; ++i)
ffStrbufAppendF(&item->conn.bssid, "%.2X:", (uint8_t) iwr.u.ap_addr.sa_data[i]);
ffStrbufTrimRight(&item->conn.bssid, '-');
}
if(ioctl(sock, SIOCGIWRATE, &iwr) >= 0)
item->conn.txRate = iwr.u.bitrate.value / 1000000.;
struct iw_statistics stats;
iwr.u.data.pointer = &stats;
iwr.u.data.length = sizeof(stats);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWSTATS, &iwr) >= 0)
{
int8_t level = (int8_t) stats.qual.level; // https://stackoverflow.com/questions/18079771/wireless-h-how-do-i-print-out-the-signal-level
item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2;
}
//FIXME: doesn't work
struct iw_encode_ext iwe;
iwr.u.data.pointer = &iwe;
iwr.u.data.length = sizeof(iwe);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0)
{
switch(iwe.alg)
{
case IW_ENCODE_ALG_WEP:
ffStrbufAppendS(&item->conn.security, "WEP");
break;
case IW_ENCODE_ALG_TKIP:
ffStrbufAppendS(&item->conn.security, "TKIP");
break;
case IW_ENCODE_ALG_CCMP:
ffStrbufAppendS(&item->conn.security, "CCMP");
break;
case IW_ENCODE_ALG_PMK:
ffStrbufAppendS(&item->conn.security, "PMK");
break;
case IW_ENCODE_ALG_AES_CMAC:
ffStrbufAppendS(&item->conn.security, "CMAC");
break;
default:
ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe.alg);
break;
}
}
return NULL;
}
#endif // FF_HAVE_LINUX_WIRELESS
const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result)
{
struct if_nameindex* infs = if_nameindex();
if(!infs)
return "if_nameindex() failed";
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
{
ffStrbufSetF(&path, "/sys/class/net/%s/phy80211", i->if_name);
if(!ffPathExists(path.chars, FF_PATHTYPE_DIRECTORY))
ffStrbufSetF(&buffer, "/sys/class/net/%s/phy80211", i->if_name);
if(!ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY))
continue;
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
@@ -242,109 +283,33 @@ static const char* detectWifiWithIoctls(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name);
if (!ffAppendFileBuffer(path.chars, &item->inf.status))
ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name);
if (!ffAppendFileBuffer(buffer.chars, &item->inf.status))
continue;
ffStrbufTrimRightSpace(&item->inf.status);
if (!ffStrbufEqualS(&item->inf.status, "up"))
continue;
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if(sock < 0)
continue;
struct iwreq iwr;
strncpy(iwr.ifr_name, i->if_name, IFNAMSIZ);
ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE);
iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars;
iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1;
iwr.u.essid.flags = 0;
if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0)
ffStrbufRecalculateLength(&item->conn.ssid);
if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11"))
if (detectWifiWithIw(item, &buffer) != NULL)
{
if(ffStrStartsWithIgnCase(iwr.u.name, "IEEE "))
ffStrbufSetS(&item->conn.protocol, iwr.u.name + strlen("IEEE "));
else
ffStrbufSetS(&item->conn.protocol, iwr.u.name);
#ifdef FF_HAVE_LINUX_WIRELESS
detectWifiWithIoctls(item);
#endif
}
if(ioctl(sock, SIOCGIWAP, &iwr) >= 0)
{
for(int i = 0; i < 6; ++i)
ffStrbufAppendF(&item->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]);
ffStrbufTrimRight(&item->conn.macAddress, '-');
}
struct iw_statistics stats;
iwr.u.data.pointer = &stats;
iwr.u.data.length = sizeof(stats);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWSTATS, &iwr) >= 0)
{
int8_t level = (int8_t) stats.qual.level; // https://stackoverflow.com/questions/18079771/wireless-h-how-do-i-print-out-the-signal-level
item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2;
}
//FIXME: doesn't work
struct iw_encode_ext iwe;
iwr.u.data.pointer = &iwe;
iwr.u.data.length = sizeof(iwe);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0)
{
struct iw_encode_ext* iwe = iwr.u.data.pointer;
switch(iwe->alg)
{
case IW_ENCODE_ALG_WEP:
ffStrbufAppendS(&item->conn.security, "WEP");
break;
case IW_ENCODE_ALG_TKIP:
ffStrbufAppendS(&item->conn.security, "TKIP");
break;
case IW_ENCODE_ALG_CCMP:
ffStrbufAppendS(&item->conn.security, "CCMP");
break;
case IW_ENCODE_ALG_PMK:
ffStrbufAppendS(&item->conn.security, "PMK");
break;
case IW_ENCODE_ALG_AES_CMAC:
ffStrbufAppendS(&item->conn.security, "CMAC");
break;
default:
ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe->alg);
break;
}
}
#ifdef FF_HAVE_DBUS
detectWifiWithNm(item, &buffer);
#endif
}
if_freenameindex(infs);
return NULL;
}
#endif
const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result)
{
#ifdef FF_HAVE_LIBNM
detectWifiWithLibnm(result);
if(result->length) // NetworkManager not enabled? #811
return NULL;
#endif
#ifdef FF_DETECT_WIFI_WITH_IOCTLS
return detectWifiWithIoctls(result);
#endif
return "linux/wireless.h not found during compilation";
}
+3 -3
View File
@@ -76,7 +76,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -107,8 +107,8 @@ const char* ffDetectWifi(FFlist* result)
(const char *)connInfo->wlanAssociationAttributes.dot11Ssid.ucSSID);
for (size_t i = 0; i < sizeof(connInfo->wlanAssociationAttributes.dot11Bssid); i++)
ffStrbufAppendF(&item->conn.macAddress, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]);
ffStrbufTrimRight(&item->conn.macAddress, '-');
ffStrbufAppendF(&item->conn.bssid, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]);
ffStrbufTrimRight(&item->conn.bssid, '-');
switch (connInfo->wlanAssociationAttributes.dot11PhyType)
{
+1
View File
@@ -8,6 +8,7 @@
#define FASTFETCH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define FASTFETCH_PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define FASTFETCH_PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define FASTFETCH_PROJECT_VERSION_GIT "@PROJECT_VERSION_GIT@"
#define FASTFETCH_PROJECT_VERSION_TWEAK "@PROJECT_VERSION_TWEAK@"
#define FASTFETCH_PROJECT_VERSION_TWEAK_NUM @PROJECT_VERSION_TWEAK_NUM@
#define FASTFETCH_PROJECT_CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@"
+1 -1
View File
@@ -13,4 +13,4 @@ ${c1} ///////${c3}\\\\\\\\\\//
/\\\/${c1}\\/
/\\\\//
//////
/// ${c3}\\\\\
/// ${c3}\\\\\
+1 -1
View File
@@ -18,4 +18,4 @@ oOO OOo
oO OOo
oOO OOo
oOO OOo
ooo OOO OOO ooo
ooo OOO OOO ooo
+1 -1
View File
@@ -12,4 +12,4 @@ ${c1}g@@@@M" ${c2}"VP`${c3}.L! ${c4}<@JJJJ`
${c3}.@FJJJF`${c4},@LFFFF`
${c3}_@FFFFF ${c4}VLLLP`
${c3}J@@LL@" ${c4}`"
${c3}V@@"
${c3}V@@"
+1 -1
View File
@@ -3,4 +3,4 @@ ${c1} /\\ /\\
/${c2}// ${c1}\\ \\
/${c2}// ${c1}\\ \\
${c2}// ${c1}\\ \\
\\
\\
+1 -1
View File
@@ -17,4 +17,4 @@
@~:~~: ~:~~:~:(zltlltlO a,wwwwww
8~~:~~:~~~~:~~~~_1ltltu ,www
5~~:~~:~~:~~:~~:~~~_1ltq N,,
g~:~~:~~~:~~:~~:~:~~~~1q N,
g~:~~:~~~:~~:~~:~:~~~~1q N,
+1 -1
View File
@@ -19,4 +19,4 @@
#####$2##%:$3######$2:############$1##
##$2+##*$3########$2############$1
$2###$3#########$2##########$1
$3########$2######
$3########$2######
+1 -1
View File
@@ -16,4 +16,4 @@ dMMMMMMMMMMMMMMMMh yMMMMMMMMMMMMMMMMd
dMMMMMMMMMMMMMMMMh yMMMMMMMMMMMMMMMMd
.:+ydNMMMMMMMMMMMh yMMMMMMMMMMMNdy+:.
`.:+shNMMMMMh yMMMMMNhs+:``
`-+shy shs+:`
`-+shy shs+:`
+1 -1
View File
@@ -7,4 +7,4 @@
~~~ /
~~._. _/
_/ _/
_/m/'
_/m/'

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