Merge pull request #1151 from fastfetch-cli/dev

Release v2.21.0
This commit is contained in:
Carter Li
2024-08-05 14:21:00 +08:00
committed by GitHub
83 changed files with 2256 additions and 867 deletions
+1 -1
View File
@@ -2,4 +2,4 @@
check-filenames =
builtin = clear,rare,usage,informal
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,conexant
+3
View File
@@ -15,6 +15,9 @@ Paste content of /etc/os-release and /etc/lsb-release here. If none of these fil
```
# Ascii
An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
```
Paste ascii art here.
```
+6 -6
View File
@@ -35,7 +35,7 @@ jobs:
run: uname -a
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_LIBNM=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_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 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 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 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 directx-headers-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
+38 -1
View File
@@ -1,3 +1,40 @@
# 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 +43,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
+62 -31
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.20.0
VERSION 2.21.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,28 +44,27 @@ 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)
@@ -294,6 +293,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 +326,7 @@ set(LIBFASTFETCH_SRC
src/modules/battery/battery.c
src/modules/bios/bios.c
src/modules/bluetooth/bluetooth.c
src/modules/bluetoothradio/bluetoothradio.c
src/modules/board/board.c
src/modules/bootmgr/bootmgr.c
src/modules/brightness/brightness.c
@@ -421,6 +422,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
@@ -488,6 +490,7 @@ elseif(ANDROID)
src/detection/battery/battery_android.c
src/detection/bios/bios_android.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_android.c
src/detection/bootmgr/bootmgr_nosupport.c
src/detection/brightness/brightness_nosupport.c
@@ -539,7 +542,7 @@ elseif(ANDROID)
src/detection/camera/camera_android.c
src/util/platform/FFPlatform_unix.c
)
elseif(BSD)
elseif(FreeBSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
@@ -550,6 +553,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
@@ -626,6 +630,7 @@ elseif(APPLE)
src/detection/battery/battery_apple.c
src/detection/bios/bios_apple.c
src/detection/bluetooth/bluetooth_apple.m
src/detection/bluetoothradio/bluetoothradio_apple.m
src/detection/board/board_apple.c
src/detection/bootmgr/bootmgr_apple.c
src/detection/brightness/brightness_apple.c
@@ -689,6 +694,7 @@ elseif(WIN32)
src/detection/battery/battery_windows.c
src/detection/bios/bios_windows.c
src/detection/bluetooth/bluetooth_windows.c
src/detection/bluetoothradio/bluetoothradio_windows.c
src/detection/board/board_windows.c
src/detection/bootmgr/bootmgr_windows.c
src/detection/brightness/brightness_windows.cpp
@@ -763,6 +769,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
@@ -828,14 +835,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 +895,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 +1063,6 @@ ff_lib_enable(OPENCL
"OpenCL"
"OpenCL"
)
ff_lib_enable(LIBNM
"libnm"
"libnm"
)
ff_lib_enable(FREETYPE
"freetype2"
"FreeType2"
@@ -1125,7 +1128,7 @@ elseif(WIN32)
PRIVATE "hid"
PRIVATE "wtsapi32"
)
elseif(BSD)
elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "usbhid"
@@ -1178,7 +1181,35 @@ 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()
CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP)
if(HAVE_PTHREAD_NP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_PTHREAD_NP=1)
endif()
check_function_exists("pthread_timedjoin_np" HAVE_TIMEDJOIN_NP)
if(HAVE_TIMEDJOIN_NP)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_TIMEDJOIN_NP=1)
endif()
endif()
######################
+1 -1
View File
@@ -2,7 +2,7 @@ Source: fastfetch
Section: universe/utils
Priority: optional
Maintainer: Carter Li <zhangsongcui@live.cn>
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Standards-Version: 4.0.0
Homepage: https://github.com/fastfetch-cli/fastfetch
+31 -1
View File
@@ -745,6 +745,7 @@
"battery",
"bios",
"bluetooth",
"bluetoothradio",
"board",
"bootmgr",
"break",
@@ -1049,7 +1050,7 @@
"additionalProperties": false,
"properties": {
"type": {
"description": "List bluetooth devices",
"description": "List (connected) bluetooth devices",
"const": "bluetooth"
},
"showDisconnected": {
@@ -1080,6 +1081,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",
+1
View File
@@ -73,6 +73,7 @@
"opencl",
"users",
"bluetooth",
"bluetoothradio",
"sound",
"camera",
"gamepad",
+1
View File
@@ -75,6 +75,7 @@
"opencl",
"users",
"bluetooth",
"bluetoothradio",
"sound",
"camera",
"gamepad",
+1 -1
View File
@@ -106,7 +106,7 @@
{
"type": "cpu",
"key": "│ CPU FREQ │{$1}",
"format": "{freq-max}{/freq-max}{freq-base}{/} GHz"
"format": "{freq-max}{/freq-max}{freq-base}{/}"
},
{
"type": "loadavg",
+64 -29
View File
@@ -10,9 +10,8 @@ static bool loadLibSymbols(FFDBusLibrary* lib)
FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_append_args, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false)
@@ -20,10 +19,6 @@ static bool loadLibSymbols(FFDBusLibrary* lib)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false)
dbus = NULL; // don't auto dlclose
return true;
}
@@ -56,11 +51,11 @@ const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data)
return NULL;
}
bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_STRING)
if(argType == DBUS_TYPE_STRING || argType == DBUS_TYPE_OBJECT_PATH)
{
const char* value = NULL;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
@@ -72,6 +67,14 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
return true;
}
if (argType == DBUS_TYPE_BYTE)
{
uint8_t value;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
ffStrbufAppendC(result, (char) value);
return false; // Don't append a comma
}
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
return false;
@@ -79,7 +82,7 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
return ffDBusGetValue(dbus, &subIter, result);
return ffDBusGetString(dbus, &subIter, result);
//At this point we have an array
@@ -87,13 +90,16 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
while(true)
{
if(ffDBusGetValue(dbus, &subIter, result))
if(ffDBusGetString(dbus, &subIter, result))
{
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
FF_DBUS_ITER_CONTINUE(dbus, &subIter);
if(!dbus->lib->ffdbus_message_iter_next(&subIter))
break;
else
continue;
}
if(foundAValue)
@@ -122,11 +128,27 @@ bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result)
return ffDBusGetBool(dbus, &subIter, result);
}
bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result)
{
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_BYTE)
{
uint8_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if(argType == DBUS_TYPE_UINT16)
{
uint16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if(argType == DBUS_TYPE_UINT32)
{
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
return true;
@@ -137,15 +159,18 @@ bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result)
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetByte(dbus, &subIter, result);
return ffDBusGetUint(dbus, &subIter, result);
}
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method)
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg)
{
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
if(message == NULL)
return NULL;
if (arg)
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
dbus->lib->ffdbus_message_unref(message);
@@ -159,20 +184,10 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
if(message == NULL)
return NULL;
DBusMessageIter requestIterator;
dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator);
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface))
{
dbus->lib->ffdbus_message_unref(message);
return NULL;
}
if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property))
{
dbus->lib->ffdbus_message_unref(message);
return NULL;
}
dbus->lib->ffdbus_message_append_args(message,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
@@ -194,7 +209,27 @@ bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char*
return false;
}
bool ret = ffDBusGetValue(dbus, &rootIterator, result);
bool ret = ffDBusGetString(dbus, &rootIterator, result);
dbus->lib->ffdbus_message_unref(reply);
return ret;
}
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result)
{
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
if(reply == NULL)
return false;
DBusMessageIter rootIterator;
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
dbus->lib->ffdbus_message_unref(reply);
return false;
}
bool ret = ffDBusGetUint(dbus, &rootIterator, result);
dbus->lib->ffdbus_message_unref(reply);
+5 -18
View File
@@ -7,22 +7,12 @@
#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; \
}
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 +20,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 +29,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
+29 -32
View File
@@ -173,94 +173,91 @@ 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_DIRECTX_HEADERS
"Directx Headers\n"
#endif
#ifdef FF_USE_SYSTEM_YYJSON
#if FF_USE_SYSTEM_YYJSON
"System yyjson\n"
#endif
#if __has_include(<linux/videodev2.h>)
#if FF_HAVE_LINUX_VIDEODEV2
"linux/videodev2\n"
#endif
#if __has_include(<linux/wireless.h>)
#if FF_HAVE_LINUX_WIRELESS
"linux/wireless\n"
#endif
""
+28 -33
View File
@@ -8,8 +8,10 @@
#include <dirent.h>
#include <errno.h>
#if __has_include(<wordexp.h>)
#include <wordexp.h>
#if FF_HAVE_WORDEXP
#include <wordexp.h>
#else
#warning "<wordexp.h> not available"
#endif
static void createSubfolders(const char* fileName)
@@ -112,7 +114,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
{
bool result = false;
#if __has_include(<wordexp.h>) // https://github.com/termux/termux-packages/pull/7056
#if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056
wordexp_t exp;
if(wordexp(in, &exp, 0) != 0)
@@ -131,46 +133,39 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
return result;
}
static int ftty = -1;
static struct termios oldTerm;
void restoreTerm(void)
{
tcsetattr(ftty, TCSAFLUSH, &oldTerm);
}
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
{
int fin = STDIN_FILENO, fout = STDOUT_FILENO;
FF_AUTO_CLOSE_FD int ftty = -1;
if (ftty < 0)
{
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
if (ftty < 0)
return "open(\"/dev/tty\", O_RDWR | O_NOCTTY | O_CLOEXEC) failed";
if (!isatty(STDIN_FILENO))
{
if (ftty < 0)
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
fin = ftty;
}
if (!isatty(STDOUT_FILENO))
{
if (ftty < 0)
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
fout = ftty;
if(tcgetattr(ftty, &oldTerm) == -1)
return "tcgetattr(STDIN_FILENO, &oldTerm) failed";
struct termios newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(ftty, TCSAFLUSH, &newTerm) == -1)
return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)";
atexit(restoreTerm);
}
struct termios oldTerm;
if(tcgetattr(fin, &oldTerm) == -1)
return "tcgetattr(STDIN_FILENO, &oldTerm) failed";
struct termios newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(fin, TCSAFLUSH, &newTerm) == -1)
return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)";
ffWriteFDData(fout, strlen(request), request);
ffWriteFDData(ftty, strlen(request), request);
//Give the terminal some time to respond
if(poll(&(struct pollfd) { .fd = fin, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
{
tcsetattr(fin, TCSANOW, &oldTerm);
if(poll(&(struct pollfd) { .fd = ftty, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
return "poll() timeout or failed";
}
char buffer[512];
ssize_t bytesRead = read(fin, buffer, sizeof(buffer) - 1);
tcsetattr(fin, TCSANOW, &oldTerm);
ssize_t bytesRead = read(ftty, buffer, sizeof(buffer) - 1);
if(bytesRead <= 0)
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
+1
View File
@@ -8,6 +8,7 @@ static FFModuleBaseInfo* B[] = {
(void*) &instance.config.modules.battery,
(void*) &instance.config.modules.bios,
(void*) &instance.config.modules.bluetooth,
(void*) &instance.config.modules.bluetoothRadio,
(void*) &instance.config.modules.board,
(void*) &instance.config.modules.bootmgr,
(void*) &instance.config.modules.break_,
+5
View File
@@ -206,6 +206,11 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
else FF_APPEND_COLOR_PROP_COND(title, colorTitle)
else FF_APPEND_COLOR_PROP_COND(output, colorOutput)
else FF_APPEND_COLOR_PROP_COND(separator, colorSeparator)
else
{
fprintf(stderr, "Error: invalid color code found: %s\n", value);
exit(479);
}
}
ffStrbufAppendC(buffer, *value);
++value;
+2 -2
View File
@@ -33,7 +33,7 @@
#else
#include <pthread.h>
#include <signal.h>
#if __has_include(<pthread_np.h>)
#if FF_HAVE_PTHREAD_NP
#include <pthread_np.h>
#endif
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
@@ -51,7 +51,7 @@
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
static inline bool ffThreadJoin(FFThreadType thread, FF_MAYBE_UNUSED uint32_t timeout)
{
#if (defined(__linux__) && !defined(__ANDROID__)) || __has_include(<pthread_np.h>)
#if HAVE_TIMEDJOIN_NP
if (timeout > 0)
{
struct timespec ts;
+19 -18
View File
@@ -61,13 +61,17 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(ffStrEquals(deviceProperty, "Address"))
ffDBusGetValue(dbus, &dictIter, &device->address);
ffDBusGetString(dbus, &dictIter, &device->address);
else if(ffStrEquals(deviceProperty, "Name"))
ffDBusGetValue(dbus, &dictIter, &device->name);
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Icon"))
ffDBusGetValue(dbus, &dictIter, &device->type);
ffDBusGetString(dbus, &dictIter, &device->type);
else if(ffStrEquals(deviceProperty, "Percentage"))
ffDBusGetByte(dbus, &dictIter, &device->battery);
{
uint32_t percentage;
if (ffDBusGetUint(dbus, &dictIter, &percentage))
device->battery = (uint8_t) percentage;
}
else if(ffStrEquals(deviceProperty, "Connected"))
ffDBusGetBool(dbus, &dictIter, &device->connected);
}
@@ -86,8 +90,8 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL)
return; //We don't care about other properties
if(!ffStrContains(propertyType, ".Device") && !ffStrContains(propertyType, ".Battery"))
return; // We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
@@ -97,11 +101,10 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
while(true)
do
{
detectBluetoothValue(dbus, &arrayIter, device);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
@@ -118,8 +121,8 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We don't want adapter objects
if(strstr(objectPath, "dev_") == NULL)
// We don't want adapter objects
if(!ffStrContains(objectPath, "/dev_"))
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
@@ -137,11 +140,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
device->battery = 0;
device->connected = false;
while(true)
do
{
detectBluetoothProperty(dbus, &arrayIter, device);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
@@ -160,11 +162,10 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
while(true)
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
}
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices)
@@ -174,7 +175,7 @@ static const char* detectBluetooth(FFlist* devices)
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
if(!managedObjects)
return "Failed to call GetManagedObjects";
+13 -21
View File
@@ -15,43 +15,35 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextDevice)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindDeviceClose)
BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = {
BLUETOOTH_DEVICE_INFO btdi = {
.dwSize = sizeof(btdi)
};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) {
.fReturnConnected = TRUE,
.fReturnRemembered = TRUE,
.fReturnAuthenticated = TRUE,
.fReturnUnknown = TRUE,
.dwSize = sizeof(btsp)
};
BLUETOOTH_DEVICE_INFO btdi = {
.dwSize = sizeof(btdi)
};
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&btsp, &btdi);
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)
}, &btdi);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return "No Bluetooth devices found";
else
return "BluetoothFindFirstDevice() failed";
return "BluetoothFindFirstDevice() failed";
}
do {
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
ffStrbufSetWS(&device->name, btdi.szName);
ffStrbufAppendF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
ffStrbufInitWS(&device->name, btdi.szName);
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
btdi.Address.rgBytes[0],
btdi.Address.rgBytes[1],
btdi.Address.rgBytes[2],
btdi.Address.rgBytes[3],
btdi.Address.rgBytes[4],
btdi.Address.rgBytes[5]);
ffStrbufInit(&device->type);
device->battery = 0;
device->connected = !!btdi.fConnected;
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
if(BitTest(&btdi.ulClassofDevice, 13))
@@ -0,0 +1,112 @@
#include "bluetoothradio.h"
// https://github.com/ziglang/zig/blob/a84951465b409495095a9598db0cae745f34fa7b/lib/libc/include/any-windows-any/bthdef.h#L187-L236
#define BTH_MFG_ERICSSON 0
#define BTH_MFG_NOKIA 1
#define BTH_MFG_INTEL 2
#define BTH_MFG_IBM 3
#define BTH_MFG_TOSHIBA 4
#define BTH_MFG_3COM 5
#define BTH_MFG_MICROSOFT 6
#define BTH_MFG_LUCENT 7
#define BTH_MFG_MOTOROLA 8
#define BTH_MFG_INFINEON 9
#define BTH_MFG_CSR 10
#define BTH_MFG_SILICONWAVE 11
#define BTH_MFG_DIGIANSWER 12
#define BTH_MFG_TI 13
#define BTH_MFG_PARTHUS 14
#define BTH_MFG_BROADCOM 15
#define BTH_MFG_MITEL 16
#define BTH_MFG_WIDCOMM 17
#define BTH_MFG_ZEEVO 18
#define BTH_MFG_ATMEL 19
#define BTH_MFG_MITSIBUSHI 20
#define BTH_MFG_RTX_TELECOM 21
#define BTH_MFG_KC_TECHNOLOGY 22
#define BTH_MFG_NEWLOGIC 23
#define BTH_MFG_TRANSILICA 24
#define BTH_MFG_ROHDE_SCHWARZ 25
#define BTH_MFG_TTPCOM 26
#define BTH_MFG_SIGNIA 27
#define BTH_MFG_CONEXANT 28
#define BTH_MFG_QUALCOMM 29
#define BTH_MFG_INVENTEL 30
#define BTH_MFG_AVM_BERLIN 31
#define BTH_MFG_BANDSPEED 32
#define BTH_MFG_MANSELLA 33
#define BTH_MFG_NEC 34
#define BTH_MFG_WAVEPLUS_TECHNOLOGY_CO 35
#define BTH_MFG_ALCATEL 36
#define BTH_MFG_PHILIPS_SEMICONDUCTOR 37
#define BTH_MFG_C_TECHNOLOGIES 38
#define BTH_MFG_OPEN_INTERFACE 39
#define BTH_MFG_RF_MICRO_DEVICES 40
#define BTH_MFG_HITACHI 41
#define BTH_MFG_SYMBOL_TECHNOLOGIES 42
#define BTH_MFG_TENOVIS 43
#define BTH_MFG_MACRONIX_INTERNATIONAL 44
#define BTH_MFG_MARVELL 72
#define BTH_MFG_APPLE 76
#define BTH_MFG_NORDIC_SEMICONDUCTORS_ASA 89
#define BTH_MFG_ARUBA_NETWORKS 283
#define BTH_MFG_INTERNAL_USE 65535
const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId)
{
switch (manufacturerId)
{
case BTH_MFG_ERICSSON: return "Ericsson";
case BTH_MFG_NOKIA: return "Nokia";
case BTH_MFG_INTEL: return "Intel";
case BTH_MFG_IBM: return "IBM";
case BTH_MFG_TOSHIBA: return "Toshiba";
case BTH_MFG_3COM: return "3Com";
case BTH_MFG_MICROSOFT: return "Microsoft";
case BTH_MFG_LUCENT: return "Lucent";
case BTH_MFG_MOTOROLA: return "Motorola";
case BTH_MFG_INFINEON: return "Infineon";
case BTH_MFG_CSR: return "CSR";
case BTH_MFG_SILICONWAVE: return "Silicon-Wave";
case BTH_MFG_DIGIANSWER: return "Digi-Answer";
case BTH_MFG_TI: return "Ti";
case BTH_MFG_PARTHUS: return "Parthus";
case BTH_MFG_BROADCOM: return "Broadcom";
case BTH_MFG_MITEL: return "Mitel";
case BTH_MFG_WIDCOMM: return "Widcomm";
case BTH_MFG_ZEEVO: return "Zeevo";
case BTH_MFG_ATMEL: return "Atmel";
case BTH_MFG_MITSIBUSHI: return "Mitsubishi";
case BTH_MFG_RTX_TELECOM: return "RTX Telecom";
case BTH_MFG_KC_TECHNOLOGY: return "KC Technology";
case BTH_MFG_NEWLOGIC: return "Newlogic";
case BTH_MFG_TRANSILICA: return "Transilica";
case BTH_MFG_ROHDE_SCHWARZ: return "Rohde-Schwarz";
case BTH_MFG_TTPCOM: return "TTPCom";
case BTH_MFG_SIGNIA: return "Signia";
case BTH_MFG_CONEXANT: return "Conexant";
case BTH_MFG_QUALCOMM: return "Qualcomm";
case BTH_MFG_INVENTEL: return "Inventel";
case BTH_MFG_AVM_BERLIN: return "AVM Berlin";
case BTH_MFG_BANDSPEED: return "Bandspeed";
case BTH_MFG_MANSELLA: return "Mansella";
case BTH_MFG_NEC: return "NEC";
case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: return "Waveplus";
case BTH_MFG_ALCATEL: return "Alcatel";
case BTH_MFG_PHILIPS_SEMICONDUCTOR: return "Philips Semiconductors";
case BTH_MFG_C_TECHNOLOGIES: return "C Technologies";
case BTH_MFG_OPEN_INTERFACE: return "Open Interface";
case BTH_MFG_RF_MICRO_DEVICES: return "RF Micro Devices";
case BTH_MFG_HITACHI: return "Hitachi";
case BTH_MFG_SYMBOL_TECHNOLOGIES: return "Symbol Technologies";
case BTH_MFG_TENOVIS: return "Tenovis";
case BTH_MFG_MACRONIX_INTERNATIONAL: return "Macronix International";
case BTH_MFG_MARVELL: return "Marvell";
case BTH_MFG_APPLE: return "Apple";
case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: return "Nordic Semiconductor ASA";
case BTH_MFG_ARUBA_NETWORKS: return "Aruba Networks";
case BTH_MFG_INTERNAL_USE: return "Internal Use";
default: return "Unknown";
}
}
@@ -0,0 +1,18 @@
#pragma once
#include "fastfetch.h"
typedef struct FFBluetoothRadioResult
{
FFstrbuf name;
FFstrbuf address;
FFstrbuf vendor;
int32_t lmpVersion;
int32_t lmpSubversion;
bool enabled;
bool discoverable;
bool connectable;
} FFBluetoothRadioResult;
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */);
const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId);
@@ -0,0 +1,69 @@
#include "bluetoothradio.h"
#include "common/processing.h"
#import <IOBluetooth/IOBluetooth.h>
// For some reason the official declaration of IOBluetoothHostController don't include property `controllers`
@interface IOBluetoothHostController()
+ (id)controllers;
@end
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */)
{
NSArray<IOBluetoothHostController*>* ctrls = IOBluetoothHostController.controllers;
if(!ctrls)
return "IOBluetoothHostController.controllers returns nil";
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffProcessAppendStdOut(&buffer, (char* const[]) {
"system_profiler",
"SPBluetoothDataType",
"-xml",
"-detailLevel",
"basic",
NULL
}) != NULL)
return "Starting `system_profiler SPBluetoothDataType -xml -detailLevel basic` failed";
NSArray* arr = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytes:buffer.chars length:buffer.length]
options:NSPropertyListImmutable
format:nil
error:nil];
if (!arr || !arr.count)
return "system_profiler SPBluetoothDataType returned an empty array";
for (IOBluetoothHostController* ctrl in ctrls)
{
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String);
ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String);
ffStrbufInitStatic(&device->vendor, "Apple");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON;
device->discoverable = false;
device->connectable = true;
for (NSDictionary* itemDict in arr[0][@"_items"])
{
NSDictionary* props = itemDict[@"controller_properties"];
if (!props) continue;
if (![ctrl.addressAsString isEqualToString:props[@"controller_address"]]) continue;
NSString* services = props[@"controller_supportedServices"];
if ([services containsString:@" LEA "])
device->lmpVersion = -11;
else if ([services containsString:@" GATT "])
device->lmpVersion = -6;
device->discoverable = ![props[@"controller_discoverable"] isEqualToString:@"attrib_off"];
ffStrbufSetS(&device->vendor, ((NSString*) props[@"controller_vendorID"]).UTF8String);
ffStrbufSubstrAfterFirstC(&device->vendor, '(');
ffStrbufTrimRight(&device->vendor, ')');
break;
}
}
return NULL;
}
@@ -0,0 +1,207 @@
#include "bluetoothradio.h"
#include "util/stringUtils.h"
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
/* Example dbus reply, striped to only the relevant parts:
array [ //root
dict entry(
object path "/org/bluez/hci0"
array [
dict entry(
string "org.bluez.Adapter1"
array [
dict entry(
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "xxxxxxxx"
)
dict entry(
string "Powered"
variant boolean true
)
dict entry(
string "PowerState"
variant string "on"
)
dict entry(
string "Manufacturer"
variant uint16 2
)
dict entry(
string "Version"
variant byte 12
)
]
)
]
)
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* deviceProperty;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(ffStrEquals(deviceProperty, "Address"))
ffDBusGetString(dbus, &dictIter, &device->address);
else if(ffStrEquals(deviceProperty, "Alias"))
ffDBusGetString(dbus, &dictIter, &device->name);
else if(ffStrEquals(deviceProperty, "Manufacturer"))
{
uint32_t vendorId;
if (ffDBusGetUint(dbus, &dictIter, &vendorId))
ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(vendorId));
}
else if(ffStrEquals(deviceProperty, "Version"))
ffDBusGetUint(dbus, &dictIter, (uint32_t*) &device->lmpVersion);
else if(ffStrEquals(deviceProperty, "Powered"))
ffDBusGetBool(dbus, &dictIter, &device->enabled);
else if(ffStrEquals(deviceProperty, "Discoverable"))
ffDBusGetBool(dbus, &dictIter, &device->discoverable);
else if(ffStrEquals(deviceProperty, "Pairable"))
ffDBusGetBool(dbus, &dictIter, &device->connectable);
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
return;
const char* propertyType;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
if(!ffStrContains(propertyType, ".Adapter"))
return; //We don't care about other properties
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
do
{
detectBluetoothValue(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
DBusMessageIter dictIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
return;
const char* objectPath;
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
//We want adapter objects
if(!ffStrStartsWith(objectPath, "/org/bluez/hci") || ffStrContains(objectPath, "/dev_"))
return;
dbus->lib->ffdbus_message_iter_next(&dictIter);
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInitStatic(&device->vendor, "Unknown");
device->lmpVersion = INT_MIN;
device->lmpSubversion = INT_MIN;
device->enabled = false;
do
{
detectBluetoothProperty(dbus, &arrayIter, device);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
if(device->name.length == 0)
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->address);
--devices->length;
}
}
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return;
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
do
{
detectBluetoothObject(devices, dbus, &arrayIter);
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
}
static const char* detectBluetooth(FFlist* devices)
{
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
if(!managedObjects)
return "Failed to call GetManagedObjects";
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
{
dbus.lib->ffdbus_message_unref(managedObjects);
return "Failed to get root iterator of GetManagedObjects";
}
detectBluetoothRoot(devices, &dbus, &rootIter);
dbus.lib->ffdbus_message_unref(managedObjects);
return NULL;
}
#endif
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
#else
return "Fastfetch was compiled without DBus support";
#endif
}
@@ -0,0 +1,6 @@
#include "bluetoothradio.h"
const char* ffDetectBluetoothRadio(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothRadioResult */)
{
return "Not supported on this platform";
}
@@ -0,0 +1,105 @@
#include "bluetoothradio.h"
#include "common/library.h"
#include "common/io/io.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <bluetoothapis.h>
#include <winioctl.h>
// #include <bthioctl.h>
#define BTH_IOCTL_BASE 0
#define BTH_CTL(id) CTL_CODE(FILE_DEVICE_BLUETOOTH, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_BTH_GET_LOCAL_INFO BTH_CTL(BTH_IOCTL_BASE+0x00)
#define LMP_LE_SUPPORTED(x) ((x >> 38) & 1)
typedef struct _BTH_RADIO_INFO
{
// Supported LMP features of the radio. Use LMP_XXX() to extract
// the desired bits.
ULONGLONG lmpSupportedFeatures;
// Manufacturer ID (possibly BTH_MFG_XXX)
USHORT mfg;
// LMP subversion
USHORT lmpSubversion;
// LMP version
UCHAR lmpVersion;
} __attribute__((__packed__)) BTH_RADIO_INFO;
typedef struct _BTH_LOCAL_RADIO_INFO
{
// Local BTH_ADDR, class of device, and radio name
BTH_DEVICE_INFO localInfo;
// Combo of LOCAL_RADIO_XXX values
ULONG flags;
// HCI revision, see core spec
USHORT hciRevision;
// HCI version, see core spec
UCHAR hciVersion;
// More information about the local radio (LMP, MFG)
BTH_RADIO_INFO radioInfo;
} __attribute__((__packed__)) BTH_LOCAL_RADIO_INFO;
static_assert(sizeof(BTH_LOCAL_RADIO_INFO) == 292, "BTH_LOCAL_RADIO_INFO should be 292 bytes");
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
{
// Actually bluetoothapis.dll, but it's missing on Windows 7
FF_LIBRARY_LOAD(bluetoothapis, NULL, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsConnectable)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsDiscoverable)
HANDLE hRadio = NULL;
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstRadio(&(BLUETOOTH_FIND_RADIO_PARAMS) {
.dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS)
}, &hRadio);
if(!hFind)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return "No Bluetooth radios found or service disabled";
else
return "BluetoothFindFirstRadio() failed";
}
do {
BTH_LOCAL_RADIO_INFO blri;
DWORD returned;
if (!DeviceIoControl(hRadio, IOCTL_BTH_GET_LOCAL_INFO, NULL, 0, &blri, sizeof(blri), &returned, NULL))
continue;
FFBluetoothRadioResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, blri.localInfo.name);
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
addr.rgBytes[0],
addr.rgBytes[1],
addr.rgBytes[2],
addr.rgBytes[3],
addr.rgBytes[4],
addr.rgBytes[5]);
device->lmpVersion = blri.radioInfo.lmpVersion;
device->lmpSubversion = blri.radioInfo.lmpSubversion;
ffStrbufInitStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg));
device->enabled = true;
device->connectable = ffBluetoothIsConnectable(hRadio);
device->discoverable = ffBluetoothIsDiscoverable(hRadio);
} while (ffBluetoothFindNextRadio(hFind, &hRadio));
ffBluetoothFindRadioClose(hFind);
return NULL;
}
+2 -2
View File
@@ -5,13 +5,13 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#if __has_include(<linux/videodev2.h>)
#if FF_HAVE_LINUX_VIDEODEV2
#include <linux/videodev2.h>
#endif
const char* ffDetectCamera(FFlist* result)
{
#if __has_include(<linux/videodev2.h>)
#if FF_HAVE_LINUX_VIDEODEV2
char path[] = "/dev/videoN";
for (uint32_t i = 0; i <= 9; ++i)
+2
View File
@@ -46,6 +46,8 @@ static void detectQualcomm(FFCPUResult* cpu)
else if (ffStrbufEqualS(&cpu->name, "SM6450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6 Gen 1 [SM6450]");
else if (ffStrbufEqualS(&cpu->name, "SM4635"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4s Gen 2 [SM4635]");
else if (ffStrbufEqualS(&cpu->name, "SM4450"))
ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 2 [SM4450]");
else if (ffStrbufEqualS(&cpu->name, "SM4375"))
+1 -1
View File
@@ -123,7 +123,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
FFDisk* disk = ffListAdd(disks);
disk->bytesTotal = fs->f_blocks * fs->f_bsize;
disk->bytesTotal = (uint64_t)fs->f_blocks * fs->f_bsize;
disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize;
disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize;
disk->bytesUsed = 0; // To be filled in ./disk.c
@@ -37,7 +37,7 @@ 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);
}
}
@@ -86,21 +86,15 @@ 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;
}
CGDisplayModeRelease(mode);
}
@@ -7,9 +7,48 @@
#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)
getWMProtocolNameFromEnv(ds);
if (!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY) &&instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE)
{
//We try wayland as our preferred display server, as it supports the most features.
//This method can't detect the name of our WM / DE
@@ -57,8 +96,11 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
}
#endif
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(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,
@@ -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);
}
@@ -131,7 +131,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
rotation,
display.edidName.length
? &display.edidName
: display.description.length
: display.description.length && !ffStrbufContain(&display.description, &display.name)
? &display.description
: &display.name,
display.type,
-41
View File
@@ -240,38 +240,6 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
}
}
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
{
//This is only called if all connection attempts to a display server failed
//We don't need to check for wayland here, as the wayland code will always set the protocol name to wayland
const char* env = getenv("XDG_SESSION_TYPE");
if(ffStrSet(env))
{
if(ffStrEqualsIgnCase(env, "x11"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
else if(ffStrEqualsIgnCase(env, "tty"))
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
else
ffStrbufSetS(&result->wmProtocolName, env);
return;
}
env = getenv("DISPLAY");
if(ffStrSet(env))
{
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
return;
}
env = getenv("TERM");
if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux"))
{
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
return;
}
}
static const char* getFromProcesses(FFDisplayServerResult* result)
{
@@ -396,15 +364,6 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
void ffdsDetectWMDE(FFDisplayServerResult* result)
{
//If all connections failed, use the environment variables to detect protocol name
if(result->wmProtocolName.length == 0)
getWMProtocolNameFromEnv(result);
//We don't want to detect anything in TTY
//This can't happen if a connection succeeded, so we don't need to clear wmProcessName
if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0)
return;
const char* env = parseEnv();
if(result->wmProcessName.length > 0)
+5
View File
@@ -7,6 +7,7 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple";
const char* FF_GPU_VENDOR_NAME_AMD = "AMD";
const char* FF_GPU_VENDOR_NAME_INTEL = "Intel";
const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA";
const char* FF_GPU_VENDOR_NAME_MTHREADS = "Moore Threads";
const char* FF_GPU_VENDOR_NAME_QUALCOMM = "Qualcomm";
const char* FF_GPU_VENDOR_NAME_MTK = "MTK";
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
@@ -24,6 +25,7 @@ const char* ffGetGPUVendorString(unsigned vendorId)
case 0x1002: case 0x1022: return FF_GPU_VENDOR_NAME_AMD;
case 0x8086: case 0x8087: case 0x03e7: return FF_GPU_VENDOR_NAME_INTEL;
case 0x0955: case 0x10de: case 0x12d2: return FF_GPU_VENDOR_NAME_NVIDIA;
case 0x1ed5: return FF_GPU_VENDOR_NAME_MTHREADS;
case 0x5143: return FF_GPU_VENDOR_NAME_QUALCOMM;
case 0x14c3: return FF_GPU_VENDOR_NAME_MTK;
case 0x15ad: return FF_GPU_VENDOR_NAME_VMWARE;
@@ -56,6 +58,7 @@ const char* detectByOpenGL(FFlist* gpus)
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0};
gpu->deviceId = 0;
@@ -70,6 +73,8 @@ const char* detectByOpenGL(FFlist* gpus)
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
else if (ffStrbufContainS(&gpu->name, "MTT"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
}
+3
View File
@@ -6,11 +6,13 @@
#define FF_GPU_CORE_COUNT_UNSET -1
#define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1)
#define FF_GPU_FREQUENCY_UNSET 0
#define FF_GPU_CORE_USAGE_UNSET (0/0.0)
extern const char* FF_GPU_VENDOR_NAME_APPLE;
extern const char* FF_GPU_VENDOR_NAME_AMD;
extern const char* FF_GPU_VENDOR_NAME_INTEL;
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
extern const char* FF_GPU_VENDOR_NAME_MTHREADS;
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
@@ -35,6 +37,7 @@ typedef struct FFGPUResult
uint32_t frequency; // Maximum time clock frequency in MHz
FFGPUMemory dedicated;
FFGPUMemory shared;
double coreUsage;
uint64_t deviceId; // Used internally, may be uninitialized
} FFGPUResult;
+43 -3
View File
@@ -76,8 +76,12 @@ static const char* detectFrequency(FFGPUResult* gpu)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
{
CFMutableDictionaryRef matches = IOServiceMatching(kIOAcceleratorClassName);
CFDictionaryAddValue(matches, CFSTR("IOMatchCategory"), CFSTR(kIOAcceleratorClassName));
if (IOServiceGetMatchingServices(MACH_PORT_NULL, matches, &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
}
io_registry_entry_t registryEntry;
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
@@ -103,6 +107,31 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = 0.0/0.0;
CFDictionaryRef perfStatistics = NULL;
uint64_t vramUsed = 0, vramTotal = 0;
if (ffCfDictGetDict(properties, CFSTR("PerformanceStatistics"), &perfStatistics) == NULL)
{
int64_t utilization;
if (ffCfDictGetInt64(perfStatistics, CFSTR("Device Utilization %"), &utilization) == NULL)
gpu->coreUsage = (double) utilization;
else if (ffCfDictGetInt64(perfStatistics, CFSTR("GPU Core Utilization"), &utilization) == NULL)
gpu->coreUsage = (double) utilization / 10000000.; // Nvidia?
if (ffCfDictGetInt64(perfStatistics, CFSTR("Alloc system memory"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("In use system memory"), (int64_t*) &vramUsed) != NULL)
vramTotal = 0;
}
else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramTotal) == NULL)
{
if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramUsed) == NULL)
vramTotal += vramUsed;
else
vramTotal = 0;
}
}
ffStrbufInit(&gpu->name);
//IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs.
//Still needs testing for AMD's
@@ -123,7 +152,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
ffStrbufInit(&gpu->vendor);
int vendorId;
if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId))
if(ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL)
{
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
ffStrbufAppendS(&gpu->vendor, vendorStr);
@@ -136,6 +165,17 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE)
detectFrequency(gpu);
#endif
if (gpu->type == FF_GPU_TYPE_INTEGRATED)
{
gpu->shared.total = vramTotal;
gpu->shared.used = vramUsed;
}
else
{
gpu->dedicated.total = vramTotal;
gpu->dedicated.used = vramUsed;
}
}
gpu->temperature = options->temp ? detectGpuTemp(&gpu->name) : FF_GPU_TEMP_UNSET;
-11
View File
@@ -44,17 +44,6 @@ const char* ffGpuDetectMetal(FFlist* gpus)
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#endif
if (gpu->type == FF_GPU_TYPE_INTEGRATED)
{
gpu->shared.total = device.recommendedMaxWorkingSetSize;
gpu->shared.used = device.currentAllocatedSize;
}
else
{
gpu->dedicated.total = device.recommendedMaxWorkingSetSize;
gpu->dedicated.used = device.currentAllocatedSize;
}
}
return NULL;
}
+22 -2
View File
@@ -57,6 +57,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;
@@ -92,10 +93,29 @@ 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)
{
gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
}
}
}
+53
View File
@@ -40,10 +40,63 @@ typedef struct FFGpuDriverResult
double* temp;
FFGPUMemory* memory;
uint32_t* coreCount;
double* coreUsage;
FFGPUType* type;
uint32_t* frequency;
FFstrbuf* name;
} FFGpuDriverResult;
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName);
FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
{
*pDetectFn = ffDetectNvidiaGpuInfo;
#ifdef _WIN32
*pDllName = "nvml.dll";
#else
*pDllName = "libnvidia-ml.so";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_MTHREADS)
{
*pDetectFn = ffDetectMthreadsGpuInfo;
#ifdef _WIN32
*pDllName = "mtml.dll";
#else
*pDllName = "libmtml.so";
#endif
}
#ifdef _WIN32
else if (vendor == FF_GPU_VENDOR_NAME_INTEL)
{
*pDetectFn = ffDetectIntelGpuInfo;
#ifdef _WIN64
*pDllName = "ControlLib.dll";
#else
*pDllName = "ControlLib32.dll";
#endif
}
else if (vendor == FF_GPU_VENDOR_NAME_AMD)
{
*pDetectFn = ffDetectAmdGpuInfo;
#ifdef _WIN64
*pDllName = "amd_ags_x64.dll";
#else
*pDllName = "amd_ags_x86.dll";
#endif
}
#endif
else
{
*pDetectFn = NULL;
*pDllName = NULL;
return false;
}
return true;
}
+112 -32
View File
@@ -7,29 +7,90 @@
#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
#if __has_include(<drm/asahi_drm.h>)
#include <drm/asahi_drm.h>
#else
/* SPDX-License-Identifier: MIT */
/* Copyright (C) The Asahi Linux Contributors */
#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_shader_start;
__u64 vm_shader_end;
__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;
};
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
#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 +106,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");
@@ -212,14 +284,6 @@ 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);
@@ -279,11 +343,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
pciDetectIntelSpecific(gpu, deviceDir, buffer);
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 +361,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 +404,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);
@@ -354,6 +433,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F
return NULL;
}
#endif
static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
{
+198
View File
@@ -0,0 +1,198 @@
#include "gpu_driver_specific.h"
#include "common/library.h"
#include "mtml.h"
struct FFMtmlData
{
FF_LIBRARY_SYMBOL(mtmlDeviceGetBrand)
FF_LIBRARY_SYMBOL(mtmlDeviceGetIndex)
FF_LIBRARY_SYMBOL(mtmlDeviceGetName)
FF_LIBRARY_SYMBOL(mtmlDeviceGetPciInfo)
FF_LIBRARY_SYMBOL(mtmlDeviceGetUUID)
FF_LIBRARY_SYMBOL(mtmlDeviceInitGpu)
FF_LIBRARY_SYMBOL(mtmlDeviceInitMemory)
FF_LIBRARY_SYMBOL(mtmlGpuGetMaxClock)
FF_LIBRARY_SYMBOL(mtmlGpuGetTemperature)
FF_LIBRARY_SYMBOL(mtmlGpuGetUtilization)
FF_LIBRARY_SYMBOL(mtmlLibraryCountDevice)
FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByIndex)
FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByPciSbdf)
FF_LIBRARY_SYMBOL(mtmlLibraryInitSystem)
FF_LIBRARY_SYMBOL(mtmlMemoryGetTotal)
FF_LIBRARY_SYMBOL(mtmlMemoryGetUsed)
FF_LIBRARY_SYMBOL(mtmlMemoryGetUtilization)
FF_LIBRARY_SYMBOL(mtmlLibraryShutDown)
bool inited;
MtmlLibrary *lib;
MtmlSystem *sys;
} mtmlData;
static void shutdownMtml()
{
mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
}
const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDriverResult result, const char *soName)
{
#ifndef FF_DISABLE_DLOPEN
if (!mtmlData.inited)
{
mtmlData.inited = true;
FF_LIBRARY_LOAD(libmtml, NULL, "dlopen mtml failed", soName, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryInit)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetBrand)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetIndex)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetName)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetPciInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetUUID)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitGpu)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitMemory)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetMaxClock)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetTemperature)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetUtilization)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryCountDevice)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByIndex)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByPciSbdf)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitSystem)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetTotal)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUsed)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUtilization)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryShutDown)
if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS)
{
mtmlData.ffmtmlLibraryInitSystem = NULL;
return "mtmlLibraryInit failed";
}
if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS)
{
mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
mtmlData.ffmtmlLibraryInitSystem = NULL;
return "mtmlLibraryInitSystem failed";
}
atexit(shutdownMtml);
libmtml = NULL; // don't close mtml
}
if (mtmlData.ffmtmlLibraryInitSystem == NULL)
return "loading mtml library failed";
MtmlDevice *device = NULL;
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
{
char pciBusIdStr[32];
snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
MtmlReturn ret = mtmlData.ffmtmlLibraryInitDeviceByPciSbdf(mtmlData.lib, pciBusIdStr, &device);
if (ret != MTML_SUCCESS)
return "mtmlLibraryInitDeviceByPciSbdf() failed";
}
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
{
uint32_t count;
if (mtmlData.ffmtmlLibraryCountDevice(mtmlData.lib, &count) != MTML_SUCCESS)
return "mtmlLibraryCountDevice() failed";
for (uint32_t i = 0; i < count; i++, device = NULL)
{
if (mtmlData.ffmtmlLibraryInitDeviceByIndex(mtmlData.lib, i, &device) != MTML_SUCCESS)
continue;
MtmlPciInfo pciInfo;
if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) != MTML_SUCCESS)
continue;
if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
pciInfo.pciSubsystemId != cond->pciDeviceId.subSystemId)
continue;
break;
}
if (!device)
return "Device not found";
}
else
{
return "Unknown condition type";
}
MtmlBrandType brand;
if (mtmlData.ffmtmlDeviceGetBrand(device, &brand) == MTML_SUCCESS)
{
switch (brand)
{
case MTML_BRAND_MTT:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
}
}
if (result.temp)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
uint32_t value;
if (mtmlData.ffmtmlGpuGetTemperature(gpu, &value) == MTML_SUCCESS)
*result.temp = value;
}
}
if (result.memory)
{
MtmlMemory *mem = NULL;
if (mtmlData.ffmtmlDeviceInitMemory(device, &mem) == MTML_SUCCESS)
{
unsigned long long total;
if (mtmlData.ffmtmlMemoryGetTotal(mem, &total) == MTML_SUCCESS)
result.memory->total = total;
unsigned long long used;
if (mtmlData.ffmtmlMemoryGetUsed(mem, &used) == MTML_SUCCESS)
result.memory->used = used;
}
}
if (result.frequency)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
uint32_t clockMHz;
if (mtmlData.ffmtmlGpuGetMaxClock(gpu, &clockMHz) == MTML_SUCCESS)
*result.frequency = clockMHz;
}
}
if (result.coreUsage)
{
MtmlGpu *gpu = NULL;
if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS)
{
unsigned int utilization;
if (mtmlData.ffmtmlGpuGetUtilization(gpu, &utilization) == MTML_SUCCESS)
*result.coreUsage = utilization;
}
}
if (result.name)
{
char name[MTML_DEVICE_NAME_BUFFER_SIZE];
if (mtmlData.ffmtmlDeviceGetName(device, name, sizeof(name)) == MTML_SUCCESS)
ffStrbufSetS(result.name, name);
}
return NULL;
#else
FF_UNUSED(cond, result, soName);
return "dlopen is disabled";
#endif
}
+18
View File
@@ -12,7 +12,9 @@ struct FFNvmlData {
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates)
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
FF_LIBRARY_SYMBOL(nvmlDeviceGetName)
bool inited;
} nvmlData;
@@ -35,7 +37,9 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetName)
if (ffnvmlInit_v2() != NVML_SUCCESS)
{
@@ -124,6 +128,20 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
if (result.frequency)
nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency);
if (result.coreUsage)
{
nvmlUtilization_t utilization;
if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &utilization) == NVML_SUCCESS)
*result.coreUsage = utilization.gpu;
}
if (result.name)
{
char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE];
if (nvmlData.ffnvmlDeviceGetName(device, name, sizeof(name)) == NVML_SUCCESS)
ffStrbufSetS(result.name, name);
}
return NULL;
#else
+1
View File
@@ -59,6 +59,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
ffStrbufInit(&gpu->platformApi);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->type = FF_GPU_TYPE_UNKNOWN;
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = 0;
+96 -104
View File
@@ -3,140 +3,118 @@
#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;
}
return true;
}
#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}"
#define FF_GUID_STRLEN (sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1)
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";
wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR;
const uint32_t regDirectxKeyPrefixLength = (uint32_t) strlen("SOFTWARE\\Microsoft\\DirectX\\");
wchar_t regControlVideoKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\" FF_EMPTY_GUID_STR L"\\0000";
const uint32_t regControlVideoKeyPrefixLength = (uint32_t) strlen("SYSTEM\\CurrentControlSet\\Control\\Video\\");
SP_DEVINFO_DATA did = { .cbSize = sizeof(did) };
for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev)
{
if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue;
wchar_t hardwareId[256];
if (!SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) hardwareId, sizeof(hardwareId), NULL))
continue;
const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey);
if (__builtin_expect(deviceKeyLength == 100, true))
wchar_t videoId[39];
{
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;
FF_HKEY_AUTO_DESTROY hKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
if (!hKey) continue;
DWORD videoIdLength = sizeof(videoId);
if (RegGetValueW(hKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, videoId, &videoIdLength) != ERROR_SUCCESS || videoIdLength != (FF_GUID_STRLEN + 1) * sizeof(wchar_t))
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"
wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, videoId, FF_GUID_STRLEN);
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue;
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);
swscanf(hardwareId, 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->name);
ffStrbufInit(&gpu->driver);
ffStrbufInitStatic(&gpu->platformApi, "Direct3D");
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] == '{')
if (!ffRegReadStrbuf(hKey, L"DriverDesc", &gpu->name, NULL)) // faster, for some reason
{
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;
wchar_t name[256];
if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) name, sizeof(name), NULL))
ffStrbufSetWS(&gpu->name, name);
}
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL);
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, videoId, FF_GUID_STRLEN);
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
{
uint64_t dedicatedVideoMemory = 0;
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}"));
FF_HKEY_AUTO_DESTROY hDirectxKey = NULL;
if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL))
uint64_t dedicatedSystemMemory, sharedSystemMemory;
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
{
uint64_t dedicatedVideoMemory = 0;
if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL))
gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
uint64_t dedicatedSystemMemory, sharedSystemMemory;
if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) &&
ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL))
{
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
gpu->shared.total = sharedSystemMemory;
}
ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL);
uint32_t featureLevel = 0;
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
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;
gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory;
gpu->shared.total = sharedSystemMemory;
}
if (gpu->vendor.length == 0)
{
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);
}
ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL);
uint32_t featureLevel = 0;
if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel)
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)
{
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);
}
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
@@ -144,23 +122,37 @@ 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)
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)
| FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
.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,
},
+4
View File
@@ -71,8 +71,10 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitS(&gpu->name, desc);
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->deviceId = 0;
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
ffStrbufInit(&gpu->driver);
@@ -119,8 +121,10 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
.temp = options->temp ? &gpu->temperature : NULL,
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
.type = &gpu->type,
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
.name = options->driverSpecific ? &gpu->name : NULL,
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
}
}
+116
View File
@@ -0,0 +1,116 @@
#pragma once
// DISCLAIMER:
// THIS FILE IS CREATED FROM SCRATCH, BY READING THE OFFICIAL MTML API
// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT.
#define MTML_API __attribute__((visibility("default")))
#define MTML_DEVICE_PCI_SBDF_BUFFER_SIZE 32
#define MTML_DEVICE_NAME_BUFFER_SIZE 32
#define MTML_DEVICE_UUID_BUFFER_SIZE 48
/**
* Return values for MTML API calls.
*/
typedef enum
{
MTML_SUCCESS = 0,
} MtmlReturn;
/**
* The brand of the device.
*/
typedef enum
{
MTML_BRAND_MTT = 0, //!< MTT series.
MTML_BRAND_UNKNOWN, //!< An unknown brand.
// Keep this on the last line.
MTML_BRAND_COUNT //!< The number of brands.
} MtmlBrandType;
typedef struct MtmlLibrary MtmlLibrary;
typedef struct MtmlSystem MtmlSystem;
typedef struct MtmlDevice MtmlDevice;
typedef struct MtmlGpu MtmlGpu;
typedef struct MtmlMemory MtmlMemory;
/**
* PCI information about a device.
*/
typedef struct
{
char sbdf[MTML_DEVICE_PCI_SBDF_BUFFER_SIZE]; //!< The tuple segment:bus:device.function PCI identifier (&amp; NULL terminator).
unsigned int segment; //!< The PCI segment group(domain) on which the device's bus resides, 0 to 0xffffffff.
unsigned int bus; //!< The bus on which the device resides, 0 to 0xff.
unsigned int device; //!< The device ID on the bus, 0 to 31.
unsigned int pciDeviceId; //!< The combined 16-bit device ID and 16-bit vendor ID.
unsigned int pciSubsystemId; //!< The 32-bit sub system device ID.
unsigned int busWidth; //!< @deprecated This value set to zero.
float pciMaxSpeed; //!< The maximum link speed (transfer rate per lane) of the device. The unit is GT/s.
float pciCurSpeed; //!< The current link speed (transfer rate per lane) of the device. The unit is GT/s.
unsigned int pciMaxWidth; //!< The maximum link width of the device.
unsigned int pciCurWidth; //!< The current link width of the device.
unsigned int pciMaxGen; //!< The maximum supported generation of the device.
unsigned int pciCurGen; //!< The current generation of the device.
int rsvd[6]; //!< Reserved for future extension.
} MtmlPciInfo;
// Retrieves the brand of a device.
MtmlReturn MTML_API mtmlDeviceGetBrand(const MtmlDevice *dev, MtmlBrandType *type);
// Retrieves the index associated with the specified device.
MtmlReturn MTML_API mtmlDeviceGetIndex(const MtmlDevice *dev, unsigned int *index);
// Retrieves the name of a device.
MtmlReturn MTML_API mtmlDeviceGetName(const MtmlDevice *dev, char *name, unsigned int length);
// Retrieves the PCI attributes of a device.
MtmlReturn MTML_API mtmlDeviceGetPciInfo(const MtmlDevice *dev, MtmlPciInfo *pci);
/**
* Retrieves the UUID of a specified device. The UUID is a hexadecimal string in the
* form of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where each 'x' is an ASCII character that represents a hexadecimal
* digit. The UUID is globally unique for every single device thus can be used to identify different devices
* physically.
*/
MtmlReturn MTML_API mtmlDeviceGetUUID(const MtmlDevice *dev, char *uuid, unsigned int length);
// Initializes a GPU opaque object to represent a specific graphic core on the target device that is designated by its index.
MtmlReturn MTML_API mtmlDeviceInitGpu(const MtmlDevice *dev, MtmlGpu **gpu);
// Initializes a memory opaque object to represent the memory on the target device.
MtmlReturn MTML_API mtmlDeviceInitMemory(const MtmlDevice *dev, MtmlMemory **mem);
// Retrieves the maximum supported clock speed for the device's graphic core.
MtmlReturn MTML_API mtmlGpuGetMaxClock(const MtmlGpu *gpu, unsigned int *clockMhz);
// Retrieves the current temperature readings for the device's graphic core, in degrees Celsius.
MtmlReturn MTML_API mtmlGpuGetTemperature(const MtmlGpu *gpu, unsigned int *temp);
// Retrieves the current utilization rate for the device's graphic core.
MtmlReturn MTML_API mtmlGpuGetUtilization(const MtmlGpu *gpu, unsigned int *utilization);
// Retrieves the number of devices that can be accessed by the library opaque object.
MtmlReturn MTML_API mtmlLibraryCountDevice(const MtmlLibrary *lib, unsigned int *count);
/**
* Initializes a device opaque object to represent a device that is designated by its index.
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
*/
MtmlReturn MTML_API mtmlLibraryInit(MtmlLibrary **lib);
/**
* Initializes a device opaque object to represent a device that is designated by its index.
* The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice().
*/
MtmlReturn MTML_API mtmlLibraryInitDeviceByIndex(const MtmlLibrary *lib, unsigned int index, MtmlDevice **dev);
/**
* Initializes a device opaque object to represent a device that is designated by its PCI Sbdf.
* The PCI Sbdf format like 00000000:3a:00.0 refer to \ref MtmlPciInfo::sbdf.
*/
MtmlReturn MTML_API mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary *lib, const char *pciSbdf, MtmlDevice **dev);
// Initializes a MtmlSystem opaque pointer that is bound to a library opaque object.
MtmlReturn MTML_API mtmlLibraryInitSystem(const MtmlLibrary *lib, MtmlSystem **sys);
/**
* Shuts down the library opaque object that is previously initialized by \ref mtmlLibraryInit() and releases its resources.
* The \a lib pointer cannot be used anymore after this function returns.
*/
MtmlReturn MTML_API mtmlLibraryShutDown(MtmlLibrary *lib);
// Retrieves the amount of total memory available on the device, in bytes.
MtmlReturn MTML_API mtmlMemoryGetTotal(const MtmlMemory *mem, unsigned long long *total);
// Retrieves the amount of used memory on the device, in bytes.
MtmlReturn MTML_API mtmlMemoryGetUsed(const MtmlMemory *mem, unsigned long long *used);
// Retrieves the current memory utilization rate for the device.
MtmlReturn MTML_API mtmlMemoryGetUtilization(const MtmlMemory *mem, unsigned int *utilization);
+15
View File
@@ -7,6 +7,7 @@
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceStructs.html
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE 32
#define NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE 16
#define NVML_DEVICE_NAME_V2_BUFFER_SIZE 96
typedef enum { NVML_SUCCESS = 0 } nvmlReturn_t;
typedef struct nvmlDevice_t* nvmlDevice_t;
@@ -94,6 +95,16 @@ typedef enum {
NVML_BRAND_COUNT,
} nvmlBrandType_t;
// https://docs.nvidia.com/deploy/nvml-api/structnvmlUtilization__t.html#structnvmlUtilization__t
// Utilization information for a device.
typedef struct
{
// Percent of time over the past second during which one or more kernels was executing on the GPU
unsigned int gpu;
// Percent of time over the past second during which global (device) memory was being read or written
unsigned int memory;
} nvmlUtilization_t;
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlInitializationAndCleanup.html#group__nvmlInitializationAndCleanup
// Initialize NVML, but don't initialize any GPUs yet
nvmlReturn_t nvmlInit_v2(void);
@@ -119,3 +130,7 @@ extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int*
extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int* clock);
// Retrieves the brand of this device
extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type);
// Retrieves the current utilization rates for the device
extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization);
// Retrieves the name of this device.
extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length);
+14 -5
View File
@@ -11,6 +11,13 @@
#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 +68,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 +92,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 +128,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;
+1
View File
@@ -81,6 +81,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
gpu->deviceId = (size_t) deviceID;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS)
{
@@ -23,6 +23,12 @@ static inline const char* getVendorString(unsigned vendorId)
void FFPhysicalMemoryUpdateVendorString(FFPhysicalMemoryResult* device)
{
if (ffStrbufEqualS(&device->vendor, "Unknown"))
{
ffStrbufClear(&device->vendor);
return;
}
char vendorIdStr[5];
if (ffStrbufStartsWithS(&device->vendor, "0x"))
{
@@ -75,10 +75,10 @@ const char* ffDetectPhysicalMemory(FFlist* result)
if (!data)
return "Memory device is not found in SMBIOS data";
for (; data->Header.Type == FF_SMBIOS_TYPE_MEMORY_DEVICE;
data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header))
for (; data->Header.Type < FF_SMBIOS_TYPE_END_OF_TABLE;
data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header))
{
if (data->Size == 0) continue;
if (data->Header.Type != FF_SMBIOS_TYPE_MEMORY_DEVICE || data->Size == 0) continue;
const char* strings = (const char*) data + data->Header.Length;
+2 -24
View File
@@ -200,28 +200,6 @@ static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
NULL
}) == NULL;
}
#else
static bool getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
{
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreate();
ffStrbufAppendS(&command, "printf \"%s\" \"$");
ffStrbufAppendTransformS(&command, exeName, toupper);
ffStrbufAppendS(&command, "_VERSION\"");
if (ffProcessAppendStdOut(version, (char* const[]) {
"env",
"-i",
exe->chars,
"-c",
command.chars,
NULL
}) != NULL)
return false;
ffStrbufSubstrBeforeFirstC(version, '(');
ffStrbufRemoveStrings(version, 2, (const char*[]) { "-release", "release" });
return true;
}
#endif
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
@@ -261,9 +239,9 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
return getShellVersionWinPowerShell(exe, version);
return getFileVersion(exe->chars, version);
#else
return getShellVersionGeneric(exe, exeName, version);
#endif
return false;
}
FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version)
@@ -42,7 +42,6 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "sudo") ||
ffStrbufEqualS(&result->processName, "su") ||
ffStrbufEqualS(&result->processName, "strace") ||
ffStrbufEqualS(&result->processName, "sshd") ||
ffStrbufEqualS(&result->processName, "gdb") ||
ffStrbufEqualS(&result->processName, "lldb") ||
ffStrbufEqualS(&result->processName, "lldb-mi") ||
@@ -51,7 +50,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "perf") ||
ffStrbufEqualS(&result->processName, "guake-wrapped") ||
ffStrbufEqualS(&result->processName, "time") ||
ffStrbufEqualS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend
ffStrbufContainS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend
ffStrbufEqualS(&result->processName, "clifm") || //https://github.com/leo-arch/clifm/issues/289
ffStrbufEqualS(&result->processName, "valgrind") ||
ffStrbufEqualS(&result->processName, "fastfetch") || //994
@@ -102,7 +101,6 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
ffStrbufEqualS(&result->processName, "oil.ovm") ||
ffStrbufEqualS(&result->processName, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
ffStrbufEqualS(&result->processName, "login") ||
ffStrbufEqualS(&result->processName, "sshd") ||
ffStrbufEqualS(&result->processName, "clifm") || // https://github.com/leo-arch/clifm/issues/289
ffStrbufEqualS(&result->processName, "chezmoi") || // #762
#ifdef __linux__
@@ -314,6 +312,8 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
ffStrbufInitStatic(&result->prettyName, "tmux");
else if(ffStrbufStartsWithS(&result->processName, "screen-"))
ffStrbufInitStatic(&result->prettyName, "screen");
else if(ffStrbufEqualS(&result->processName, "sshd") || ffStrbufStartsWithS(&result->processName, "sshd-"))
ffStrbufInitCopy(&result->prettyName, &result->tty);
#if defined(__ANDROID__)
@@ -53,7 +53,6 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
if(
ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "su") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables
@@ -155,7 +154,7 @@ static bool getTerminalFromEnv(FFTerminalResult* result)
}
//SSH
if(getenv("SSH_CONNECTION") != NULL)
if(getenv("SSH_TTY") != NULL)
term = getenv("SSH_TTY");
//Windows Terminal
@@ -315,6 +314,11 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
ffStrbufSetStatic(&result->prettyName, "Windows Explorer");
else if(ffStrbufEqualS(&result->prettyName, "wezterm-gui"))
ffStrbufSetStatic(&result->prettyName, "WezTerm");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || ffStrbufStartsWithIgnCaseS(&result->prettyName, "sshd-"))
{
const char* tty = getenv("SSH_TTY");
if (tty) ffStrbufSetS(&result->prettyName, tty);
}
}
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
+1 -1
View File
@@ -1,7 +1,7 @@
#include "fastfetch.h"
#include "users.h"
#if __has_include(<utmpx.h>)
#if FF_HAVE_UTMPX
#include <utmpx.h>
#else
//for Android compatibility
+1
View File
@@ -237,6 +237,7 @@ static const char* detectVulkan(FFVulkanResult* result)
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
next:
continue;
+1 -1
View File
@@ -12,7 +12,7 @@ struct FFWifiConnection
{
FFstrbuf status;
FFstrbuf ssid;
FFstrbuf macAddress;
FFstrbuf bssid;
FFstrbuf protocol;
FFstrbuf security;
double signalQuality; // Percentage
+4 -4
View File
@@ -37,7 +37,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -53,12 +53,12 @@ const char* ffDetectWifi(FFlist* result)
if(!ffStrbufEqualS(&item->inf.status, "COMPLETED"))
return NULL;
double rssi = yyjson_get_num(yyjson_obj_get(root, "rssi"));
item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2;
ffStrbufAppendS(&item->inf.description, yyjson_get_str(yyjson_obj_get(root, "ip")));
ffStrbufAppendS(&item->conn.macAddress, yyjson_get_str(yyjson_obj_get(root, "bssid")));
ffStrbufAppendS(&item->conn.bssid, yyjson_get_str(yyjson_obj_get(root, "bssid")));
ffStrbufAppendS(&item->conn.ssid, yyjson_get_str(yyjson_obj_get(root, "ssid")));
return NULL;
+14 -18
View File
@@ -6,21 +6,17 @@
struct Apple80211; // https://code.google.com/archive/p/iphone-wireless/wikis/Apple80211.wiki
// 0 is successful; < 0 is failure
int Apple80211Open(struct Apple80211 **handle) __attribute__((weak_import));
int Apple80211BindToInterface(struct Apple80211 *handle, CFStringRef interface) __attribute__((weak_import));
int Apple80211GetInfoCopy(struct Apple80211 *handle, CFDictionaryRef *info) __attribute__((weak_import));
int Apple80211Close(struct Apple80211 *handle) __attribute__((weak_import));
static NSDictionary* getWifiInfoByApple80211(NSString* ifName)
@interface CWInterface()
@property (readonly) struct Apple80211* device;
@end
static NSDictionary* getWifiInfoByApple80211(CWInterface* inf)
{
if (!Apple80211Open || !Apple80211BindToInterface || !Apple80211GetInfoCopy || !Apple80211Close) return NULL;
struct Apple80211* handle = NULL;
if (Apple80211Open(&handle) < 0) return NULL;
if (Apple80211BindToInterface(handle, (__bridge CFStringRef)ifName) < 0) return NULL;
CFDictionaryRef result;
if (Apple80211GetInfoCopy(handle, &result) < 0) return NULL;
Apple80211Close(handle);
if (!Apple80211GetInfoCopy) return NULL;
CFDictionaryRef result = NULL;
if (Apple80211GetInfoCopy(inf.device, &result) < 0) return NULL;
return CFBridgingRelease(result);
}
@@ -37,7 +33,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -57,15 +53,15 @@ const char* ffDetectWifi(FFlist* result)
if (inf.ssid) // https://developer.apple.com/forums/thread/732431
ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String);
else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName)))
else if (apple || (apple = getWifiInfoByApple80211(inf)))
ffStrbufAppendS(&item->conn.ssid, [[apple valueForKey:@"SSID_STR"] UTF8String]);
else
ffStrbufSetStatic(&item->conn.ssid, "<unknown ssid>"); // https://developer.apple.com/forums/thread/732431
if (inf.bssid)
ffStrbufAppendS(&item->conn.macAddress, inf.bssid.UTF8String);
else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName)))
ffStrbufAppendS(&item->conn.macAddress, [[apple valueForKey:@"BSSID"] UTF8String]);
ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String);
else if (apple || (apple = getWifiInfoByApple80211(inf)))
ffStrbufAppendS(&item->conn.bssid, [[apple valueForKey:@"BSSID"] UTF8String]);
switch(inf.activePHYMode)
{
@@ -152,7 +148,7 @@ const char* ffDetectWifi(FFlist* result)
break;
case kCWSecurityUnknown:
// Sonoma...
if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName)))
if (apple || (apple = getWifiInfoByApple80211(inf)))
{
NSDictionary* authType = [apple valueForKey:@"AUTH_TYPE"];
if (authType)
+2 -2
View File
@@ -28,7 +28,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -42,7 +42,7 @@ const char* ffDetectWifi(FFlist* result)
if (ibssid < item->conn.ssid.length)
{
ibssid += (uint32_t) strlen(" bssid ");
ffStrbufSetS(&item->conn.macAddress, item->conn.ssid.chars + ibssid);
ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + ibssid);
}
ffStrbufSubstrBeforeFirstC(&item->conn.ssid, ' ');
+226 -260
View File
@@ -1,184 +1,95 @@
#include "wifi.h"
#include "util/stringUtils.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef FF_HAVE_LIBNM
#include "common/dbus.h"
#include "common/processing.h"
#include "common/properties.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include <glib.h>
#define NM_NO_INCLUDE_EXTRA_HEADERS 1
#include <NetworkManager.h>
#include <net/if.h>
//https://developer-old.gnome.org/libnm/stable/libnm-nm-dbus-interface.html
#ifndef NM_VERSION_1_26
#define NM_802_11_AP_SEC_KEY_MGMT_OWE 0x00000800
#define NM_802_11_AP_SEC_KEY_MGMT_OWE_TM 0x00001000
#endif
#ifdef FF_HAVE_DBUS
// https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApFlags
typedef enum {
NM_802_11_AP_FLAGS_NONE = 0x00000000,
NM_802_11_AP_FLAGS_PRIVACY = 0x00000001,
NM_802_11_AP_FLAGS_WPS = 0x00000002,
NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004,
NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008,
} NM80211ApFlags;
static const char* detectWifiWithLibnm(FFlist* result)
// https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApSecurityFlags
typedef enum {
NM_802_11_AP_SEC_NONE = 0x00000000,
NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001,
NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002,
NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004,
NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008,
NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010,
NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020,
NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040,
NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080,
NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100,
NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200,
NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400,
NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800,
NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000,
NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000,
} NM80211ApSecurityFlags;
static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer)
{
FF_LIBRARY_LOAD(nm, &instance.config.library.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_new);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_get_devices);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_iface);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_state);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_type);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_active_access_point);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_ssid);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_utils_ssid_to_utf8);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_bssid);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_strength);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_max_bitrate);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_flags);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_wpa_flags);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_rsn_flags);
FFDBusData dbus;
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
if(error)
return error;
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_type_check_instance_is_a);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_size);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_data);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_free);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_object_unref);
NMClient* client = ffnm_client_new(NULL, NULL);
if(!client)
return "Could not create NMClient";
/* Get all devices managed by NetworkManager */
const GPtrArray* devices = ffnm_client_get_devices(client);
/* Go through the array and process Wi-Fi devices */
for (guint i = 0; i < devices->len; i++)
{
NMDevice *device = g_ptr_array_index(devices, i);
if (!({
GTypeInstance *inst = (GTypeInstance*) device;
GType type = ffnm_device_wifi_get_type();
gboolean return_value;
if (!inst)
return_value = FALSE;
else if (inst->g_class && inst->g_class->g_type == type)
return_value = TRUE;
else
return_value = ffg_type_check_instance_is_a (inst, type);
return_value;
}) //NM_IS_DEVICE_WIFI(device)
)
continue;
DBusMessage* device = ffDBusGetMethodReply(&dbus, "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", "GetDeviceByIpIface", item->inf.description.chars);
if(!device)
return "Failed to call GetDeviceByIpIface";
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
ffStrbufInit(&item->inf.description);
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
ffStrbufAppendS(&item->inf.description, ffnm_device_get_iface(device));
NMDeviceState state = ffnm_device_get_state(device);
switch(state)
ffStrbufClear(buffer);
DBusMessageIter rootIter;
if(!dbus.lib->ffdbus_message_iter_init(device, &rootIter) || !ffDBusGetString(&dbus, &rootIter, buffer))
{
case NM_DEVICE_STATE_UNKNOWN:
ffStrbufSetStatic(&item->inf.status, "Unknown");
break;
case NM_DEVICE_STATE_UNMANAGED:
ffStrbufSetStatic(&item->inf.status, "Unmanaged");
break;
case NM_DEVICE_STATE_UNAVAILABLE:
ffStrbufSetStatic(&item->inf.status, "Unavailable");
break;
case NM_DEVICE_STATE_DISCONNECTED:
ffStrbufSetStatic(&item->inf.status, "Disconnected");
break;
case NM_DEVICE_STATE_PREPARE:
ffStrbufSetStatic(&item->inf.status, "Prepare");
break;
case NM_DEVICE_STATE_CONFIG:
ffStrbufSetStatic(&item->inf.status, "Config");
break;
case NM_DEVICE_STATE_NEED_AUTH:
ffStrbufSetStatic(&item->inf.status, "Need auth");
break;
case NM_DEVICE_STATE_IP_CONFIG:
ffStrbufSetStatic(&item->inf.status, "IP config");
break;
case NM_DEVICE_STATE_IP_CHECK:
ffStrbufSetStatic(&item->inf.status, "IP check");
break;
case NM_DEVICE_STATE_SECONDARIES:
ffStrbufSetStatic(&item->inf.status, "Secondaries");
break;
case NM_DEVICE_STATE_ACTIVATED:
ffStrbufSetStatic(&item->inf.status, "Activated");
break;
case NM_DEVICE_STATE_DEACTIVATING:
ffStrbufSetStatic(&item->inf.status, "Deactivating");
break;
case NM_DEVICE_STATE_FAILED:
ffStrbufSetStatic(&item->inf.status, "Failed");
break;
dbus.lib->ffdbus_message_unref(device);
return "Failed to get device path";
}
if(state != NM_DEVICE_STATE_ACTIVATED)
continue;
dbus.lib->ffdbus_message_unref(device);
}
NMAccessPoint* ap = ffnm_device_wifi_get_active_access_point((NMDeviceWifi *) device);
if (!ap)
continue;
if (item->conn.txRate != item->conn.txRate)
{
uint32_t bitrate;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", buffer->chars, "org.freedesktop.NetworkManager.Device.Wireless", "Bitrate", &bitrate))
item->conn.txRate = bitrate / 1000.;
}
ffStrbufSetStatic(&item->conn.status, "Connected");
FF_STRBUF_AUTO_DESTROY apPath = ffStrbufCreate();
if (!ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", buffer->chars, "org.freedesktop.NetworkManager.Device.Wireless", "ActiveAccessPoint", &apPath))
return "Failed to get active access point path";
GBytes* activeSsid = ffnm_access_point_get_ssid(ap);
if (activeSsid)
{
char* ssid = ffnm_utils_ssid_to_utf8(ffg_bytes_get_data(activeSsid, NULL), ffg_bytes_get_size(activeSsid));
ffStrbufAppendS(&item->conn.ssid, ssid);
ffg_free(ssid);
}
if (!item->conn.status.length)
ffStrbufSetStatic(&item->conn.status, "connected");
ffStrbufAppendS(&item->conn.macAddress, ffnm_access_point_get_bssid(ap));
item->conn.signalQuality = ffnm_access_point_get_strength(ap);
item->conn.rxRate = ffnm_access_point_get_max_bitrate(ap);
if (!item->conn.ssid.length)
ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Ssid", &item->conn.ssid);
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
if(!ffProcessAppendStdOut(&output, (char* const[]){
"iw",
"dev",
item->inf.description.chars,
"link",
NULL
}))
{
if(ffParsePropLines(output.chars, "rx bitrate: ", &item->conn.protocol))
{
sscanf(item->conn.protocol.chars, "%lf", &item->conn.rxRate);
}
if(ffParsePropLines(output.chars, "tx bitrate: ", &item->conn.protocol))
{
if(ffStrbufContainS(&item->conn.protocol, " HE-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else if(ffStrbufContainS(&item->conn.protocol, " VHT-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if(ffStrbufContainS(&item->conn.protocol, " MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
else
ffStrbufClear(&item->conn.protocol);
if (!item->conn.bssid.length)
ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "HwAddress", &item->conn.bssid);
sscanf(item->conn.protocol.chars, "%lf", &item->conn.txRate);
}
}
NM80211ApFlags flags = ffnm_access_point_get_flags(ap);
NM80211ApSecurityFlags wpaFlags = ffnm_access_point_get_wpa_flags(ap);
NM80211ApSecurityFlags rsnFlags = ffnm_access_point_get_rsn_flags(ap);
if (item->conn.signalQuality != item->conn.signalQuality)
{
uint32_t strengthPercent;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Strength", &strengthPercent))
item->conn.signalQuality = strengthPercent;
}
NM80211ApFlags flags;
NM80211ApSecurityFlags wpaFlags, rsnFlags;
if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Flags", &flags) &&
ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "WpaFlags", &wpaFlags) &&
ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars , "org.freedesktop.NetworkManager.AccessPoint", "RsnFlags", &rsnFlags))
{
if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE)
&& (rsnFlags == NM_802_11_AP_SEC_NONE))
ffStrbufAppendS(&item->conn.security, "WEP/");
@@ -205,36 +116,167 @@ static const char* detectWifiWithLibnm(FFlist* result)
ffStrbufTrimRight(&item->conn.security, '/');
}
ffg_object_unref(client);
return NULL;
}
#endif // FF_HAVE_DBUS
static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer)
{
const char* error = NULL;
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
if((error = ffProcessAppendStdOut(&output, (char* const[]){
"iw",
"dev",
item->inf.description.chars,
"link",
NULL
})))
return error;
if(output.length == 0)
return "iw command execution failed";
if(!ffParsePropLines(output.chars, "Connected to ", &item->conn.bssid))
{
ffStrbufAppendS(&item->conn.status, "disconnected");
return NULL;
}
ffStrbufAppendS(&item->conn.status, "connected");
ffStrbufSubstrBeforeFirstC(&item->conn.bssid, ' ');
ffStrbufUpperCase(&item->conn.bssid);
ffParsePropLines(output.chars, "SSID: ", &item->conn.ssid);
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "signal: ", buffer))
{
int level = (int) ffStrbufToSInt(buffer, INT_MAX);
if (level != INT_MAX)
item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2;
}
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "rx bitrate: ", buffer))
item->conn.rxRate = ffStrbufToDouble(buffer);
ffStrbufClear(buffer);
if(ffParsePropLines(output.chars, "tx bitrate: ", buffer))
{
item->conn.txRate = ffStrbufToDouble(buffer);
if(ffStrbufContainS(buffer, " HE-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else if(ffStrbufContainS(buffer, " VHT-MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if(ffStrbufContainS(buffer, " MCS "))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
}
return NULL;
}
#endif
#if __has_include(<linux/wireless.h>)
#define FF_DETECT_WIFI_WITH_IOCTLS
#if FF_HAVE_LINUX_WIRELESS
#include "common/io/io.h"
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/wireless.h> //TODO: Don't depend on kernel headers
#include <linux/wireless.h>
static const char* detectWifiWithIoctls(FFlist* result)
static const char* detectWifiWithIoctls(FFWifiResult* item)
{
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if(sock < 0)
return "socket() failed";
struct iwreq iwr;
strncpy(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ);
ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE);
iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars;
iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1;
iwr.u.essid.flags = 0;
if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0)
{
ffStrbufSetStatic(&item->conn.status, "connected");
ffStrbufRecalculateLength(&item->conn.ssid);
}
if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11"))
{
if(ffStrStartsWithIgnCase(iwr.u.name, "IEEE "))
ffStrbufSetS(&item->conn.protocol, iwr.u.name + strlen("IEEE "));
else
ffStrbufSetS(&item->conn.protocol, iwr.u.name);
}
if(ioctl(sock, SIOCGIWAP, &iwr) >= 0)
{
for(int i = 0; i < 6; ++i)
ffStrbufAppendF(&item->conn.bssid, "%.2X:", (uint8_t) iwr.u.ap_addr.sa_data[i]);
ffStrbufTrimRight(&item->conn.bssid, '-');
}
if(ioctl(sock, SIOCGIWRATE, &iwr) >= 0)
item->conn.txRate = iwr.u.bitrate.value / 1000000.;
struct iw_statistics stats;
iwr.u.data.pointer = &stats;
iwr.u.data.length = sizeof(stats);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWSTATS, &iwr) >= 0)
{
int8_t level = (int8_t) stats.qual.level; // https://stackoverflow.com/questions/18079771/wireless-h-how-do-i-print-out-the-signal-level
item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2;
}
//FIXME: doesn't work
struct iw_encode_ext iwe;
iwr.u.data.pointer = &iwe;
iwr.u.data.length = sizeof(iwe);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0)
{
switch(iwe.alg)
{
case IW_ENCODE_ALG_WEP:
ffStrbufAppendS(&item->conn.security, "WEP");
break;
case IW_ENCODE_ALG_TKIP:
ffStrbufAppendS(&item->conn.security, "TKIP");
break;
case IW_ENCODE_ALG_CCMP:
ffStrbufAppendS(&item->conn.security, "CCMP");
break;
case IW_ENCODE_ALG_PMK:
ffStrbufAppendS(&item->conn.security, "PMK");
break;
case IW_ENCODE_ALG_AES_CMAC:
ffStrbufAppendS(&item->conn.security, "CMAC");
break;
default:
ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe.alg);
break;
}
}
return NULL;
}
#endif // FF_HAVE_LINUX_WIRELESS
const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result)
{
struct if_nameindex* infs = if_nameindex();
if(!infs)
return "if_nameindex() failed";
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
{
ffStrbufSetF(&path, "/sys/class/net/%s/phy80211", i->if_name);
if(!ffPathExists(path.chars, FF_PATHTYPE_DIRECTORY))
ffStrbufSetF(&buffer, "/sys/class/net/%s/phy80211", i->if_name);
if(!ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY))
continue;
FFWifiResult* item = (FFWifiResult*)ffListAdd(result);
@@ -242,109 +284,33 @@ static const char* detectWifiWithIoctls(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name);
if (!ffAppendFileBuffer(path.chars, &item->inf.status))
ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name);
if (!ffAppendFileBuffer(buffer.chars, &item->inf.status))
continue;
ffStrbufTrimRightSpace(&item->inf.status);
if (!ffStrbufEqualS(&item->inf.status, "up"))
continue;
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if(sock < 0)
continue;
struct iwreq iwr;
strncpy(iwr.ifr_name, i->if_name, IFNAMSIZ);
ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE);
iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars;
iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1;
iwr.u.essid.flags = 0;
if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0)
ffStrbufRecalculateLength(&item->conn.ssid);
if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11"))
if (detectWifiWithIw(item, &buffer) != NULL)
{
if(ffStrStartsWithIgnCase(iwr.u.name, "IEEE "))
ffStrbufSetS(&item->conn.protocol, iwr.u.name + strlen("IEEE "));
else
ffStrbufSetS(&item->conn.protocol, iwr.u.name);
#ifdef FF_HAVE_LINUX_WIRELESS
detectWifiWithIoctls(item);
#endif
}
if(ioctl(sock, SIOCGIWAP, &iwr) >= 0)
{
for(int i = 0; i < 6; ++i)
ffStrbufAppendF(&item->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]);
ffStrbufTrimRight(&item->conn.macAddress, '-');
}
struct iw_statistics stats;
iwr.u.data.pointer = &stats;
iwr.u.data.length = sizeof(stats);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWSTATS, &iwr) >= 0)
{
int8_t level = (int8_t) stats.qual.level; // https://stackoverflow.com/questions/18079771/wireless-h-how-do-i-print-out-the-signal-level
item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2;
}
//FIXME: doesn't work
struct iw_encode_ext iwe;
iwr.u.data.pointer = &iwe;
iwr.u.data.length = sizeof(iwe);
iwr.u.data.flags = 0;
if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0)
{
struct iw_encode_ext* iwe = iwr.u.data.pointer;
switch(iwe->alg)
{
case IW_ENCODE_ALG_WEP:
ffStrbufAppendS(&item->conn.security, "WEP");
break;
case IW_ENCODE_ALG_TKIP:
ffStrbufAppendS(&item->conn.security, "TKIP");
break;
case IW_ENCODE_ALG_CCMP:
ffStrbufAppendS(&item->conn.security, "CCMP");
break;
case IW_ENCODE_ALG_PMK:
ffStrbufAppendS(&item->conn.security, "PMK");
break;
case IW_ENCODE_ALG_AES_CMAC:
ffStrbufAppendS(&item->conn.security, "CMAC");
break;
default:
ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe->alg);
break;
}
}
#ifdef FF_HAVE_DBUS
detectWifiWithNm(item, &buffer);
#endif
}
if_freenameindex(infs);
return NULL;
}
#endif
const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result)
{
#ifdef FF_HAVE_LIBNM
detectWifiWithLibnm(result);
if(result->length) // NetworkManager not enabled? #811
return NULL;
#endif
#ifdef FF_DETECT_WIFI_WITH_IOCTLS
return detectWifiWithIoctls(result);
#endif
return "linux/wireless.h not found during compilation";
}
+3 -3
View File
@@ -76,7 +76,7 @@ const char* ffDetectWifi(FFlist* result)
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.macAddress);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
@@ -107,8 +107,8 @@ const char* ffDetectWifi(FFlist* result)
(const char *)connInfo->wlanAssociationAttributes.dot11Ssid.ucSSID);
for (size_t i = 0; i < sizeof(connInfo->wlanAssociationAttributes.dot11Bssid); i++)
ffStrbufAppendF(&item->conn.macAddress, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]);
ffStrbufTrimRight(&item->conn.macAddress, '-');
ffStrbufAppendF(&item->conn.bssid, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]);
ffStrbufTrimRight(&item->conn.bssid, '-');
switch (connInfo->wlanAssociationAttributes.dot11PhyType)
{
+7 -7
View File
@@ -1,7 +1,7 @@
/${c2}o${c3}.
${c1} :${c2}sssso${c3}-
${c1} :${c2}ossssssso${c3}:
${c1} /${c2}ssssssssssso${c3}+
${c1} -+${c2}ssssssssssssssso${c3}+
${c1} //${c2}osssssssssssssso${c3}+-
`+++++++++++++++-`
/${c2}o${c3}.
${c1} /${c2}sssso${c3}-
${c1} /${c2}ossssssso${c3}:
${c1} /${c2}ssssssssssso${c3}+
${c1} /${c2}ssssssssssssssso${c3}+
${c1}//${c2}osssssssssssssso${c3}+-
`+++++++++++++++-`
+14
View File
@@ -0,0 +1,14 @@
$1###########################-
$1###############################
$1=#########**************#########
$1########## ########
$1########## ########
$1########## ########
$1########## ########
$1########## ########
$1########## $2. $1########
$1########## $2+=. $1:#####
$1+#########+=========- $2%%%* $1=#
$1#####################* $2%%%%#
$1-#####################* $2%%%%%.
$2```````
+11
View File
@@ -3508,6 +3508,17 @@ static const FFlogo P[] = {
};
static const FFlogo Q[] = {
// QTS
{
.names = {"qts"},
.lines = FASTFETCH_DATATEXT_LOGO_QTS,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_RED,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// Q4OS
{
.names = {"Q4OS"},
+3 -3
View File
@@ -178,8 +178,8 @@ void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options,
void ffPrintBluetoothHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTH_MODULE_NAME, "{1} ({4})", FF_BLUETOOTH_NUM_FORMAT_ARGS, ((const char* []) {
"Name - name",
"Address - address",
"Name - device name",
"Address - remote device address",
"Type - type",
"Battery percentage number - battery-percentage",
"Is connected - connected",
@@ -192,7 +192,7 @@ void ffInitBluetoothOptions(FFBluetoothOptions* options)
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_BLUETOOTH_MODULE_NAME,
"List bluetooth devices",
"List (connected) bluetooth devices",
ffParseBluetoothCommandOptions,
ffParseBluetoothJsonObject,
ffPrintBluetooth,
+217
View File
@@ -0,0 +1,217 @@
#include "common/percent.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/bluetoothradio/bluetoothradio.h"
#include "modules/bluetoothradio/bluetoothradio.h"
#include "util/stringUtils.h"
#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 8
#define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio"
static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index)
{
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
if (options->moduleArgs.key.length == 0)
{
ffStrbufAppendF(&key, "%s (%s)", FF_BLUETOOTHRADIO_DISPLAY_NAME, radio->name.chars);
}
else
{
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT, &index, "index"},
{FF_FORMAT_ARG_TYPE_STRING, radio->name.chars, "name"},
{FF_FORMAT_ARG_TYPE_STRBUF, &options->moduleArgs.keyIcon, "icon"},
}));
}
const char* version = NULL;
switch (radio->lmpVersion < 0 ? -radio->lmpVersion : radio->lmpVersion)
{
case 0: version = "1.0b"; break;
case 1: version = "1.1"; break;
case 2: version = "1.2"; break;
case 3: version = "2.0"; break;
case 4: version = "2.1"; break;
case 5: version = "3.0"; break;
case 6: version = "4.0"; break;
case 7: version = "4.1"; break;
case 8: version = "4.2"; break;
case 9: version = "5.0"; break;
case 10: version = "5.1"; break;
case 11: version = "5.2"; break;
case 12: version = "5.3"; break;
case 13: version = "5.4"; break;
}
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
if (version)
printf("Bluetooth %s%s (%s)\n", version, (radio->lmpVersion < 0 ? "+" : ""), radio->vendor.chars);
else
ffStrbufPutTo(&radio->vendor, stdout);
}
else
{
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &radio->name, "name"},
{FF_FORMAT_ARG_TYPE_STRBUF, &radio->address, "address"},
{FF_FORMAT_ARG_TYPE_INT, &radio->lmpVersion, "lmp-version"},
{FF_FORMAT_ARG_TYPE_INT, &radio->lmpSubversion, "lmp-subversion"},
{FF_FORMAT_ARG_TYPE_STRING, version, "version"},
{FF_FORMAT_ARG_TYPE_STRBUF, &radio->vendor, "vendor"},
{FF_FORMAT_ARG_TYPE_BOOL, &radio->discoverable, "discoverable"},
{FF_FORMAT_ARG_TYPE_BOOL, &radio->connectable, "connectable"},
}));
}
}
void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options)
{
FF_LIST_AUTO_DESTROY radios = ffListCreate(sizeof (FFBluetoothRadioResult));
const char* error = ffDetectBluetoothRadio(&radios);
if(error)
{
ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
}
else
{
uint8_t index = 0;
FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, radios)
{
if (!radio->enabled)
continue;
index++;
printDevice(options, radio, index);
}
if (index == 0)
{
if (radios.length > 0)
ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled");
else
ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected");
}
}
FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, radios)
{
ffStrbufDestroy(&radio->name);
ffStrbufDestroy(&radio->address);
ffStrbufDestroy(&radio->vendor);
}
}
bool ffParseBluetoothRadioCommandOptions(FFBluetoothRadioOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_BLUETOOTHRADIO_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
return false;
}
void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_val* module)
{
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
}
}
void ffGenerateBluetoothRadioJsonConfig(FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
__attribute__((__cleanup__(ffDestroyBluetoothRadioOptions))) FFBluetoothRadioOptions defaultOptions;
ffInitBluetoothRadioOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
}
void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothRadioResult));
const char* error = ffDetectBluetoothRadio(&results);
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
return;
}
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
FF_LIST_FOR_EACH(FFBluetoothRadioResult, item, results)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address);
if (item->lmpVersion == INT_MIN)
yyjson_mut_obj_add_null(doc, obj, "lmpVersion");
else
yyjson_mut_obj_add_int(doc, obj, "lmpVersion", item->lmpVersion);
if (item->lmpSubversion == INT_MIN)
yyjson_mut_obj_add_null(doc, obj, "lmpSubversion");
else
yyjson_mut_obj_add_int(doc, obj, "lmpSubversion", item->lmpSubversion);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &item->vendor);
yyjson_mut_obj_add_bool(doc, obj, "enabled", item->enabled);
yyjson_mut_obj_add_bool(doc, obj, "discoverable", item->discoverable);
yyjson_mut_obj_add_bool(doc, obj, "connectable", item->connectable);
}
FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, results)
{
ffStrbufDestroy(&radio->name);
ffStrbufDestroy(&radio->address);
ffStrbufDestroy(&radio->vendor);
}
}
void ffPrintBluetoothRadioHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTHRADIO_MODULE_NAME, "Bluetooth {5} ({6})", FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((const char* []) {
"Radio name for discovering - name",
"Address - local radio address",
"LMP version - lmp-version",
"LMP subversion - lmp-subversion",
"Bluetooth version - version",
"Vendor - vendor",
"Discoverable - discoverable",
"Connectable / Pairable - connectable",
}));
}
void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options)
{
ffOptionInitModuleBaseInfo(
&options->moduleInfo,
FF_BLUETOOTHRADIO_MODULE_NAME,
"List bluetooth radios width supported version and vendor",
ffParseBluetoothRadioCommandOptions,
ffParseBluetoothRadioJsonObject,
ffPrintBluetoothRadio,
ffGenerateBluetoothRadioJsonResult,
ffPrintBluetoothRadioHelpFormat,
ffGenerateBluetoothRadioJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs, "󰐻");
}
void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}
@@ -0,0 +1,9 @@
#pragma once
#include "fastfetch.h"
#define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio"
void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options);
void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options);
void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options);
+12
View File
@@ -0,0 +1,12 @@
#pragma once
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
#include "common/percent.h"
typedef struct FFBluetoothRadioOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
} FFBluetoothRadioOptions;
+1 -1
View File
@@ -95,7 +95,7 @@ void ffPrintCPU(FFCPUOptions* options)
FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBase, &freqBase);
FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBase, &freqMax);
ffParseFrequency(cpu.frequencyMax, &freqMax);
FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate();
ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit);
+3 -1
View File
@@ -327,6 +327,8 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
else
yyjson_mut_obj_add_null(doc, obj, "coreCount");
yyjson_mut_obj_add_real(doc, obj, "coreUsage", gpu->coreUsage);
yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, obj, "memory");
yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated");
@@ -371,7 +373,7 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi);
yyjson_mut_obj_add_real(doc, obj, "frequency", gpu->frequency); // NaN will be output as "null"
yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency);
yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId);
}
+1
View File
@@ -5,6 +5,7 @@
#include "modules/battery/battery.h"
#include "modules/bios/bios.h"
#include "modules/bluetooth/bluetooth.h"
#include "modules/bluetoothradio/bluetoothradio.h"
#include "modules/brightness/brightness.h"
#include "modules/board/board.h"
#include "modules/bootmgr/bootmgr.h"
+1 -1
View File
@@ -54,7 +54,7 @@ void ffPrintMonitor(FFMonitorOptions* options)
printf("%ux%u px", display->width, display->height);
if (display->refreshRate > 0)
printf(" @ %.3f Hz", display->refreshRate);
printf(" @ %g Hz", ((int) (display->refreshRate * 1000 + 0.5)) / 1000.0);
if (inch > 0)
printf(" - %ux%u mm (%.2f inches, %.2f ppi)\n", display->physicalWidth, display->physicalHeight, inch, ppi);
else
+1 -1
View File
@@ -96,7 +96,7 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson
else
yyjson_mut_obj_add_null(doc, gpuObj, "coreCount");
yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency);
yyjson_mut_obj_add_uint(doc, gpuObj, "frequency", gpu->frequency);
yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory");
+1
View File
@@ -5,6 +5,7 @@
#include "modules/battery/option.h"
#include "modules/bios/option.h"
#include "modules/bluetooth/option.h"
#include "modules/bluetoothradio/option.h"
#include "modules/board/option.h"
#include "modules/bootmgr/option.h"
#include "modules/break/option.h"
@@ -20,6 +20,12 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options)
return;
}
if (result.length == 0)
{
ffPrintError(FF_PHYSICALMEMORY_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory detected");
return;
}
FF_STRBUF_AUTO_DESTROY prettySize = ffStrbufCreate();
uint32_t i = 0;
+4 -4
View File
@@ -85,7 +85,7 @@ void ffPrintWifi(FFWifiOptions* options)
{FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status, "inf-status"},
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status, "status"},
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid, "ssid"},
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress, "mac-address"},
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.bssid, "bssid"},
{FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol, "protocol"},
{FF_FORMAT_ARG_TYPE_DOUBLE, &percentNum, "signal-quality"},
{FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate, "rx-rate"},
@@ -99,7 +99,7 @@ void ffPrintWifi(FFWifiOptions* options)
ffStrbufDestroy(&item->inf.status);
ffStrbufDestroy(&item->conn.status);
ffStrbufDestroy(&item->conn.ssid);
ffStrbufDestroy(&item->conn.macAddress);
ffStrbufDestroy(&item->conn.bssid);
ffStrbufDestroy(&item->conn.protocol);
ffStrbufDestroy(&item->conn.security);
}
@@ -170,7 +170,7 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut
yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn");
yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status);
yyjson_mut_obj_add_strbuf(doc, conn, "ssid", &wifi->conn.ssid);
yyjson_mut_obj_add_strbuf(doc, conn, "bssid", &wifi->conn.macAddress);
yyjson_mut_obj_add_strbuf(doc, conn, "bssid", &wifi->conn.bssid);
yyjson_mut_obj_add_strbuf(doc, conn, "protocol", &wifi->conn.protocol);
yyjson_mut_obj_add_strbuf(doc, conn, "security", &wifi->conn.security);
yyjson_mut_obj_add_real(doc, conn, "signalQuality", wifi->conn.signalQuality);
@@ -184,7 +184,7 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut
ffStrbufDestroy(&item->inf.status);
ffStrbufDestroy(&item->conn.status);
ffStrbufDestroy(&item->conn.ssid);
ffStrbufDestroy(&item->conn.macAddress);
ffStrbufDestroy(&item->conn.bssid);
ffStrbufDestroy(&item->conn.protocol);
ffStrbufDestroy(&item->conn.security);
}
-7
View File
@@ -62,8 +62,6 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va
ffStrbufSetS(&options->libOSMesa, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "pulse"))
ffStrbufSetS(&options->libPulse, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "nm"))
ffStrbufSetS(&options->libnm, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "ddcutil"))
ffStrbufSetS(&options->libDdcutil, yyjson_get_str(val));
else if (ffStrEqualsIgnCase(key, "drm"))
@@ -129,8 +127,6 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key
ffOptionParseString(key, value, &options->libOSMesa);
else if(ffStrEqualsIgnCase(subkey, "pulse"))
ffOptionParseString(key, value, &options->libPulse);
else if(ffStrEqualsIgnCase(subkey, "nm"))
ffOptionParseString(key, value, &options->libnm);
else if(ffStrEqualsIgnCase(subkey, "ddcutil"))
ffOptionParseString(key, value, &options->libDdcutil);
else if(ffStrEqualsIgnCase(subkey, "drm"))
@@ -227,9 +223,6 @@ void ffOptionsGenerateLibraryJsonConfig(FFOptionsLibrary* options, yyjson_mut_do
if (!ffStrbufEqual(&options->libPulse, &defaultOptions.libPulse))
yyjson_mut_obj_add_strbuf(doc, obj, "pulse", &options->libPulse);
if (!ffStrbufEqual(&options->libnm, &defaultOptions.libnm))
yyjson_mut_obj_add_strbuf(doc, obj, "nm", &options->libnm);
if (!ffStrbufEqual(&options->libDdcutil, &defaultOptions.libDdcutil))
yyjson_mut_obj_add_strbuf(doc, obj, "ddcutil", &options->libDdcutil);
-1
View File
@@ -30,7 +30,6 @@ typedef struct FFOptionsLibrary
FFstrbuf libGLX;
FFstrbuf libOSMesa;
FFstrbuf libPulse;
FFstrbuf libnm;
FFstrbuf libDdcutil;
FFstrbuf libdrm;
#endif
+2
View File
@@ -6,6 +6,7 @@ void ffOptionsInitModules(FFOptionsModules* options)
ffInitBatteryOptions(&options->battery);
ffInitBiosOptions(&options->bios);
ffInitBluetoothOptions(&options->bluetooth);
ffInitBluetoothRadioOptions(&options->bluetoothRadio);
ffInitBoardOptions(&options->board);
ffInitBootmgrOptions(&options->bootmgr);
ffInitBreakOptions(&options->break_);
@@ -77,6 +78,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options)
ffDestroyBatteryOptions(&options->battery);
ffDestroyBiosOptions(&options->bios);
ffDestroyBluetoothOptions(&options->bluetooth);
ffDestroyBluetoothRadioOptions(&options->bluetoothRadio);
ffDestroyBoardOptions(&options->board);
ffDestroyBootmgrOptions(&options->bootmgr);
ffDestroyBreakOptions(&options->break_);
+1
View File
@@ -7,6 +7,7 @@ typedef struct FFOptionsModules
FFBatteryOptions battery;
FFBiosOptions bios;
FFBluetoothOptions bluetooth;
FFBluetoothRadioOptions bluetoothRadio;
FFBoardOptions board;
FFBootmgrOptions bootmgr;
FFBreakOptions break_;