mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
174 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 823f2ef028 | |||
| 11cfdba5cb | |||
| 5b78b2e897 | |||
| 773b8db337 | |||
| d15d4c621c | |||
| 788cad3cbe | |||
| f6ccbf7711 | |||
| e6fb545d1d | |||
| ce7ecd3863 | |||
| c8d85e09d7 | |||
| 34bc662065 | |||
| a54cbee79a | |||
| df873a19e1 | |||
| b5695b50c2 | |||
| f22b8ede02 | |||
| 893b3a6bff | |||
| e199a2fb79 | |||
| b4aac9d7d7 | |||
| cf9bd0f373 | |||
| 17deaf963e | |||
| e66a83a4cf | |||
| 96905012a4 | |||
| 591dba8829 | |||
| d10dd2095a | |||
| 22e25d0c78 | |||
| 1c8375908c | |||
| 099a390f2f | |||
| dd2d343630 | |||
| 543eed9a53 | |||
| 4860bc35d6 | |||
| 8559ab2dcd | |||
| 811485661f | |||
| 31ead528f1 | |||
| 8641442c3f | |||
| 418902512d | |||
| fbfe2b2d1a | |||
| f71c4f6d5a | |||
| b46d9d8b8e | |||
| 9d27106964 | |||
| bbb873c27b | |||
| da50a48dd5 | |||
| c8e4de9831 | |||
| e0d733f030 | |||
| ff8e0e72d2 | |||
| 63971fd245 | |||
| 6b6827b915 | |||
| 7447a95299 | |||
| bfdcab5b57 | |||
| 01c202bd93 | |||
| 0c2953ac66 | |||
| c0774b89d6 | |||
| 030f34d405 | |||
| cedc93fe7b | |||
| e155767289 | |||
| 4e41223b81 | |||
| 2ee4d7daac | |||
| a6a0a03b44 | |||
| 4b3241a286 | |||
| d37bf7252d | |||
| dd66626165 | |||
| fe7e684e85 | |||
| 2281caaff8 | |||
| 96c838d3f3 | |||
| c6e1677369 | |||
| ea18d93a40 | |||
| f6e1e5c96b | |||
| 0b85fc74eb | |||
| 946eb0eacd | |||
| a11ec589f0 | |||
| a89955b080 | |||
| df4350666a | |||
| 55b1603b83 | |||
| fb1c727641 | |||
| 87d964c7ca | |||
| bdb0a9262c | |||
| e42dfe63c3 | |||
| e8932895e8 | |||
| 4091d33c56 | |||
| 5df2a751ea | |||
| 65b9f0005b | |||
| a3e4b4fe22 | |||
| 0749704400 | |||
| 9977cb688d | |||
| 8c26e776c2 | |||
| e174eddef1 | |||
| f866c90687 | |||
| a61a956b84 | |||
| ef73c4a97d | |||
| 79c02ebf7c | |||
| 1394a0ae2e | |||
| e8ebae7ee9 | |||
| 3fae29ba8f | |||
| a9373fb4e4 | |||
| 2e2cf64452 | |||
| 7c3835bd9f | |||
| 945fd3a402 | |||
| 53d2dbd420 | |||
| eaa4721b36 | |||
| f695ae9116 | |||
| b0270f36f9 | |||
| fe5b07e0d0 | |||
| 8396f000e1 | |||
| 1361e8cd18 | |||
| b3ac696312 | |||
| 2205712bc0 | |||
| f1741c66bf | |||
| 3247aabd74 | |||
| 312d4cc518 | |||
| b24877af0b | |||
| 1de97fa3ed | |||
| 6ca65b9166 | |||
| b2cc5c4f04 | |||
| f683351fe3 | |||
| d81cd50f64 | |||
| 1101d2e90e | |||
| 8284d73cc9 | |||
| 6b0db6fa74 | |||
| 3a61b31e0a | |||
| 493cf8ff6c | |||
| e6cf7fdb9f | |||
| 831d2a05ce | |||
| d0b72c5457 | |||
| 0c82a84266 | |||
| d501c8b41a | |||
| 0354fd5d9d | |||
| a856350416 | |||
| 4efe12c0d2 | |||
| 1a66bc4ec0 | |||
| d96d794d1f | |||
| 45659854d2 | |||
| b111626fe9 | |||
| dccbdba242 | |||
| 884fd097c6 | |||
| 08dea9fe21 | |||
| 98fc793386 | |||
| 121e9b911e | |||
| b9fe2fb4dd | |||
| 812a13c871 | |||
| dcbfae7f72 | |||
| 65883766a0 | |||
| 104cb43158 | |||
| 114cc753d9 | |||
| d68c4cef13 | |||
| c549a5cab8 | |||
| cbf8fdf3fc | |||
| 1e8b9aa461 | |||
| 5d32eba1a6 | |||
| 2ce7c8c60d | |||
| 7eaaed6024 | |||
| bd5012edc8 | |||
| cf0d1cf294 | |||
| a070519721 | |||
| fa0007ac6f | |||
| ced67e81a5 | |||
| 88a7468489 | |||
| ec8391f6c6 | |||
| 4371e719ae | |||
| bbbb493cdf | |||
| 6cb565e379 | |||
| 2bb988a7f8 | |||
| 0929b940c8 | |||
| c14ba32b82 | |||
| 7a75615d9e | |||
| 96c58148f6 | |||
| 2c7cd6df98 | |||
| db1fbe0a30 | |||
| a102f0505c | |||
| 8a3af14d22 | |||
| ce648e9e44 | |||
| 2cc94ee095 | |||
| 16dd9fb213 | |||
| 873285b083 | |||
| ce43f06863 | |||
| 3c92e7013d |
+1
-1
@@ -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
@@ -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
@@ -1 +1 @@
|
||||
github: [LinusDierheimer, CarterLi]
|
||||
github: [CarterLi, LinusDierheimer]
|
||||
|
||||
@@ -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.
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
+112
-1
@@ -1,3 +1,114 @@
|
||||
# 2.22.0
|
||||
|
||||
Features:
|
||||
* Small performance improvements (Terminal, Editor)
|
||||
* Improve arm32 and loongarch support (CPU, Linux)
|
||||
* Ignore the parent process if env `$FFTS_IGNORE_PARENT` is set to `1` (Shell)
|
||||
* Add code name of Apple M4 (CPU, Linux)
|
||||
* Add ethernet speed rate detection support (LocalIP)
|
||||
* Add zsh completion script
|
||||
* Add Linglong package manager detection support (Packages, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Fix building on macOS 10.14
|
||||
* Fix tmux in linux TTY (Colors)
|
||||
* Fix hang in WSL when custom format is used (Disk, Linux)
|
||||
* Fix `/proc/loadavg` parsing (Loadavg, Linux)
|
||||
* Disable use of `LC_NUMERIC` locale settings to fix parsing of decimal numbers
|
||||
* Fix possible segfault (DiskIO, Linux)
|
||||
* Honor `preciseRefreshRate` in custom format (Display)
|
||||
|
||||
Logos:
|
||||
* Add Lingmo OS
|
||||
* Add Sleeper OS
|
||||
|
||||
# 2.21.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix bad Intel Arc GPU name detection, which was supposed to be fixed in the last version but the change was reverted accidentally (#1177, GPU, Linux)
|
||||
* Fix arm32 CPU name detection no longer work. Regression of 2.21.2 (CPU, Linux)
|
||||
|
||||
# 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 +117,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
|
||||
|
||||
+89
-33
@@ -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.22.0
|
||||
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 ANDROID" 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
|
||||
@@ -399,6 +401,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/util/base64.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
src/util/path.c
|
||||
src/util/platform/FFPlatform.c
|
||||
src/util/smbiosHelper.c
|
||||
)
|
||||
@@ -421,6 +424,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 +482,7 @@ if(LINUX)
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
@@ -488,6 +493,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
|
||||
@@ -538,8 +544,9 @@ elseif(ANDROID)
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(BSD)
|
||||
elseif(FreeBSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
@@ -550,6 +557,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 +623,7 @@ elseif(BSD)
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
@@ -626,6 +635,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
|
||||
@@ -679,6 +689,7 @@ elseif(APPLE)
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_apple.c
|
||||
)
|
||||
elseif(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
@@ -689,6 +700,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
|
||||
@@ -744,6 +756,7 @@ elseif(WIN32)
|
||||
src/util/windows/unicode.c
|
||||
src/util/windows/wmi.cpp
|
||||
src/util/platform/FFPlatform_windows.c
|
||||
src/util/binary_windows.c
|
||||
)
|
||||
elseif(SunOS)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
@@ -763,6 +776,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 +833,7 @@ elseif(SunOS)
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -828,14 +843,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 +903,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 +1071,6 @@ ff_lib_enable(OPENCL
|
||||
"OpenCL"
|
||||
"OpenCL"
|
||||
)
|
||||
ff_lib_enable(LIBNM
|
||||
"libnm"
|
||||
"libnm"
|
||||
)
|
||||
ff_lib_enable(FREETYPE
|
||||
"freetype2"
|
||||
"FreeType2"
|
||||
@@ -1072,6 +1083,10 @@ ff_lib_enable(DDCUTIL
|
||||
"ddcutil"
|
||||
"Ddcutil"
|
||||
)
|
||||
ff_lib_enable(ELF
|
||||
"libelf"
|
||||
"libelf"
|
||||
)
|
||||
ff_lib_enable(DIRECTX_HEADERS
|
||||
"DirectX-Headers"
|
||||
"DirectX-Headers"
|
||||
@@ -1124,8 +1139,9 @@ elseif(WIN32)
|
||||
PRIVATE "setupapi"
|
||||
PRIVATE "hid"
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "imagehlp"
|
||||
)
|
||||
elseif(BSD)
|
||||
elseif(FreeBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "usbhid"
|
||||
@@ -1178,7 +1194,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()
|
||||
|
||||
######################
|
||||
@@ -1287,6 +1337,12 @@ install(
|
||||
RENAME "${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.zsh"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/zsh/site-functions"
|
||||
RENAME "_${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.fish"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/fish/vendor_completions.d"
|
||||
|
||||
@@ -30,17 +30,23 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
|
||||
Some distros packaged an outdated fastfetch version. Older version receive no support, so please try always to use the latest version.
|
||||
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
|
||||
* Debian: `sudo apt install fastfetch` (for Debian 13 or newer)
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
* Arch Linux: `sudo pacman -S fastfetch`
|
||||
* Fedora: `sudo dnf install fastfetch`
|
||||
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
|
||||
* Arch Linux: `pacman -S fastfetch`
|
||||
* Fedora: `dnf install fastfetch`
|
||||
* Gentoo: `emerge --ask app-misc/fastfetch`
|
||||
* Alpine: `apk add --upgrade fastfetch`
|
||||
* NixOS: `nix-shell -p fastfetch`
|
||||
* openSUSE: `sudo zypper install fastfetch`
|
||||
* ALT Linux: `sudo apt-get install fastfetch`
|
||||
* openSUSE: `zypper install fastfetch`
|
||||
* ALT Linux: `apt-get install fastfetch`
|
||||
* Exherbo: `cave resolve --execute app-misc/fastfetch`
|
||||
* GNU Guix: `guix install fastfetch`
|
||||
* Solus: `eopkg install fastfetch`
|
||||
* Slackware: `sbopkg -i fastfetch`
|
||||
* Void Linux: `xbps-install fastfetch`
|
||||
* Venom Linux: `scratch install fastfetch`
|
||||
|
||||
Replace sudo with doas depending on what you use.
|
||||
You may need `sudo`, `doas` or `sup` to run these commands.
|
||||
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging).
|
||||
|
||||
@@ -54,8 +60,9 @@ If fastfetch is not packaged for your distro or an outdated version is packaged,
|
||||
### Windows
|
||||
|
||||
* [scoop](https://scoop.sh/#/apps?q=fastfetch): `scoop install fastfetch`
|
||||
* [Chocolatey](https://community.chocolatey.org/packages/fastfetch): `choco install fastfetch`
|
||||
* [winget](https://github.com/microsoft/winget-pkgs/tree/master/manifests/f/Fastfetch-cli/Fastfetch): `winget install fastfetch`
|
||||
* [MSYS2 MinGW](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-fastfetch): `pacman -S mingw-w64-<subsystem>-<arch>-fastfetch`
|
||||
* [MSYS2 MinGW](https://packages.msys2.org/base/mingw-w64-fastfetch): `pacman -S mingw-w64-<subsystem>-<arch>-fastfetch`
|
||||
|
||||
You may also download the program directly from [the GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) in the form of an archive file.
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#compdef fastfetch
|
||||
|
||||
function _fastfetch() {
|
||||
local state
|
||||
|
||||
local -a opts
|
||||
opts=(${(f)"$(
|
||||
python <<EOF
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
data: dict[str, list[dict]] = json.loads(
|
||||
subprocess.check_output(["fastfetch", "--help-raw"])
|
||||
)
|
||||
|
||||
for key in data:
|
||||
for flag in data[key]:
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
if "short" in flag:
|
||||
command_prefix = f"""-{flag["short"]}[{flag["desc"]}]"""
|
||||
print_command(command_prefix, flag)
|
||||
|
||||
if "long" in flag:
|
||||
command_prefix = f"""--{flag["long"]}[{flag["desc"]}]"""
|
||||
print_command(command_prefix, flag)
|
||||
|
||||
|
||||
def print_command(command_prefix: str, flag: dict):
|
||||
if "arg" in flag:
|
||||
type: str = flag["arg"]["type"]
|
||||
if type == "bool":
|
||||
print(f"{command_prefix}:bool:(true false)")
|
||||
elif type == "color":
|
||||
print(f"{command_prefix}:color:(black red green yellow blue magenta cyan white default)")
|
||||
elif type == "command":
|
||||
print(f"{command_prefix}:module:->modules")
|
||||
elif type == "config":
|
||||
print(f"{command_prefix}:presets:->presets")
|
||||
elif type == "enum":
|
||||
temp: str = " ".join(flag["arg"]["enum"])
|
||||
print(f'{command_prefix}:type:( {temp} )')
|
||||
elif type == "logo":
|
||||
print(f"{command_prefix}:logo:->logo")
|
||||
elif type == "structure":
|
||||
print(f"{command_prefix}:structure:->structure")
|
||||
elif type == "path":
|
||||
print(f"{command_prefix}:path:_files -/")
|
||||
else:
|
||||
print(f"{command_prefix}:")
|
||||
else:
|
||||
print(f"{command_prefix}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception:
|
||||
sys.exit(1)
|
||||
EOF
|
||||
)"})
|
||||
|
||||
_arguments -C "$opts[@]"
|
||||
|
||||
case $state in
|
||||
modules)
|
||||
local -a modules=( ${(f)"$(fastfetch --list-modules autocompletion)"} )
|
||||
modules=( ${(L)^modules%%:*}-format format color )
|
||||
_describe 'module' modules
|
||||
;;
|
||||
presets)
|
||||
local -a presets=(
|
||||
${$(fastfetch --list-presets autocompletion):#.*}
|
||||
"none:Disable loading config file"
|
||||
)
|
||||
_describe 'preset' presets
|
||||
;;
|
||||
structure)
|
||||
local -a structures=( ${(f)"$(fastfetch --list-modules autocompletion)"} )
|
||||
_describe 'structure' structures
|
||||
;;
|
||||
logo)
|
||||
local -a logos=(
|
||||
$(fastfetch --list-logos autocompletion)
|
||||
"none:Don't print logo"
|
||||
"small:Print small ascii logo if available"
|
||||
)
|
||||
_describe 'logo' logos
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_fastfetch "$@"
|
||||
Vendored
+30
@@ -1,3 +1,33 @@
|
||||
fastfetch (2.21.3) jammy; urgency=medium
|
||||
|
||||
* Update to 2.21.3
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 15 Aug 2024 16:14:52 +0800
|
||||
|
||||
fastfetch (2.21.2) jammy; urgency=medium
|
||||
|
||||
* Update to 2.21.2
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 14 Aug 2024 14:42:07 +0800
|
||||
|
||||
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
|
||||
|
||||
Vendored
+1
-1
@@ -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
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.19.1_source.buildinfo universe/utils optional
|
||||
fastfetch_2.21.3_source.buildinfo universe/utils optional
|
||||
|
||||
+46
-4
@@ -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
@@ -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",
|
||||
|
||||
@@ -75,7 +75,8 @@
|
||||
},
|
||||
{
|
||||
"type": "publicip",
|
||||
"key": "WAN IP"
|
||||
"key": "WAN IP",
|
||||
"timeout": 1000
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+5
-1
@@ -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",
|
||||
|
||||
@@ -97,7 +97,8 @@
|
||||
{
|
||||
"key": "Public IP ",
|
||||
"keyColor": "cyan",
|
||||
"type": "publicip"
|
||||
"type": "publicip",
|
||||
"timeout": 1000
|
||||
},
|
||||
"break",
|
||||
{
|
||||
|
||||
@@ -66,7 +66,10 @@
|
||||
"type": "localip",
|
||||
"compact": true
|
||||
},
|
||||
"publicip",
|
||||
{
|
||||
"type": "publicip",
|
||||
"timeout": 1000
|
||||
},
|
||||
{
|
||||
"type": "wifi",
|
||||
"format": "{ssid}"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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": "[_Kernel___> ",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"outputColor": "white",
|
||||
"key": " [_Packages_> ",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "localip",
|
||||
"outputColor": "white",
|
||||
"key": " [_Local_IP_> ",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"format": "[{3}] {1} / {2}",
|
||||
"key": " [_RAM______> ",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"format": "[{3}] {1} / {2}",
|
||||
"key": " [_SWAP_____> ",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"format": "[{3}] {1} / {2} {9}",
|
||||
"key": " [_Disk_____> ",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
{
|
||||
"type": "battery",
|
||||
"format": "[{4}] {5}",
|
||||
"key": " [_Battery__> ",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "colors",
|
||||
"paddingLeft": 9,
|
||||
"symbol": "circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -161,7 +161,8 @@
|
||||
{
|
||||
"type": "publicip",
|
||||
"key": "├─",
|
||||
"keyColor": "blue"
|
||||
"keyColor": "blue",
|
||||
"timeout": 1000
|
||||
},
|
||||
{
|
||||
"type": "wifi",
|
||||
|
||||
@@ -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
@@ -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
@@ -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
-36
@@ -54,10 +54,6 @@ void ffInitInstance(void)
|
||||
#else
|
||||
// Never use `setlocale(LC_ALL, "")`
|
||||
setlocale(LC_TIME, "");
|
||||
setlocale(LC_NUMERIC, "");
|
||||
#ifdef LC_MESSAGES
|
||||
setlocale(LC_MESSAGES, "");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
initState(&instance.state);
|
||||
@@ -173,94 +169,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
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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_,
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -36,6 +36,7 @@ const char* ffCPUAppleCodeToName(uint32_t code)
|
||||
case 6030: return "Apple M3 Pro";
|
||||
case 6031:
|
||||
case 6034: return "Apple M3 Max";
|
||||
case 8132: return "Apple M4";
|
||||
default: return "Apple Silicon";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,3 +30,30 @@ typedef struct FFCPUResult
|
||||
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
const char* ffCPUAppleCodeToName(uint32_t code);
|
||||
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
// WARNING: CPUID may report frequencies of efficient cores
|
||||
inline static const char* ffCPUDetectSpeedByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t base = 0, max = 0, bus = 0, unused = 0;
|
||||
if (!__get_cpuid(0x16, &base, &max, &bus, &unused))
|
||||
return "Unsupported instruction";
|
||||
|
||||
// cpuid returns 0 MHz when hyper-v is enabled
|
||||
if (base) cpu->frequencyBase = base;
|
||||
if (max) cpu->frequencyMax = max;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline static const char* ffCPUDetectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
return "Unsupported platform";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* decPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xa10: return "SA110";
|
||||
case 0xa11: return "SA1100";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* apmPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x000: return "X-Gene";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* nvidiaPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x000: return "Denver";
|
||||
case 0x003: return "Denver 2";
|
||||
case 0x004: return "Carmel";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* faradayPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x526: return "FA526";
|
||||
case 0x626: return "FA626";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* fujitsuPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0x001: return "A64FX";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* amperePartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xac3: return "Ampere-1";
|
||||
case 0xac4: return "Ampere-1a";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* msPartId2name(uint32_t partId)
|
||||
{
|
||||
switch (partId)
|
||||
{
|
||||
case 0xd49: return "Azure-Cobalt-100";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
}
|
||||
}
|
||||
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
|
||||
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
|
||||
{
|
||||
ffStrbufClear(&buffer);
|
||||
|
||||
+126
-122
@@ -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,62 +74,120 @@ 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";
|
||||
#if __arm__ || __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;
|
||||
uint32_t lastPartId = UINT32_MAX;
|
||||
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;
|
||||
if (partId > 0) // Linux reports 0 for unknown CPUs
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (lastPartId != partId)
|
||||
{
|
||||
if (lastPartId != UINT32_MAX)
|
||||
{
|
||||
if (num > 1)
|
||||
ffStrbufAppendF(&cpu->name, "*%u", num);
|
||||
ffStrbufAppendS(&cpu->name, " + ");
|
||||
}
|
||||
if (name)
|
||||
ffStrbufAppendS(&cpu->name, name);
|
||||
else if (partId)
|
||||
ffStrbufAppendF(&cpu->name, "%s-%X", cpu->vendor.chars, partId);
|
||||
else
|
||||
ffStrbufAppend(&cpu->name, &cpu->vendor);
|
||||
lastPartId = partId;
|
||||
num = 1;
|
||||
}
|
||||
else
|
||||
++num;
|
||||
}
|
||||
if (num > 1)
|
||||
ffStrbufAppendF(&cpu->name, "*%u", num);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* parseCpuInfo(
|
||||
FF_MAYBE_UNUSED FILE* cpuinfo,
|
||||
FF_MAYBE_UNUSED FFCPUResult* cpu,
|
||||
FF_MAYBE_UNUSED FFstrbuf* physicalCoresBuffer,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuMHz,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuIsa,
|
||||
FF_MAYBE_UNUSED FFstrbuf* cpuUarch,
|
||||
FF_MAYBE_UNUSED 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
|
||||
if(*line == '\0' || *line == '\n')
|
||||
//Stop after reasonable information is acquired
|
||||
if((*line == '\0' || *line == '\n')
|
||||
#if __arm__ || __loongarch__
|
||||
&& cpu->name.length > 0 // #1202 #1204
|
||||
#endif
|
||||
)
|
||||
break;
|
||||
|
||||
(void)(
|
||||
ffParsePropLine(line, "model name :", &cpu->name) ||
|
||||
ffParsePropLine(line, "vendor_id :", &cpu->vendor) ||
|
||||
ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) ||
|
||||
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
|
||||
ffParsePropLine(line, "isa :", cpuIsa) ||
|
||||
ffParsePropLine(line, "uarch :", cpuUarch) ||
|
||||
|
||||
#ifdef __aarch64__
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", &implementer)) ||
|
||||
// arm64 doesn't have "model name"; arm32 does have "model name" but its value is not useful.
|
||||
// "Hardware" should always be used in this case
|
||||
#if !(__arm__ || __aarch64__)
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) ||
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) ||
|
||||
(physicalCoresBuffer->length == 0 && ffParsePropLine(line, "cpu cores :", physicalCoresBuffer)) ||
|
||||
(cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz :", cpuMHz)) ||
|
||||
#endif
|
||||
|
||||
#if !(__x86_64__ || __i386__ || __arm__ || __aarch64__)
|
||||
(cpuIsa->length == 0 && ffParsePropLine(line, "isa :", cpuIsa)) ||
|
||||
(cpuUarch->length == 0 && ffParsePropLine(line, "uarch :", cpuUarch)) ||
|
||||
#endif
|
||||
|
||||
#if __arm__ || __aarch64__
|
||||
(cpuImplementer->length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
|
||||
(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 __powerpc__ || __powerpc
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -221,16 +281,19 @@ static double detectCPUTemp(void)
|
||||
{
|
||||
if(
|
||||
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
|
||||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
|
||||
ffStrbufCompS(&value->name, "coretemp") == 0
|
||||
ffStrbufEqualS(&value->name, "k10temp") ||
|
||||
ffStrbufEqualS(&value->name, "coretemp")
|
||||
) return value->value;
|
||||
}
|
||||
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
static void parseIsa(FFstrbuf* cpuIsa)
|
||||
FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa)
|
||||
{
|
||||
// Always use the last part of the ISA string. Ref: #590 #1204
|
||||
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
|
||||
|
||||
if(ffStrbufStartsWithS(cpuIsa, "rv"))
|
||||
{
|
||||
// RISC-V ISA string example: "rv64imafdch_zicsr_zifencei".
|
||||
@@ -246,13 +309,9 @@ static void parseIsa(FFstrbuf* cpuIsa)
|
||||
}
|
||||
// The final ISA output of the above example is "rv64gch".
|
||||
}
|
||||
if(ffStrbufStartsWithS(cpuIsa, "mips"))
|
||||
{
|
||||
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
void detectAsahi(FFCPUResult* cpu)
|
||||
FF_MAYBE_UNUSED static void detectAsahi(FFCPUResult* cpu)
|
||||
{
|
||||
// In Asahi Linux, reading /proc/device-tree/compatible gives
|
||||
// information on the device model. It consists of 3 NUL terminated
|
||||
@@ -277,23 +336,31 @@ 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();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
|
||||
|
||||
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
|
||||
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
|
||||
|
||||
#if !(__x86_64__ || __i386__ || __arm__ || __aarch64__)
|
||||
if(cpuUarch.length > 0)
|
||||
{
|
||||
if(cpu->name.length > 0)
|
||||
@@ -308,84 +375,21 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffStrbufAppendC(&cpu->name, ' ');
|
||||
ffStrbufAppend(&cpu->name, &cpuIsa);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
detectAndroid(cpu);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__aarch64__)
|
||||
#if __arm__ || __aarch64__
|
||||
uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16);
|
||||
ffStrbufSetStatic(&cpu->vendor, hwImplId2Vendor(cpuImplementer));
|
||||
|
||||
#if __ANDROID__
|
||||
detectAndroid(cpu);
|
||||
#elif __aarch64__
|
||||
detectAsahi(cpu);
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
|
||||
kstat_named_t* kn = kstat_data_lookup(ks, "vendor_id");
|
||||
ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
|
||||
}
|
||||
{
|
||||
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
|
||||
if (kn->value.ui32 > cpu->frequencyBase)
|
||||
cpu->frequencyBase = kn->value.ui32;
|
||||
}
|
||||
|
||||
ks = kstat_lookup(kc, "unix", -1, "system_misc");
|
||||
if (ks && kstat_read(kc, ks, NULL) >= 0)
|
||||
|
||||
@@ -54,31 +54,6 @@ typedef struct FFSmbiosProcessorInfo
|
||||
static_assert(offsetof(FFSmbiosProcessorInfo, ThreadEnabled) == 0x30,
|
||||
"FFSmbiosProcessorInfo: Wrong struct alignment");
|
||||
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
|
||||
#include <cpuid.h>
|
||||
|
||||
inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t base = 0, max = 0, bus = 0, unused = 0;
|
||||
if (!__get_cpuid(0x16, &base, &max, &bus, &unused))
|
||||
return "Unsupported instruction";
|
||||
|
||||
// cpuid returns 0 MHz when hyper-v is enabled
|
||||
if (base) cpu->frequencyBase = base;
|
||||
if (max) cpu->frequencyMax = max;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline static const char* detectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
|
||||
{
|
||||
return "Unsupported platform";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
{
|
||||
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
|
||||
@@ -193,7 +168,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
detectSpeedByCpuid(cpu);
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
if (options->showPeCoreCount) detectCoreTypes(cpu);
|
||||
|
||||
if (cpu->frequencyMax == 0)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -72,7 +72,7 @@ static bool isPhysicalDevice(const struct mntent* device)
|
||||
) return false;
|
||||
|
||||
// https://source.android.com/docs/core/ota/apex?hl=zh-cn
|
||||
if(ffStrStartsWith(device->mnt_dir, "/apex/"))
|
||||
if(ffStrStartsWith(device->mnt_dir, "/apex/"))
|
||||
return false;
|
||||
|
||||
#endif // __ANDROID__
|
||||
@@ -240,8 +240,16 @@ static void detectStats(FFDisk* disk)
|
||||
disk->bytesAvailable = fs.f_bavail * fs.f_frsize;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
|
||||
disk->filesTotal = (uint32_t) fs.f_files;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
|
||||
if (fs.f_files >= fs.f_ffree)
|
||||
{
|
||||
disk->filesTotal = (uint32_t) fs.f_files;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Windows filesystem in WSL
|
||||
disk->filesTotal = disk->filesUsed = 0;
|
||||
}
|
||||
|
||||
if(fs.f_flag & ST_RDONLY)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
|
||||
@@ -37,24 +37,23 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
|
||||
if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY))
|
||||
continue;
|
||||
|
||||
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
|
||||
ffStrbufInit(&device->name);
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
|
||||
|
||||
{
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName);
|
||||
if (ffAppendFileBuffer(pathSysBlock, &device->name))
|
||||
if (ffAppendFileBuffer(pathSysBlock, &name))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
if (device->name.length > 0)
|
||||
ffStrbufAppendC(&device->name, ' ');
|
||||
ffStrbufTrimRightSpace(&name);
|
||||
if (name.length > 0)
|
||||
ffStrbufAppendC(&name, ' ');
|
||||
}
|
||||
|
||||
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName);
|
||||
ffAppendFileBuffer(pathSysBlock, &device->name);
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
ffAppendFileBuffer(pathSysBlock, &name);
|
||||
ffStrbufTrimRightSpace(&name);
|
||||
|
||||
if (device->name.length == 0)
|
||||
ffStrbufSetS(&device->name, devName);
|
||||
if (name.length == 0)
|
||||
ffStrbufSetS(&name, devName);
|
||||
else if (ffStrStartsWith(devName, "nvme"))
|
||||
{
|
||||
int devid, nsid;
|
||||
@@ -69,17 +68,13 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
|
||||
if (multiNs)
|
||||
{
|
||||
// In Asahi Linux, there are multiple namespaces for the same NVMe drive.
|
||||
ffStrbufAppendF(&device->name, " - %d", nsid);
|
||||
ffStrbufAppendF(&name, " - %d", nsid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
result->length--;
|
||||
if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// I/Os merges sectors ticks ...
|
||||
@@ -94,6 +89,8 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
|
||||
continue;
|
||||
}
|
||||
|
||||
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
|
||||
ffStrbufInitMove(&device->name, &name);
|
||||
ffStrbufInitF(&device->devPath, "/dev/%s", devName);
|
||||
device->bytesRead = sectorRead * 512;
|
||||
device->bytesWritten = sectorWritten * 512;
|
||||
|
||||
@@ -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,22 @@ 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;
|
||||
}
|
||||
display->bitDepth = bitDepth;
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
if (CoreDisplay_Display_IsHDRModeEnabled)
|
||||
{
|
||||
display->hdrEnabled = CoreDisplay_Display_IsHDRModeEnabled(screen);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,17 +1,44 @@
|
||||
#include "editor.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/path.h"
|
||||
#include "util/binary.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
static inline char* realpath(const char* restrict file_name, char* restrict resolved_name)
|
||||
{
|
||||
return _fullpath(resolved_name, file_name, _MAX_PATH);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool extractNvimVersionFromBinary(const char* str, uint32_t len, void* userdata)
|
||||
{
|
||||
if (len < strlen("NVIM v0.0.0")) return true;
|
||||
if (!ffStrStartsWith(str, "NVIM v")) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("NVIM v"));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool extractVimVersionFromBinary(const char* str, uint32_t len, void* userdata)
|
||||
{
|
||||
if (len < strlen("VIM - Vi IMproved 0.0")) return true;
|
||||
if (!ffStrStartsWith(str, "VIM - Vi IMproved ")) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("VIM - Vi IMproved "));
|
||||
ffStrbufSubstrBeforeFirstC(userdata, ' ');
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool extractNanoVersionFromBinary(const char* str, uint32_t len, void* userdata)
|
||||
{
|
||||
if (len < strlen("GNU nano 0.0")) return true;
|
||||
if (!ffStrStartsWith(str, "GNU nano ")) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("GNU nano "));
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectEditor(FFEditorResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->name, getenv("VISUAL"));
|
||||
@@ -26,41 +53,26 @@ const char* ffDetectEditor(FFEditorResult* result)
|
||||
return "$VISUAL or $EDITOR not set";
|
||||
}
|
||||
|
||||
if (!instance.config.general.detectVersion) return NULL;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (result->name.chars[0] != '/')
|
||||
{
|
||||
if (ffProcessAppendStdOut(&result->path, (char* const[]){
|
||||
FASTFETCH_TARGET_DIR_USR "/bin/which",
|
||||
result->name.chars,
|
||||
NULL,
|
||||
}) != NULL || result->path.length == 0)
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (!(result->name.length > 3 && ffCharIsEnglishAlphabet(result->name.chars[0]) && result->name.chars[1] == ':' && result->name.chars[2] == '\\'))
|
||||
{
|
||||
char buf[32];
|
||||
uint32_t len = GetSystemDirectoryA(buf, sizeof(buf));
|
||||
if (len < strlen("C:\\WINDOWS\\system32")) return NULL;
|
||||
strncpy(buf + len, "\\where.exe", sizeof(buf) - len);
|
||||
if (ffProcessAppendStdOut(&result->path, (char* const[]){
|
||||
buf,
|
||||
result->name.chars,
|
||||
NULL,
|
||||
}) != NULL || result->path.length == 0)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
if (ffIsAbsolutePath(result->name.chars))
|
||||
ffStrbufSet(&result->path, &result->name);
|
||||
else
|
||||
{
|
||||
const char* error = ffFindExecutableInPath(result->name.chars, &result->path);
|
||||
if (error) return NULL;
|
||||
}
|
||||
|
||||
char buf[PATH_MAX + 1];
|
||||
if (!realpath(result->path.chars, buf))
|
||||
return NULL;
|
||||
{
|
||||
char buf[PATH_MAX + 1];
|
||||
if (!realpath(result->path.chars, buf))
|
||||
return NULL;
|
||||
|
||||
ffStrbufSetS(&result->path, buf);
|
||||
// WIN32: Should we handle scoop shim exe here?
|
||||
|
||||
#ifdef __linux__
|
||||
if (!ffStrEndsWith(buf, "/snap"))
|
||||
#endif
|
||||
ffStrbufSetS(&result->path, buf);
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t index = ffStrbufLastIndexC(&result->path,
|
||||
@@ -82,6 +94,17 @@ const char* ffDetectEditor(FFEditorResult* result)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!instance.config.general.detectVersion) return NULL;
|
||||
|
||||
if (ffStrbufEqualS(&result->exe, "nvim"))
|
||||
ffBinaryExtractStrings(result->path.chars, extractNvimVersionFromBinary, &result->version);
|
||||
else if (ffStrbufEqualS(&result->exe, "vim"))
|
||||
ffBinaryExtractStrings(result->path.chars, extractVimVersionFromBinary, &result->version);
|
||||
else if (ffStrbufEqualS(&result->exe, "nano"))
|
||||
ffBinaryExtractStrings(result->path.chars, extractNanoVersionFromBinary, &result->version);
|
||||
|
||||
if (result->version.length > 0) return NULL;
|
||||
|
||||
const char* param = NULL;
|
||||
if (
|
||||
ffStrbufEqualS(&result->exe, "nano") ||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+141
-48
@@ -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,17 @@ 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 +290,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 +326,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 +335,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 +348,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 +369,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 +412,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 +432,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 +529,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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 (& 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);
|
||||
@@ -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);
|
||||
|
||||
@@ -1,7 +1,22 @@
|
||||
#include "initsystem.h"
|
||||
#include "common/processing.h"
|
||||
#include "util/binary.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)
|
||||
ffBinaryExtractStrings(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;
|
||||
|
||||
@@ -9,12 +9,12 @@ const char* ffDetectLoadavg(double result[3])
|
||||
|
||||
// Don't use syscall for container compatibility. #620
|
||||
char buf[64];
|
||||
ssize_t nRead = ffReadFileData("/proc/uptime", sizeof(buf) - 1, buf);
|
||||
ssize_t nRead = ffReadFileData("/proc/loadavg", sizeof(buf) - 1, buf);
|
||||
if (nRead > 0)
|
||||
{
|
||||
buf[nRead] = '\0';
|
||||
|
||||
if (sscanf(buf, "%lf %lf %lf", &result[0], &result[1], &result[2]) == 3)
|
||||
if (sscanf(buf, "%lf%lf%lf", &result[0], &result[1], &result[2]) == 3)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
void ffDetectLocale(FFstrbuf* result)
|
||||
{
|
||||
ffStrbufAppendS(result, getenv("LC_MESSAGES"));
|
||||
ffStrbufAppendS(result, getenv("LC_ALL"));
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
@@ -12,11 +12,5 @@ void ffDetectLocale(FFstrbuf* result)
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
#ifdef LC_MESSAGES
|
||||
ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL));
|
||||
if(result->length > 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
ffStrbufAppendS(result, setlocale(LC_TIME, NULL));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ typedef struct FFLocalIpResult
|
||||
FFstrbuf ipv6;
|
||||
FFstrbuf mac;
|
||||
int32_t mtu;
|
||||
int32_t speed;
|
||||
bool defaultRoute;
|
||||
} FFLocalIpResult;
|
||||
|
||||
|
||||
@@ -12,7 +12,13 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sockios.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_dl.h>
|
||||
#else
|
||||
#include <netpacket/packet.h>
|
||||
@@ -40,6 +46,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type,
|
||||
ffStrbufInit(&ip->mac);
|
||||
ip->defaultRoute = defaultRoute;
|
||||
ip->mtu = -1;
|
||||
ip->speed = -1;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
@@ -172,9 +179,388 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
strncpy(ifr.ifr_name, iface->name.chars, IFNAMSIZ - 1);
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFMTU, &ifr) == 0)
|
||||
iface->mtu = (int32_t) ifr.ifr_mtu;
|
||||
|
||||
#ifdef __linux__
|
||||
struct ethtool_cmd edata = { .cmd = ETHTOOL_GSET };
|
||||
ifr.ifr_data = (void*) &edata;
|
||||
if (ioctl(sockfd, SIOCETHTOOL, &ifr) == 0)
|
||||
iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android
|
||||
#elif __FreeBSD__ || __APPLE__
|
||||
struct ifmediareq ifmr = {};
|
||||
strncpy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ - 1);
|
||||
if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0)
|
||||
{
|
||||
switch (IFM_SUBTYPE(ifmr.ifm_active))
|
||||
{
|
||||
#ifdef IFM_HPNA_1
|
||||
case IFM_HPNA_1:
|
||||
#endif
|
||||
iface->speed = 1; break;
|
||||
#ifdef IFM_1000_CX
|
||||
case IFM_1000_CX:
|
||||
#endif
|
||||
#ifdef IFM_1000_CX_SGMII
|
||||
case IFM_1000_CX_SGMII:
|
||||
#endif
|
||||
#ifdef IFM_1000_KX
|
||||
case IFM_1000_KX:
|
||||
#endif
|
||||
#ifdef IFM_1000_LX
|
||||
case IFM_1000_LX:
|
||||
#endif
|
||||
#ifdef IFM_1000_SGMII
|
||||
case IFM_1000_SGMII:
|
||||
#endif
|
||||
#ifdef IFM_1000_SX
|
||||
case IFM_1000_SX:
|
||||
#endif
|
||||
#ifdef IFM_1000_T
|
||||
case IFM_1000_T:
|
||||
#endif
|
||||
iface->speed = 1000; break;
|
||||
#ifdef IFM_100G_AUI2
|
||||
case IFM_100G_AUI2:
|
||||
#endif
|
||||
#ifdef IFM_100G_AUI2_AC
|
||||
case IFM_100G_AUI2_AC:
|
||||
#endif
|
||||
#ifdef IFM_100G_AUI4
|
||||
case IFM_100G_AUI4:
|
||||
#endif
|
||||
#ifdef IFM_100G_AUI4_AC
|
||||
case IFM_100G_AUI4_AC:
|
||||
#endif
|
||||
#ifdef IFM_100G_CAUI2
|
||||
case IFM_100G_CAUI2:
|
||||
#endif
|
||||
#ifdef IFM_100G_CAUI2_AC
|
||||
case IFM_100G_CAUI2_AC:
|
||||
#endif
|
||||
#ifdef IFM_100G_CAUI4
|
||||
case IFM_100G_CAUI4:
|
||||
#endif
|
||||
#ifdef IFM_100G_CAUI4_AC
|
||||
case IFM_100G_CAUI4_AC:
|
||||
#endif
|
||||
#ifdef IFM_100G_CP2
|
||||
case IFM_100G_CP2:
|
||||
#endif
|
||||
#ifdef IFM_100G_CR4
|
||||
case IFM_100G_CR4:
|
||||
#endif
|
||||
#ifdef IFM_100G_CR_PAM4
|
||||
case IFM_100G_CR_PAM4:
|
||||
#endif
|
||||
#ifdef IFM_100G_DR
|
||||
case IFM_100G_DR:
|
||||
#endif
|
||||
#ifdef IFM_100G_KR2_PAM4
|
||||
case IFM_100G_KR2_PAM4:
|
||||
#endif
|
||||
#ifdef IFM_100G_KR4
|
||||
case IFM_100G_KR4:
|
||||
#endif
|
||||
#ifdef IFM_100G_KR_PAM4
|
||||
case IFM_100G_KR_PAM4:
|
||||
#endif
|
||||
#ifdef IFM_100G_LR4
|
||||
case IFM_100G_LR4:
|
||||
#endif
|
||||
#ifdef IFM_100G_SR2
|
||||
case IFM_100G_SR2:
|
||||
#endif
|
||||
#ifdef IFM_100G_SR4
|
||||
case IFM_100G_SR4:
|
||||
#endif
|
||||
iface->speed = 100000; break;
|
||||
#ifdef IFM_100_FX
|
||||
case IFM_100_FX:
|
||||
#endif
|
||||
#ifdef IFM_100_SGMII
|
||||
case IFM_100_SGMII:
|
||||
#endif
|
||||
#ifdef IFM_100_T
|
||||
case IFM_100_T:
|
||||
#endif
|
||||
#ifdef IFM_100_T2
|
||||
case IFM_100_T2:
|
||||
#endif
|
||||
#ifdef IFM_100_T4
|
||||
case IFM_100_T4:
|
||||
#endif
|
||||
#ifdef IFM_100_TX
|
||||
case IFM_100_TX:
|
||||
#endif
|
||||
#ifdef IFM_100_VG
|
||||
case IFM_100_VG:
|
||||
#endif
|
||||
iface->speed = 100; break;
|
||||
#ifdef IFM_10G_AOC
|
||||
case IFM_10G_AOC:
|
||||
#endif
|
||||
#ifdef IFM_10G_CR1
|
||||
case IFM_10G_CR1:
|
||||
#endif
|
||||
#ifdef IFM_10G_CX4
|
||||
case IFM_10G_CX4:
|
||||
#endif
|
||||
#ifdef IFM_10G_ER
|
||||
case IFM_10G_ER:
|
||||
#endif
|
||||
#ifdef IFM_10G_KR
|
||||
case IFM_10G_KR:
|
||||
#endif
|
||||
#ifdef IFM_10G_KX4
|
||||
case IFM_10G_KX4:
|
||||
#endif
|
||||
#ifdef IFM_10G_LR
|
||||
case IFM_10G_LR:
|
||||
#endif
|
||||
#ifdef IFM_10G_LRM
|
||||
case IFM_10G_LRM:
|
||||
#endif
|
||||
#ifdef IFM_10G_SFI
|
||||
case IFM_10G_SFI:
|
||||
#endif
|
||||
#ifdef IFM_10G_SR
|
||||
case IFM_10G_SR:
|
||||
#endif
|
||||
#ifdef IFM_10G_T
|
||||
case IFM_10G_T:
|
||||
#endif
|
||||
#ifdef IFM_10G_TWINAX
|
||||
case IFM_10G_TWINAX:
|
||||
#endif
|
||||
#ifdef IFM_10G_TWINAX_LONG
|
||||
case IFM_10G_TWINAX_LONG:
|
||||
#endif
|
||||
iface->speed = 10000; break;
|
||||
#ifdef IFM_10_2
|
||||
case IFM_10_2:
|
||||
#endif
|
||||
#ifdef IFM_10_5
|
||||
case IFM_10_5:
|
||||
#endif
|
||||
#ifdef IFM_10_FL
|
||||
case IFM_10_FL:
|
||||
#endif
|
||||
#ifdef IFM_10_STP
|
||||
case IFM_10_STP:
|
||||
#endif
|
||||
#ifdef IFM_10_T
|
||||
case IFM_10_T:
|
||||
#endif
|
||||
iface->speed = 10; break;
|
||||
#ifdef IFM_200G_AUI4
|
||||
case IFM_200G_AUI4:
|
||||
#endif
|
||||
#ifdef IFM_200G_AUI4_AC
|
||||
case IFM_200G_AUI4_AC:
|
||||
#endif
|
||||
#ifdef IFM_200G_AUI8
|
||||
case IFM_200G_AUI8:
|
||||
#endif
|
||||
#ifdef IFM_200G_AUI8_AC
|
||||
case IFM_200G_AUI8_AC:
|
||||
#endif
|
||||
#ifdef IFM_200G_CR4_PAM4
|
||||
case IFM_200G_CR4_PAM4:
|
||||
#endif
|
||||
#ifdef IFM_200G_DR4
|
||||
case IFM_200G_DR4:
|
||||
#endif
|
||||
#ifdef IFM_200G_FR4
|
||||
case IFM_200G_FR4:
|
||||
#endif
|
||||
#ifdef IFM_200G_KR4_PAM4
|
||||
case IFM_200G_KR4_PAM4:
|
||||
#endif
|
||||
#ifdef IFM_200G_LR4
|
||||
case IFM_200G_LR4:
|
||||
#endif
|
||||
#ifdef IFM_200G_SR4
|
||||
case IFM_200G_SR4:
|
||||
#endif
|
||||
iface->speed = 200000; break;
|
||||
#ifdef IFM_20G_KR2
|
||||
case IFM_20G_KR2:
|
||||
#endif
|
||||
iface->speed = 20000; break;
|
||||
#ifdef IFM_2500_KX
|
||||
case IFM_2500_KX:
|
||||
#endif
|
||||
#ifdef IFM_2500_SX
|
||||
case IFM_2500_SX:
|
||||
#endif
|
||||
#ifdef IFM_2500_T
|
||||
case IFM_2500_T:
|
||||
#endif
|
||||
#ifdef IFM_2500_X
|
||||
case IFM_2500_X:
|
||||
#endif
|
||||
iface->speed = 2500; break;
|
||||
#ifdef IFM_25G_ACC
|
||||
case IFM_25G_ACC:
|
||||
#endif
|
||||
#ifdef IFM_25G_AOC
|
||||
case IFM_25G_AOC:
|
||||
#endif
|
||||
#ifdef IFM_25G_AUI
|
||||
case IFM_25G_AUI:
|
||||
#endif
|
||||
#ifdef IFM_25G_CR
|
||||
case IFM_25G_CR:
|
||||
#endif
|
||||
#ifdef IFM_25G_CR1
|
||||
case IFM_25G_CR1:
|
||||
#endif
|
||||
#ifdef IFM_25G_CR_S
|
||||
case IFM_25G_CR_S:
|
||||
#endif
|
||||
#ifdef IFM_25G_KR
|
||||
case IFM_25G_KR:
|
||||
#endif
|
||||
#ifdef IFM_25G_KR1
|
||||
case IFM_25G_KR1:
|
||||
#endif
|
||||
#ifdef IFM_25G_KR_S
|
||||
case IFM_25G_KR_S:
|
||||
#endif
|
||||
#ifdef IFM_25G_LR
|
||||
case IFM_25G_LR:
|
||||
#endif
|
||||
#ifdef IFM_25G_PCIE
|
||||
case IFM_25G_PCIE:
|
||||
#endif
|
||||
#ifdef IFM_25G_SR
|
||||
case IFM_25G_SR:
|
||||
#endif
|
||||
#ifdef IFM_25G_T
|
||||
case IFM_25G_T:
|
||||
#endif
|
||||
iface->speed = 25000; break;
|
||||
#ifdef IFM_400G_AUI8
|
||||
case IFM_400G_AUI8:
|
||||
#endif
|
||||
#ifdef IFM_400G_AUI8_AC
|
||||
case IFM_400G_AUI8_AC:
|
||||
#endif
|
||||
#ifdef IFM_400G_DR4
|
||||
case IFM_400G_DR4:
|
||||
#endif
|
||||
#ifdef IFM_400G_FR8
|
||||
case IFM_400G_FR8:
|
||||
#endif
|
||||
#ifdef IFM_400G_LR8
|
||||
case IFM_400G_LR8:
|
||||
#endif
|
||||
iface->speed = 400000; break;
|
||||
#ifdef IFM_40G_CR4
|
||||
case IFM_40G_CR4:
|
||||
#endif
|
||||
#ifdef IFM_40G_ER4
|
||||
case IFM_40G_ER4:
|
||||
#endif
|
||||
#ifdef IFM_40G_KR4
|
||||
case IFM_40G_KR4:
|
||||
#endif
|
||||
#ifdef IFM_40G_LR4
|
||||
case IFM_40G_LR4:
|
||||
#endif
|
||||
#ifdef IFM_40G_SR4
|
||||
case IFM_40G_SR4:
|
||||
#endif
|
||||
#ifdef IFM_40G_XLAUI
|
||||
case IFM_40G_XLAUI:
|
||||
#endif
|
||||
#ifdef IFM_40G_XLAUI_AC
|
||||
case IFM_40G_XLAUI_AC:
|
||||
#endif
|
||||
#ifdef IFM_40G_XLPPI
|
||||
case IFM_40G_XLPPI:
|
||||
#endif
|
||||
#ifdef IFM_40G_LM4
|
||||
case IFM_40G_LM4:
|
||||
#endif
|
||||
iface->speed = 40000; break;
|
||||
#ifdef IFM_5000_KR
|
||||
case IFM_5000_KR:
|
||||
#endif
|
||||
#ifdef IFM_5000_KR1
|
||||
case IFM_5000_KR1:
|
||||
#endif
|
||||
#ifdef IFM_5000_KR_S
|
||||
case IFM_5000_KR_S:
|
||||
#endif
|
||||
#ifdef IFM_5000_T
|
||||
case IFM_5000_T:
|
||||
#endif
|
||||
iface->speed = 5000; break;
|
||||
#ifdef IFM_50G_AUI1
|
||||
case IFM_50G_AUI1:
|
||||
#endif
|
||||
#ifdef IFM_50G_AUI1_AC
|
||||
case IFM_50G_AUI1_AC:
|
||||
#endif
|
||||
#ifdef IFM_50G_AUI2
|
||||
case IFM_50G_AUI2:
|
||||
#endif
|
||||
#ifdef IFM_50G_AUI2_AC
|
||||
case IFM_50G_AUI2_AC:
|
||||
#endif
|
||||
#ifdef IFM_50G_CP
|
||||
case IFM_50G_CP:
|
||||
#endif
|
||||
#ifdef IFM_50G_CR2
|
||||
case IFM_50G_CR2:
|
||||
#endif
|
||||
#ifdef IFM_50G_FR
|
||||
case IFM_50G_FR:
|
||||
#endif
|
||||
#ifdef IFM_50G_KR2
|
||||
case IFM_50G_KR2:
|
||||
#endif
|
||||
#ifdef IFM_50G_KR_PAM4
|
||||
case IFM_50G_KR_PAM4:
|
||||
#endif
|
||||
#ifdef IFM_50G_LAUI2
|
||||
case IFM_50G_LAUI2:
|
||||
#endif
|
||||
#ifdef IFM_50G_LAUI2_AC
|
||||
case IFM_50G_LAUI2_AC:
|
||||
#endif
|
||||
#ifdef IFM_50G_LR
|
||||
case IFM_50G_LR:
|
||||
#endif
|
||||
#ifdef IFM_50G_LR2
|
||||
case IFM_50G_LR2:
|
||||
#endif
|
||||
#ifdef IFM_50G_PCIE
|
||||
case IFM_50G_PCIE:
|
||||
#endif
|
||||
#ifdef IFM_50G_SR
|
||||
case IFM_50G_SR:
|
||||
#endif
|
||||
#ifdef IFM_50G_SR2
|
||||
case IFM_50G_SR2:
|
||||
#endif
|
||||
#ifdef IFM_50G_KR4
|
||||
case IFM_50G_KR4:
|
||||
#endif
|
||||
iface->speed = 50000; break;
|
||||
#ifdef IFM_56G_R4
|
||||
case IFM_56G_R4:
|
||||
#endif
|
||||
iface->speed = 56000; break;
|
||||
default:
|
||||
iface->speed = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
if ((options->showType & FF_LOCALIP_TYPE_MAC_BIT) && ioctl(sockfd, SIOCGIFHWADDR, &ifr) == 0)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type,
|
||||
ffStrbufInit(&ip->ipv6);
|
||||
ffStrbufInit(&ip->mac);
|
||||
ip->defaultRoute = defaultRoute;
|
||||
ip->speed = -1;
|
||||
ip->mtu = -1;
|
||||
}
|
||||
else
|
||||
@@ -150,7 +151,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
}
|
||||
|
||||
if (!newIp)
|
||||
FF_LIST_GET(FFLocalIpResult, *results, results->length - 1)->mtu = (int32_t) adapter->Mtu;
|
||||
{
|
||||
FFLocalIpResult* result = FF_LIST_GET(FFLocalIpResult, *results, results->length - 1);
|
||||
result->speed = (int32_t) (adapter->ReceiveLinkSpeed / 1000);
|
||||
result->mtu = (int32_t) adapter->Mtu;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ typedef struct FFPackagesResult
|
||||
uint32_t guixHome;
|
||||
uint32_t guixSystem;
|
||||
uint32_t guixUser;
|
||||
uint32_t linglong;
|
||||
uint32_t lpkg;
|
||||
uint32_t lpkgbuild;
|
||||
uint32_t nixDefault;
|
||||
|
||||
@@ -471,6 +471,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
{
|
||||
packageCounts->guixSystem += getGuixPackages(baseDir, "/run/current-system/profile");
|
||||
}
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", DT_DIR);
|
||||
}
|
||||
|
||||
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/binary.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 = ffBinaryExtractStrings(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
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/binary.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef __FreeBSD__
|
||||
@@ -200,28 +201,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 +240,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)
|
||||
@@ -272,8 +251,24 @@ FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version)
|
||||
return version->length > 0;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version)
|
||||
static bool extractGnomeTerminalVersion(const char *str, FF_MAYBE_UNUSED uint32_t len, void *userdata)
|
||||
{
|
||||
if (!ffCharIsDigit(str[0])) return true;
|
||||
int count = 0;
|
||||
sscanf(str, "%*d.%*d.%*d%n", &count);
|
||||
if (count == 0) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str);
|
||||
return false;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if (exe->chars[0] == '/')
|
||||
{
|
||||
ffBinaryExtractStrings(exe->chars, extractGnomeTerminalVersion, version);
|
||||
if (version->length) return true;
|
||||
}
|
||||
|
||||
if(ffProcessAppendStdOut(version, (char* const[]){
|
||||
"gnome-terminal",
|
||||
"--version",
|
||||
@@ -507,6 +502,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(
|
||||
@@ -585,7 +607,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal"))
|
||||
return getTerminalVersionGnome(version);
|
||||
return getTerminalVersionGnome(exe, version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "konsole"))
|
||||
return getTerminalVersionKonsole(exe, version);
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -384,6 +384,14 @@ const FFShellResult* ffDetectShell()
|
||||
result.tty = -1;
|
||||
|
||||
pid_t ppid = getppid();
|
||||
|
||||
const char* ignoreParent = getenv("FFTS_IGNORE_PARENT");
|
||||
if (ignoreParent && ffStrEquals(ignoreParent, "1"))
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY _ = ffStrbufCreate();
|
||||
ffProcessGetBasicInfoLinux(ppid, &_, &ppid, NULL);
|
||||
}
|
||||
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
getUserShellFromEnv(&result);
|
||||
setShellInfoDetails(&result);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <wchar.h>
|
||||
@@ -53,7 +54,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 +155,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 +315,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);
|
||||
@@ -341,6 +346,10 @@ const FFShellResult* ffDetectShell(void)
|
||||
if(!ffProcessGetInfoWindows(0, &ppid, NULL, NULL, NULL, NULL, NULL))
|
||||
return &result;
|
||||
|
||||
const char* ignoreParent = getenv("FFTS_IGNORE_PARENT");
|
||||
if (ignoreParent && ffStrEquals(ignoreParent, "1"))
|
||||
ffProcessGetInfoWindows(ppid, &ppid, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
ppid = getShellInfo(&result, ppid);
|
||||
|
||||
if (result.processName.length > 0)
|
||||
|
||||
@@ -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,8 +1,8 @@
|
||||
#include "version.h"
|
||||
|
||||
#if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64)
|
||||
#if defined(__x86_64__)
|
||||
#define FF_ARCHITECTURE "x86_64"
|
||||
#elif defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(__i586__) || defined(__i586) || defined(__i686__) || defined(__i686)
|
||||
#elif defined(__i386__)
|
||||
#define FF_ARCHITECTURE "i386"
|
||||
#elif defined(__aarch64__)
|
||||
#define FF_ARCHITECTURE "aarch64"
|
||||
@@ -16,6 +16,8 @@
|
||||
#define FF_ARCHITECTURE "riscv"
|
||||
#elif defined(__s390x__)
|
||||
#define FF_ARCHITECTURE "s390x"
|
||||
#elif defined(__loongarch__)
|
||||
#define FF_ARCHITECTURE "loongarch"
|
||||
#else
|
||||
#define FF_ARCHITECTURE "unknown"
|
||||
#endif
|
||||
@@ -44,6 +46,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 =
|
||||
|
||||
@@ -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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user