Compare commits

...

101 Commits

Author SHA1 Message Date
Carter Li d0d9831d41 Merge pull request #686 from fastfetch-cli/dev
Release v2.6.0
2024-01-17 15:20:56 +08:00
李通洲 b3945e277c Global: review code 2024-01-17 15:06:52 +08:00
李通洲 9f77851176 JsonSchema: make it a valid json document 2024-01-17 14:08:31 +08:00
李通洲 963eaa5395 Release: v2.6.0 2024-01-17 14:02:07 +08:00
李通洲 07dfe57386 Doc: update changelog 2024-01-17 14:00:55 +08:00
Carter Li a3c0085e2b Sound: tidy 2024-01-17 13:31:34 +08:00
Carter Li c8f28e4c79 Sound (FreeBSD): don't use mixer.h
It's only supported in FreeBSD 14 and later
2024-01-17 10:22:56 +08:00
Carter Li 861eea5899 Sound (FreeBSD): new impl; drop pulseaudio dep 2024-01-16 17:40:41 +08:00
李通洲 1227799a38 Vulkan: print platformApi in JSON format 2024-01-15 18:14:40 +08:00
李通洲 35d1497053 Doc: update changelog 2024-01-15 15:48:39 +08:00
李通洲 ea3734f004 Locale (Windows): fix typo 2024-01-15 15:48:32 +08:00
李通洲 5d35dade60 DisplayServer (Windows): don't detect unknown display type as external 2024-01-15 15:22:33 +08:00
李通洲 0c844fc342 FFstrbuf: don't crash with ffStrbufInitStatic(&buf, NULL) 2024-01-15 15:22:33 +08:00
李通洲 c1ed0a4e91 Locale (Windows): print standard format 2024-01-15 15:22:33 +08:00
李通洲 e1af6fc0fe Locale: display only LC_MESSAGES if available, which is used by gettext 2024-01-15 14:27:29 +08:00
李通洲 c1d41a36bb CMake: fix build in macOS with -DENABLE_SYSTEM_YYJSON 2024-01-15 14:21:23 +08:00
李通洲 958bde228b Doc: fix typo 2024-01-15 13:30:18 +08:00
李通洲 6655c446ba Revert "Image: silence compiler warnings"
This reverts commit afa0a7dac8.
2024-01-15 13:15:43 +08:00
李通洲 43657e8fd6 Doc: update changelog 2024-01-15 11:29:29 +08:00
李通洲 38f216291e CMake: use system <yyjson.h> in fastfetch.c and flashfetch.c too
Fix #684
2024-01-15 11:22:42 +08:00
Carter Li 01de158bba Vulkan: print instance version if no vulkan drivers found 2024-01-15 10:33:55 +08:00
李通洲 5a34b8d01f Vulkan: error out if no results detected 2024-01-15 09:39:03 +08:00
李通洲 afa0a7dac8 Image: silence compiler warnings 2024-01-15 09:13:14 +08:00
李通洲 974ee2ab0d TerminalShell: fix wezterm name pretty printing 2024-01-14 17:26:54 +08:00
李通洲 ab1e3db665 Shell (Linux): detect ash version 2024-01-13 23:39:17 +08:00
李通洲 95b64622c4 Terminal (Linux): fix detection 2024-01-13 23:39:17 +08:00
李通洲 d3c7529c45 Processing (Windows): don't use CreateEventW 2024-01-13 13:38:53 +08:00
李通洲 89db425a03 Gamepad (Windows): use nonblocking read to get battery information 2024-01-13 13:33:29 +08:00
apocelipes 269ad36df5 refactor(TerminalShell): changing recursion into loops 2024-01-12 23:56:04 +08:00
李通洲 22cdb1247f TerminalShell: tidy; use case senstive string comparation where meaningful 2024-01-12 21:21:42 +08:00
李通洲 905ed76ddd TerminalShell: split terminal and shell detection code further 2024-01-12 20:58:45 +08:00
李通洲 6da57d64c3 TerminalShell: split terminal detection and shell detection 2024-01-12 16:44:19 +08:00
李通洲 37e0a7b03f stringUtils: tidy 2024-01-11 16:27:53 +08:00
李通洲 0c65cdc1f5 GPU (macOS): detect memory usage 2024-01-11 10:11:50 +08:00
李通洲 653e689f18 GPU (macOS): tidy 2024-01-11 09:55:13 +08:00
李通洲 a8aaf605b1 Doc: update changelog 2024-01-10 19:04:47 +08:00
李通洲 5f638a67ed Battery: rename manufacturerDate to manufactureDate 2024-01-10 19:03:58 +08:00
李通洲 0645f559af Monitor: detect serial number and manufacture date 2024-01-10 19:01:54 +08:00
李通洲 f5a57ab747 Doc: update changelog 2024-01-10 14:48:47 +08:00
李通洲 92e05f7e38 Chassis: don't print useless version 2024-01-10 14:44:14 +08:00
李通洲 8ba031b761 Brightness (FreeBSD): don't print empty () 2024-01-10 14:22:56 +08:00
李通洲 fdb68669f4 Battery (macOS): support manufacture date detection 2024-01-10 13:26:54 +08:00
李通洲 12155e029b Battery (Linux): support manufacture date detection 2024-01-09 23:08:19 +08:00
李通洲 7926b74917 Battery: detect manufacturer date 2024-01-09 22:58:32 +08:00
Carter Li 61af59fc00 Battery (Linux): fix temperature detection 2024-01-09 16:34:04 +08:00
李通洲 bc52613410 Gamepad: rename identifier to serial number 2024-01-09 15:53:42 +08:00
李通洲 f84bb1ebe2 Smbios: silence compiler warnings 2024-01-09 15:46:19 +08:00
李通洲 a160bc8de5 Gamepad (macOS): detect manufacturer 2024-01-09 15:28:03 +08:00
Carter Li cb599c6f2a Display (FreeBSD): support resolution detection in console 2024-01-08 16:03:07 +08:00
Carter Li 5693700c16 Bios (FreeBSD): fix boot type detection on some weird platforms 2024-01-08 16:02:52 +08:00
Carter Li e8c067ff3d Wifi (Linux): don't print invalid information 2024-01-08 11:32:39 +08:00
Carter Li 80cc4e3f4a Host (Linux): detect serial number for Asahi Linux 2024-01-08 11:19:35 +08:00
李通洲 8e78fadbeb Gamepad: don't provide device names of XBox compatible controllers 2024-01-08 10:38:40 +08:00
李通洲 1215eb06ca Gamepad (Windows): support battery detection of NS Pro 2024-01-07 19:07:15 +08:00
李通洲 2aa899d83c Gamepad (Linux): support battery level detection of NS Pro controller 2024-01-07 17:59:50 +08:00
李通洲 cf096eb101 Gamepad (Windows): detect serial number and battery (PS4 controller) 2024-01-06 23:43:35 +08:00
李通洲 5b4a26393d Gamepad (Linux): detect battery capacity 2024-01-06 20:40:20 +08:00
李通洲 2ba878cbab Monitor (Linux): fix detection with Nvidia drivers
NVIDIA DRM driver reports `enabled` to be `disabled`
2024-01-06 19:12:36 +08:00
李通洲 0af40ab6a3 Settings (FreeBSD): don't append trailing \0 2024-01-06 18:47:16 +08:00
李通洲 b9777bec77 Chassis: detect serial number 2024-01-06 18:35:10 +08:00
李通洲 8801921d02 Smbios: trim spaces 2024-01-06 18:33:57 +08:00
李通洲 c0c32456e8 Board: detect serial number 2024-01-06 18:12:51 +08:00
李通洲 640fa146c1 CPU (Windows): only use smbios to detect maximum speed
Because some virtual machines report invalid information
2024-01-06 18:00:59 +08:00
李通洲 de91429e1a CI: fix build 2024-01-06 17:11:39 +08:00
李通洲 1621484c96 CPU (Windows): don't report 30GHz in VMware 2024-01-06 17:11:26 +08:00
李通洲 d8297d296e CPU (Windows): use ThreadCount if GetLogicalProcessorInformationEx() fails 2024-01-06 17:11:26 +08:00
李通洲 48bb82c8fb Board (Windows): use SMBIOS result 2024-01-06 17:11:26 +08:00
李通洲 c1c7f7b93f Bios (Windows): use SMBIOS result 2024-01-06 17:11:26 +08:00
李通洲 1d35811253 Windows: make SMBIOS data a singleton 2024-01-06 17:11:26 +08:00
李通洲 fe0b43d92d CPU (Windows): detect the actual maximum frequency 2024-01-06 17:11:26 +08:00
李通洲 446fe907d2 Smbios: add comments, tidy 2024-01-06 17:11:26 +08:00
李通洲 d578f1006c Host / Chassis (Windows): remove options --*-use-wmi 2024-01-06 17:11:26 +08:00
李通洲 33f3199383 Host / Chassis (Windows): parse SMBIOS data directly 2024-01-06 17:11:25 +08:00
李通洲 21f3875c4f Host (Windows): detect serial number and UUID 2024-01-06 17:11:25 +08:00
李通洲 6bcd75835e Host: rename properties 2024-01-05 20:38:29 +08:00
李通洲 24cec76251 Host (Linux): detect serial number and uuid 2024-01-05 16:33:52 +08:00
李通洲 f8ac56691f Host (FreeBSD): detect serial number and uuid 2024-01-05 16:32:34 +08:00
李通洲 810112cb26 Host (macOS): detect serial number and uuid 2024-01-05 16:29:38 +08:00
李通洲 2340c2afd7 Board (macOS): print internal name instead of model indentifier
and actually detect the vendor
2024-01-05 16:24:43 +08:00
李通洲 b6c8649cbf macOS: improve IO service related code generally 2024-01-05 15:00:50 +08:00
李通洲 92a6b01133 Brightness (Apple): code optimise and fix mem leaks 2024-01-05 13:20:47 +08:00
李通洲 396112e8ea PowerAdapter: simplify implementation and support serial number detection 2024-01-05 11:01:32 +08:00
李通洲 5eacd0bb8e Battery (Apple): use less hard coded strings 2024-01-05 11:01:32 +08:00
李通洲 ea3ea196aa Battery (Linux): simplify temp detection 2024-01-05 11:01:32 +08:00
李通洲 0e6be69eb8 GPU (Linux): try detect GPU type 2024-01-04 18:50:38 +08:00
李通洲 d69e19377e Doc: update changelog 2024-01-04 16:31:41 +08:00
李通洲 f4f466d4ba Battery: print serial number 2024-01-04 16:21:19 +08:00
李通洲 10b2fe13bd Battery (Windows): detect serial number 2024-01-04 16:20:48 +08:00
李通洲 b5dc4f59f1 Battery (macOS): detect serial number 2024-01-04 16:04:34 +08:00
李通洲 7c0b743c61 Merge remote-tracking branch 'origin/master' into dev 2024-01-04 15:33:16 +08:00
李通洲 6bd909c89d Doc: update changelog 2024-01-04 15:27:31 +08:00
李通洲 1fef41241a Presets: fix formatation 2024-01-04 15:27:31 +08:00
Carter Li 5c75e271ef PowerAdapter (Linux): add support 2024-01-04 15:16:51 +08:00
Carter Li b6b1993f62 Battery (Linux): code refactor, support serial number detection 2024-01-04 15:16:51 +08:00
Carter Li cd0109c382 Battery (Linux): remove option --battery-dir
It was added in c5c3cecb93 but there was no comment or issues linked to indicate why it was necessary.

`/sys/class/power_supply` is standardized in <https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power>. I don't I want to support non-standard platform unless proper reason is given
2024-01-04 14:18:33 +08:00
Carter Li 6698283430 GPU: fix vendor detection for asahi 2024-01-04 10:29:02 +08:00
李通洲 83ce3e4554 Wallpaper (macOS): support Sonoma 2024-01-03 10:15:56 +08:00
李通洲 ff0f91dc3c macOS: fix mem leaks 2024-01-03 10:12:48 +08:00
李通洲 ab028964bf GPU (WSL): add missing FF_USE_PROPRIETARY_GPU_DRIVER_API macro guards 2024-01-02 18:47:06 +08:00
李通洲 21353b8256 CMake (GPU): change ENABLE_NVIDIA_GPU to ENABLE_PROPRIETARY_GPU_DRIVER_API 2024-01-02 10:49:03 +08:00
Viorel 0a1de91a29 Add option for NVIDIA GPU support 2024-01-01 22:18:03 +08:00
109 changed files with 2392 additions and 1310 deletions
+29
View File
@@ -1,3 +1,32 @@
# 2.6.0
Changes:
* Remove support of option `--battery-dir`. We detect a lot of things in `/sys/class/*` and only module `Battery` supports specifying a custom directory for some reason, which is weird.
* Remove `--chassis-use-wmi` which is no longer used.
Features:
* Add `ENABLE_PROPRIETARY_GPU_DRIVER_API` cmake option to disable using of proprietary GPU driver APIs (GPU)
* Support wallpaper detection for macOS Sonoma (Wallpaper, macOS)
* Support power adapter detection for Asahi Linux (PowerAdapter, Linux)
* Support battery serial number and manufacturer date detection (Battery)
* Support host serial number and UUID detection (Host)
* Support battery level detection for gamepads where possible (Gamepad)
* Support maximum CPU clock detection. Previously base clock was printed (CPU, Windows)
* Support manufacture date and serial number detection for physical monitors (Monitor)
* Support ash (default shell of BusyBox) version detection (Shell, Linux)
* Sound module in FreeBSD now uses native `ioctl`s. Pulseaudio dependency is no longer used.
* Locale module in Windows now prints the same format as in Linux and other posix systems.
Bugfixes:
* Fix overall memory leaks (macOS)
* Remove trailing `\0` in JSON results (FreeBSD)
* Fix physical monitor detection with Nvidia drivers (Monitor, Linux)
* Don't print llvmpipe in vulkan module (Vulkan)
* Fix system yyjson usage in `fastfetch.c`. Previously embedded `3rdparty/yyjson/yyjson.h` was used in `fastfetch.c` even if `ENABLE_SYSTEM_YYJSON` was set (CMake)
* Fix locale module printing unexpected results in specific environments (Locale)
* Fix battery temperature detection in Windows. Note only smart batteries report temperatures but few laptops uses smart battery (Battery, Windows)
* Print device name if no backlight name is available, so we don't print empty parentheses (Brightness, FreeBSD)
# 2.5.0
Changes:
+44 -20
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.5.0
VERSION 2.6.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -66,7 +66,7 @@ cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
@@ -74,6 +74,7 @@ cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_PROPRIETARY_GPU_DRIVER_API "Enable proprietary GPU driver API (NVML, IGCL and AGS)" ON)
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
@@ -109,12 +110,8 @@ endif()
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
endif()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
elseif(APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc")
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
@@ -290,7 +287,6 @@ set(LIBFASTFETCH_SRC
src/detection/displayserver/displayserver.c
src/detection/font/font.c
src/detection/gpu/gpu.c
src/detection/locale/locale.c
src/detection/media/media.c
src/detection/netio/netio.c
src/detection/opencl/opencl.c
@@ -374,7 +370,6 @@ set(LIBFASTFETCH_SRC
src/util/FFlist.c
src/util/FFstrbuf.c
src/util/platform/FFPlatform.c
src/util/stringUtils.c
src/util/smbiosHelper.c
)
@@ -405,12 +400,12 @@ if(LINUX)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gpu/gpu_nvidia.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_linux.c
src/detection/icons/icons_linux.c
src/detection/libc/libc_linux.c
src/detection/lm/lm_linux.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_linux.c
src/detection/media/media_linux.c
@@ -420,7 +415,7 @@ if(LINUX)
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/poweradapter/poweradapter_linux.c
src/detection/processes/processes_linux.c
src/detection/gtk_qt/qt.c
src/detection/sound/sound_linux.c
@@ -464,6 +459,7 @@ elseif(ANDROID)
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_android.c
src/detection/lm/lm_nosupport.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
src/detection/media/media_nosupport.c
@@ -519,12 +515,12 @@ elseif(BSD)
src/detection/displayserver/linux/xlib.c
src/detection/font/font_linux.c
src/detection/gpu/gpu_linux.c
src/detection/gpu/gpu_nvidia.c
src/detection/gtk_qt/gtk.c
src/detection/host/host_bsd.c
src/detection/lm/lm_linux.c
src/detection/icons/icons_linux.c
src/detection/libc/libc_bsd.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_bsd.c
src/detection/media/media_linux.c
@@ -537,7 +533,7 @@ elseif(BSD)
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/processes/processes_bsd.c
src/detection/gtk_qt/qt.c
src/detection/sound/sound_linux.c
src/detection/sound/sound_bsd.c
src/detection/swap/swap_bsd.c
src/detection/temps/temps_bsd.c
src/detection/terminalfont/terminalfont_linux.c
@@ -580,6 +576,7 @@ elseif(APPLE)
src/detection/lm/lm_nosupport.c
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_apple.c
src/detection/locale/locale_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_apple.c
src/detection/media/media_apple.m
@@ -600,7 +597,7 @@ elseif(APPLE)
src/detection/theme/theme_nosupport.c
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_apple.c
src/detection/wallpaper/wallpaper_apple.m
src/detection/wifi/wifi_apple.m
src/detection/wm/wm_apple.c
src/detection/de/de_nosupport.c
@@ -620,7 +617,7 @@ elseif(WIN32)
src/detection/bluetooth/bluetooth_windows.c
src/detection/board/board_windows.c
src/detection/brightness/brightness_windows.cpp
src/detection/chassis/chassis_windows.cpp
src/detection/chassis/chassis_windows.c
src/detection/cpu/cpu_windows.c
src/detection/cpuusage/cpuusage_windows.c
src/detection/cursor/cursor_windows.c
@@ -630,13 +627,11 @@ elseif(WIN32)
src/detection/displayserver/displayserver_windows.c
src/detection/font/font_windows.c
src/detection/gpu/gpu_windows.c
src/detection/gpu/gpu_nvidia.c
src/detection/gpu/gpu_intel.c
src/detection/gpu/gpu_amd.c
src/detection/host/host_windows.c
src/detection/icons/icons_windows.c
src/detection/libc/libc_windows.cpp
src/detection/lm/lm_nosupport.c
src/detection/locale/locale_windows.c
src/detection/localip/localip_windows.c
src/detection/gamepad/gamepad_windows.c
src/detection/media/media_nosupport.c
@@ -676,6 +671,17 @@ if(ENABLE_DIRECTX_HEADERS)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp)
endif()
if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32))
message(STATUS "Enabling proprietary GPU driver API")
if(LINUX OR BSD OR WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.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()
endif()
include(CheckFunctionExists)
check_function_exists(wcwidth HAVE_WCWIDTH)
if(NOT HAVE_WCWIDTH)
@@ -699,9 +705,20 @@ add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32))
target_compile_definitions(libfastfetch PRIVATE FF_USE_PROPRIETARY_GPU_DRIVER_API)
endif()
if(yyjson_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(libfastfetch PRIVATE yyjson)
target_link_libraries(libfastfetch PRIVATE yyjson::yyjson)
# `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
else()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
endif()
endif()
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
@@ -993,6 +1010,13 @@ set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
if(yyjson_FOUND)
target_compile_definitions(fastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(fastfetch PRIVATE yyjson::yyjson)
target_compile_definitions(flashfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(flashfetch PRIVATE yyjson::yyjson)
endif()
if(WIN32)
set(TARGET_NAME fastfetch)
target_sources(fastfetch
-1
View File
@@ -384,7 +384,6 @@ __fastfetch_completion()
"--lib-pulse"
"--lib-ddcutil"
"--lib-nm"
"--battery-dir"
)
local FF_OPTIONS_LOGO=(
-9
View File
@@ -804,10 +804,6 @@
"const": "battery",
"description": "Print battery capacity, status, etc"
},
"dir": {
"description": "The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only",
"type": "string"
},
"useSetupApi": {
"description": "Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only",
"type": "boolean",
@@ -883,11 +879,6 @@
"const": "chassis",
"description": "Print chassis type (desktop, laptop, etc)"
},
"useWmi": {
"description": "Set if WMI query should be used on Windows, which detects more information but slower",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
+9
View File
@@ -244,6 +244,15 @@ void ffListFeatures(void)
#ifdef FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
"Proprietary GPU driver API\n"
#endif
#ifdef FF_USE_SYSTEM_YYJSON
"System yyjson\n"
#endif
#ifdef FF_USE_PCI_MEMORY
"PCI memory\n"
#endif
""
, stdout);
}
+1 -1
View File
@@ -105,7 +105,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
unsigned int mode = fileStat.st_mode & S_IFMT;
if(pathType & FF_PATHTYPE_FILE && mode == S_IFREG)
if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR)
return true;
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
+3 -4
View File
@@ -83,8 +83,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
char str[FF_PIPE_BUFSIZ];
DWORD nRead = 0;
FF_AUTO_CLOSE_FD HANDLE hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
OVERLAPPED overlapped = { .hEvent = hEvent };
OVERLAPPED overlapped = { };
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
do
{
@@ -93,11 +92,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
switch (GetLastError())
{
case ERROR_IO_PENDING:
if (!timeout || WaitForSingleObject(hEvent, (DWORD) timeout) != WAIT_OBJECT_0)
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
{
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "WaitForSingleObject(hEvent) failed or timeout";
return "WaitForSingleObject(hChildPipeRead) failed or timeout";
}
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
+2 -3
View File
@@ -411,9 +411,8 @@ bool ffSettingsGetFreeBSDKenv(const char* propName, FFstrbuf* result)
//https://wiki.ghostbsd.org/index.php/Kenv
ffStrbufEnsureFree(result, KENV_MVALLEN);
int len = kenv(KENV_GET, propName, result->chars + result->length, KENV_MVALLEN);
if (len <= 0) return false;
result->length += (uint32_t) len;
result->chars[result->length] = '\0';
if (len <= 1) return false; // number of bytes copied, including NUL terminator
result->length += (uint32_t) len - 1;
return true;
}
#endif
-19
View File
@@ -842,16 +842,6 @@
"default": "default"
}
},
{
"long": "chassis-use-wmi",
"desc": "Set if WMI query should be used on Windows",
"remark": "WMI query detects more information but is slower. Windows only",
"arg": {
"type": "bool",
"optional": true,
"default": false
}
},
{
"long": "separator-string",
"desc": "Set the string printed by the separator module",
@@ -1026,15 +1016,6 @@
"default": "main"
}
},
{
"long": "battery-dir",
"desc": "The directory where the battery folders are",
"remark": "Linux only",
"arg": {
"type": "path",
"default": "/sys/class/power_supply/"
}
},
{
"long": "battery-use-setup-api",
"desc": "Set if \"SetupAPI\" should be used on Windows to detect battery info",
+3 -1
View File
@@ -7,10 +7,12 @@
typedef struct FFBatteryResult
{
FFstrbuf manufacturer;
FFstrbuf manufactureDate;
FFstrbuf modelName;
FFstrbuf technology;
double capacity;
FFstrbuf status;
FFstrbuf serial;
double capacity;
double temperature;
uint32_t cycleCount;
} FFBatteryResult;
+1
View File
@@ -40,6 +40,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->manufactureDate);
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
ffStrbufAppendS(&battery->status, yyjson_get_str(yyjson_obj_get(root, "status")));
+33 -26
View File
@@ -4,49 +4,46 @@
#include "detection/temps/temps_apple.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPM.h>
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryBattery = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
continue;
}
bool boolValue;
const char* error;
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->manufactureDate);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
return error;
if (maxCapacity <= 0)
return "Querying MaxCapacity failed";
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
continue;
if ((error = ffCfDictGetInt(properties, CFSTR("CurrentCapacity"), &currentCapacity)))
return error;
if(currentCapacity <= 0)
return "Querying CurrentCapacity failed";
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), &currentCapacity) != NULL || currentCapacity <= 0)
continue;
battery->capacity = currentCapacity * 100.0 / maxCapacity;
ffCfDictGetString(properties, CFSTR("DeviceName"), &battery->modelName);
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial);
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
{
@@ -57,33 +54,43 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
}
int32_t cycleCount = 0;
ffCfDictGetInt(properties, CFSTR("CycleCount"), &cycleCount);
ffCfDictGetInt(properties, CFSTR(kIOPMPSCycleCountKey), &cycleCount);
battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount;
if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue)
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "AC connected, ");
else
ffStrbufAppendS(&battery->status, "Discharging, ");
if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Charging, ");
if (!ffCfDictGetBool(properties, CFSTR("AtCriticalLevel"), &boolValue) && boolValue)
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) && boolValue)
ffStrbufAppendS(&battery->status, "Critical, ");
ffStrbufTrimRight(&battery->status, ' ');
ffStrbufTrimRight(&battery->status, ',');
CFDictionaryRef batteryData;
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL)
{
char manufactureDate[sizeof(uint64_t)];
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL)
{
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
if (options->temp)
{
int64_t temp;
if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp))
if (!ffCfDictGetInt64(properties, CFSTR(kIOPMPSBatteryTemperatureKey), &temp))
battery->temperature = (double) temp / 10 - 273.15;
else
ffDetectSmcTemps(FF_TEMP_BATTERY, &battery->temperature);
}
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
return NULL;
}
+2
View File
@@ -39,6 +39,8 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->serial);
ffStrbufInit(&battery->manufactureDate);
battery->capacity = battio.battinfo.cap;
if(battio.battinfo.state == ACPI_BATT_STAT_INVALID)
+71 -44
View File
@@ -9,106 +9,133 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
{
uint32_t dirLength = dir->length;
FF_STRBUF_AUTO_DESTROY testBatteryBuffer = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
//type must exist and be "Battery"
ffStrbufAppendS(dir, "/type");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufTrimRightSpace(&testBatteryBuffer);
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
ffStrbufTrimRightSpace(&tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0)
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery"))
return;
//scope may not exist or must not be "Device"
ffStrbufAppendS(dir, "/scope");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufTrimRightSpace(&testBatteryBuffer);
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
ffStrbufTrimRightSpace(&tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
return;
FFBatteryResult* result = ffListAdd(results);
//capacity must exist and be not empty
ffStrbufAppendS(dir, "/capacity");
bool available = ffReadFileBuffer(dir->chars, &testBatteryBuffer);
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(available)
result->capacity = ffStrbufToDouble(&testBatteryBuffer);
if(!available)
{
result->capacity = 0.0/0.0;
--results->length;
if (!available)
return;
}
FFBatteryResult* result = ffListAdd(results);
result->capacity = ffStrbufToDouble(&tmpBuffer);
//At this point, we have a battery. Try to get as much values as possible.
ffStrbufInit(&result->manufacturer);
ffStrbufAppendS(dir, "/manufacturer");
ffReadFileBuffer(dir->chars, &result->manufacturer);
ffStrbufTrimRightSpace(&result->manufacturer);
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
ffStrbufTrimRightSpace(&result->manufacturer);
else if (ffStrEquals(id, "macsmc-battery")) // asahi
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->modelName);
ffStrbufAppendS(dir, "/model_name");
ffReadFileBuffer(dir->chars, &result->modelName);
ffStrbufTrimRightSpace(&result->modelName);
if (ffReadFileBuffer(dir->chars, &result->modelName))
ffStrbufTrimRightSpace(&result->modelName);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->technology);
ffStrbufAppendS(dir, "/technology");
ffReadFileBuffer(dir->chars, &result->technology);
ffStrbufTrimRightSpace(&result->technology);
if (ffReadFileBuffer(dir->chars, &result->technology))
ffStrbufTrimRightSpace(&result->technology);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->status);
ffStrbufAppendS(dir, "/status");
ffReadFileBuffer(dir->chars, &result->status);
ffStrbufTrimRightSpace(&result->status);
if (ffReadFileBuffer(dir->chars, &result->status))
ffStrbufTrimRightSpace(&result->status);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/serial_number");
if (ffReadFileBuffer(dir->chars, &result->serial))
ffStrbufTrimRightSpace(&result->serial);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufAppendS(dir, "/cycle_count");
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
ffStrbufTrimRightSpace(&testBatteryBuffer);
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (dir->length)
if (available)
{
int64_t cycleCount = 0;
cycleCount = (int64_t) strtoll(testBatteryBuffer.chars, NULL, 10);
int64_t cycleCount = ffStrbufToSInt(&tmpBuffer, 0);
result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount;
}
ffStrbufInit(&result->manufactureDate);
ffStrbufAppendS(dir, "/manufacture_year");
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (available)
{
int year = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (year > 0)
{
ffStrbufAppendS(dir, "/manufacture_month");
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (available)
{
int month = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (month > 0)
{
ffStrbufAppendS(dir, "/manufacture_day");
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (available)
{
int day = (int) ffStrbufToSInt(&tmpBuffer, 0);
if (day > 0)
{
ffStrbufSetF(&result->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
}
}
}
}
}
result->temperature = FF_BATTERY_TEMP_UNSET;
if (options->temp)
{
const FFlist* tempsResult = ffDetectTemps();
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
{
if (ffStrbufEqualS(&value->deviceName, id))
{
result->temperature = value->value;
break;
}
}
ffStrbufAppendS(dir, "/temp");
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
result->temperature = ffStrbufToDouble(&tmpBuffer) / 10;
ffStrbufSubstrBefore(dir, dirLength);
}
}
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
ffStrbufAppend(&baseDir, &options->dir);
ffStrbufEnsureEndsWithC(&baseDir, '/');
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
uint32_t baseDirLength = baseDir.length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
return "opendir(batteryDir) == NULL";
return "opendir(\"/sys/class/power_supply/\") == NULL";
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
@@ -122,7 +149,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
}
if(results->length == 0)
return "batteryDir doesn't contain any battery folder";
return "\"/sys/class/power_supply/\" doesn't contain any battery folder";
return NULL;
}
+108 -9
View File
@@ -1,6 +1,7 @@
#include "battery.h"
#include "util/windows/unicode.h"
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -75,19 +76,19 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
ffStrbufInitStatic(&battery->technology, "Lead Acid");
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
ffStrbufInitS(&battery->technology, "Lithium Ion");
ffStrbufInitStatic(&battery->technology, "Lithium Ion");
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
ffStrbufInitStatic(&battery->technology, "Nickel Cadmium");
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
ffStrbufInitStatic(&battery->technology, "Nickel Metal Hydride");
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
ffStrbufInitS(&battery->technology, "Nickel Zinc");
ffStrbufInitStatic(&battery->technology, "Nickel Zinc");
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
ffStrbufInitStatic(&battery->technology, "Rechargeable Alkaline-Manganese");
else
ffStrbufInitS(&battery->technology, "Unknown");
ffStrbufInitStatic(&battery->technology, "Unknown");
{
ffStrbufInit(&battery->modelName);
@@ -105,6 +106,22 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
ffStrbufSetWS(&battery->manufacturer, name);
}
{
ffStrbufInit(&battery->manufactureDate);
bqi.InformationLevel = BatteryManufactureDate;
BATTERY_MANUFACTURE_DATE date;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year + 1900, date.Month, date.Day);
}
{
ffStrbufInit(&battery->serial);
bqi.InformationLevel = BatterySerialNumber;
wchar_t name[64];
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
ffStrbufSetWS(&battery->serial, name);
}
battery->cycleCount = bi.CycleCount;
battery->temperature = 0.0/0.0;
@@ -113,7 +130,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
bqi.InformationLevel = BatteryTemperature;
ULONG temp;
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
battery->temperature = temp;
battery->temperature = temp / 10.0 - 273.15;
}
{
@@ -140,6 +157,83 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
return NULL;
}
typedef struct FFSmbiosPortableBattery
{
FFSmbiosHeader Header;
// 2.1+
uint8_t Location; // string
uint8_t Manufacturer; // string
uint8_t ManufactureDate; // string
uint8_t SerialNumber; // string
uint8_t DeviceName; // string
uint8_t DeviceChemistry; // enum
uint16_t DesignCapacity; // varies
uint16_t DesignVoltage; // varies
uint8_t SbdsVersionNumber; // string
uint8_t MaximumErrorInBatteryData; // varies
// 2.2+
uint16_t SbdsSerialNumber; // varies
uint16_t SbdsManufactureDate; // varies
uint8_t SbdsDeviceChemistry; // string
uint8_t DesignCapacityMultiplier; // varies
uint16_t OEMSpecific; // varies
} FFSmbiosPortableBattery;
const char* detectBySmbios(FFBatteryResult* battery)
{
const FFSmbiosPortableBattery* data = (const FFSmbiosPortableBattery*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PORTABLE_BATTERY];
if (!data)
return "Portable battery section is not found in SMBIOS data";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&battery->modelName, ffSmbiosLocateString(strings, data->DeviceName));
ffCleanUpSmbiosValue(&battery->modelName);
ffStrbufSetStatic(&battery->manufacturer, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&battery->manufacturer);
if (data->ManufactureDate)
{
ffStrbufSetStatic(&battery->manufactureDate, ffSmbiosLocateString(strings, data->ManufactureDate));
ffCleanUpSmbiosValue(&battery->manufactureDate);
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsManufactureDate))
{
uint16_t day = data->SbdsManufactureDate & 0b11111;
uint16_t month = (data->SbdsManufactureDate >> 5) & 0b1111;
uint16_t year = (data->SbdsManufactureDate >> 9) + 1800;
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
}
switch (data->DeviceChemistry)
{
case 0x01: ffStrbufSetStatic(&battery->technology, "Other"); break;
case 0x02: ffStrbufSetStatic(&battery->technology, "Unknown"); break;
case 0x03: ffStrbufSetStatic(&battery->technology, "Lead Acid"); break;
case 0x04: ffStrbufSetStatic(&battery->technology, "Nickel Cadmium"); break;
case 0x05: ffStrbufSetStatic(&battery->technology, "Nickel metal hydride"); break;
case 0x06: ffStrbufSetStatic(&battery->technology, "Lithium-ion"); break;
case 0x07: ffStrbufSetStatic(&battery->technology, "Zinc air"); break;
case 0x08: ffStrbufSetStatic(&battery->technology, "Lithium Polymer"); break;
}
if (data->SerialNumber)
{
ffStrbufSetStatic(&battery->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&battery->serial);
}
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsSerialNumber))
{
ffStrbufSetF(&battery->serial, "%4X", data->SbdsSerialNumber);
}
return NULL;
}
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
{
SYSTEM_BATTERY_STATE info;
@@ -148,8 +242,10 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->manufactureDate);
ffStrbufInit(&battery->technology);
ffStrbufInit(&battery->status);
ffStrbufInit(&battery->serial);
battery->temperature = FF_BATTERY_TEMP_UNSET;
battery->cycleCount = 0;
@@ -162,6 +258,9 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
}
else if(info.Discharging)
ffStrbufAppendS(&battery->status, "Discharging");
detectBySmbios(battery);
return NULL;
}
return "NtPowerInformation(SystemBatteryState) failed";
@@ -169,7 +268,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
return true
return options->useSetupApi
? detectWithSetupApi(options, results)
: detectWithNtApi(options, results);
}
+14
View File
@@ -2,6 +2,7 @@
#include "common/settings.h"
#include "common/sysctl.h"
#include "common/io/io.h"
#include "util/smbiosHelper.h"
const char* ffDetectBios(FFBiosResult* result)
@@ -15,5 +16,18 @@ const char* ffDetectBios(FFBiosResult* result)
ffSettingsGetFreeBSDKenv("smbios.bios.version", &result->version);
ffCleanUpSmbiosValue(&result->version);
ffSysctlGetString("machdep.bootmethod", &result->type);
if (result->type.length == 0)
{
if (ffSettingsGetFreeBSDKenv("loader.efi", &result->type))
ffStrbufSetStatic(&result->type, ffStrbufEqualS(&result->type, "1") ? "UEFI" : "BIOS");
else
{
ffStrbufSetStatic(&result->type,
ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) ||
ffPathExists("/boot/efi/efi" /*efi partition*/, FF_PATHTYPE_DIRECTORY)
? "UEFI" : "BIOS");
}
}
return NULL;
}
+32 -14
View File
@@ -1,5 +1,4 @@
#include "bios.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
#include <ntstatus.h>
@@ -26,27 +25,46 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
};
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
typedef struct FFSmbiosBios
{
FFSmbiosHeader Header;
uint8_t Vendor; // string
uint8_t BiosVersion; // string
uint16_t BiosStartingAddressSegment; // varies
uint8_t BiosReleaseDate; // string
uint8_t BiosRomSize; // string
uint32_t BiosCharacteristics; // bit field
// 2.4+
uint8_t BiosCharacteristicsExtensionBytes[2]; // bit field
uint8_t SystemBiosMajorRelease; // varies
uint8_t SystemBiosMinorRelease; // varies
uint8_t EmbeddedControllerFirmwareMajorRelease; // varies
uint8_t EmbeddedControllerFirmwareMinorRelease; // varies
// 3.1+
uint16_t ExtendedBiosRomSize; // bit field
} FFSmbiosBios;
const char* ffDetectBios(FFBiosResult* bios)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
const FFSmbiosBios* data = (const FFSmbiosBios*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_BIOS];
if (!data)
return "BIOS section is not found in SMBIOS data";
if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->version, NULL))
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSVersion\" doesn't exist";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&bios->version, ffSmbiosLocateString(strings, data->BiosVersion));
ffCleanUpSmbiosValue(&bios->version);
ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->vendor, NULL);
ffStrbufSetStatic(&bios->vendor, ffSmbiosLocateString(strings, data->Vendor));
ffCleanUpSmbiosValue(&bios->vendor);
ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->date, NULL);
ffStrbufSetStatic(&bios->date, ffSmbiosLocateString(strings, data->BiosReleaseDate));
ffCleanUpSmbiosValue(&bios->date);
uint32_t major, minor;
if(
ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) &&
ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL)
)
ffStrbufAppendF(&bios->release, "%u.%u", (unsigned)major, (unsigned)minor);
if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease))
ffStrbufSetF(&bios->release, "%u.%u", data->SystemBiosMajorRelease, data->SystemBiosMinorRelease);
// Same as GetFirmwareType, but support (?) Windows 7
// https://ntdoc.m417z.com/system_information_class
+1
View File
@@ -7,6 +7,7 @@ typedef struct FFBoardResult
FFstrbuf name;
FFstrbuf vendor;
FFstrbuf version;
FFstrbuf serial;
} FFBoardResult;
const char* ffDetectBoard(FFBoardResult* board);
+12 -4
View File
@@ -1,13 +1,21 @@
#include "board.h"
#include "common/sysctl.h"
#include "util/apple/cf_helpers.h"
const char* ffDetectBoard(FFBoardResult* result)
{
const char* error = ffSysctlGetString("hw.model", &result->name);
if (error)
return error;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice"));
if (!service)
return "No IOPlatformExpertDevice found";
io_name_t name;
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
ffStrbufSetS(&result->name, name);
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
if (manufacturer)
ffCfStrGetString(manufacturer, &result->vendor);
ffStrbufSetStatic(&result->vendor, "Apple");
return NULL;
}
+2
View File
@@ -6,6 +6,8 @@ const char* ffDetectBoard(FFBoardResult* result)
{
ffSettingsGetFreeBSDKenv("smbios.planar.product", &result->name);
ffCleanUpSmbiosValue(&result->name);
ffSettingsGetFreeBSDKenv("smbios.planar.serial", &result->serial);
ffCleanUpSmbiosValue(&result->serial);
ffSettingsGetFreeBSDKenv("smbios.planar.maker", &result->vendor);
ffCleanUpSmbiosValue(&result->vendor);
ffSettingsGetFreeBSDKenv("smbios.planar.version", &result->version);
+1
View File
@@ -7,6 +7,7 @@
const char* ffDetectBoard(FFBoardResult* board)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_serial", "/sys/class/dmi/id/board_serial", &board->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
return NULL;
+26 -9
View File
@@ -1,21 +1,38 @@
#include "board.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
typedef struct FFSmbiosBaseboard
{
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t Product; // string
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTag; // string
uint8_t FeatureFlags; // bit field
uint8_t LocationInChassis; // string
uint16_t ChassisHandle; // varies
uint8_t BoardType; // enum
uint8_t NumberOfContainedObjectHandle; // varies
uint16_t ContainedObjectHandle[]; // varies
} FFSmbiosBaseboard;
const char* ffDetectBoard(FFBoardResult* board)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
const FFSmbiosBaseboard* data = (const FFSmbiosBaseboard*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_BASEBOARD_INFO];
if (!data)
return "Baseboard information section is not found in SMBIOS data";
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\") failed";
if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->name, NULL))
return "ffRegReadStrbuf(hKey, L\"BaseBoardProduct\") failed";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&board->name, ffSmbiosLocateString(strings, data->Product));
ffCleanUpSmbiosValue(&board->name);
ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->vendor, NULL);
ffStrbufSetStatic(&board->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&board->serial);
ffStrbufSetStatic(&board->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&board->vendor);
ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->version, NULL);
ffStrbufSetStatic(&board->version, ffSmbiosLocateString(strings, data->Version));
ffCleanUpSmbiosValue(&board->version);
return NULL;
+22 -22
View File
@@ -57,35 +57,35 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
return "IOAVService is not available";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = NULL;
{
IOObjectRelease(registryEntry);
continue;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryAv = registryEntry;
FF_CFTYPE_AUTO_RELEASE CFBooleanRef IOAVServiceUserInterfaceSupported = IORegistryEntryCreateCFProperty(entryAv, CFSTR("IOAVServiceUserInterfaceSupported"), kCFAllocatorDefault, kNilOptions);
if (IOAVServiceUserInterfaceSupported && !CFBooleanGetValue(IOAVServiceUserInterfaceSupported))
{
// IOAVServiceCreateWithService won't work
continue;
}
FF_CFTYPE_AUTO_RELEASE CFStringRef location = IORegistryEntryCreateCFProperty(entryAv, CFSTR("Location"), kCFAllocatorDefault, kNilOptions);
if (location && CFStringCompare(location, CFSTR("Embedded"), 0) == 0)
{
// Builtin display should be handled by DisplayServices
continue;
}
service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
if (!service) continue;
}
ffStrbufClear(&location);
if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded"))
{
// Builtin display should be handled by DisplayServices
IOObjectRelease(registryEntry);
continue;
}
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
IOObjectRelease(registryEntry);
if (!service) continue;
{
uint8_t i2cIn[4] = { 0x82, 0x01, 0x10 /* luminance */ };
i2cIn[3] = 0x6e ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2];
@@ -36,6 +36,8 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
struct backlight_info info;
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
ffStrbufAppendS(&brightness->name, info.name);
else
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
}
return NULL;
}
+2 -2
View File
@@ -2,9 +2,9 @@
const char* ffChassisTypeToString(uint32_t type)
{
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.0.pdf
// 7.4.1 System Enclosure or Chassis Types
switch (type)
switch (type & 0b01111111)
{
case 0x01: return "Other";
case 0x02: return "Unknown";
+2 -1
View File
@@ -5,9 +5,10 @@
typedef struct FFChassisResult
{
FFstrbuf type;
FFstrbuf serial;
FFstrbuf vendor;
FFstrbuf version;
} FFChassisResult;
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options);
const char* ffDetectChassis(FFChassisResult* result);
const char* ffChassisTypeToString(uint32_t type);
+3 -1
View File
@@ -2,13 +2,15 @@
#include "common/settings.h"
#include "util/smbiosHelper.h"
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
const char* ffDetectChassis(FFChassisResult* result)
{
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
ffCleanUpSmbiosValue(&result->type);
ffSettingsGetFreeBSDKenv("smbios.chassis.maker", &result->vendor);
ffCleanUpSmbiosValue(&result->vendor);
ffSettingsGetFreeBSDKenv("smbios.chassis.serial", &result->serial);
ffCleanUpSmbiosValue(&result->serial);
ffSettingsGetFreeBSDKenv("smbios.chassis.version", &result->version);
ffCleanUpSmbiosValue(&result->version);
return NULL;
+2 -1
View File
@@ -4,9 +4,10 @@
#include <stdlib.h>
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
const char* ffDetectChassis(FFChassisResult* result)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version);
+1 -1
View File
@@ -1,6 +1,6 @@
#include "chassis.h"
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
{
return "Not supported on this platform";
}
+47
View File
@@ -0,0 +1,47 @@
#include "chassis.h"
#include "util/smbiosHelper.h"
// 7.4
typedef struct FFSmbiosSystemEnclosure
{
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t Type; // varies
uint8_t Version; // string
uint8_t SerialNumber; // string
uint8_t AssetTagNumber; // string
// 2.1+
uint8_t BootupState; // enum
uint8_t PowerSupplyState; // enum
uint8_t ThermalState; // enum
uint8_t SecurityStatus; // enum
// 2.3+
uint32_t OEMDefined; // varies
uint8_t Height; // varies
uint8_t NumberOfPowerCords; // varies
uint8_t ContainedElementCount; // varies
uint8_t ContainedRecordLength; // varies
uint8_t ContainedElements[]; // varies
} FFSmbiosSystemEnclosure;
const char* ffDetectChassis(FFChassisResult* result)
{
const FFSmbiosSystemEnclosure* data = (const FFSmbiosSystemEnclosure*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE];
if (!data)
return "System enclosure is not found in SMBIOS data";
const char* strings = (const char*) data + data->Header.Length;
ffStrbufSetStatic(&result->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&result->vendor);
ffStrbufSetStatic(&result->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&result->serial);
ffStrbufSetStatic(&result->version, ffSmbiosLocateString(strings, data->Version));
ffCleanUpSmbiosValue(&result->version);
ffStrbufSetStatic(&result->type, ffChassisTypeToString(data->Type));
return NULL;
}
-73
View File
@@ -1,73 +0,0 @@
extern "C" {
#include "chassis.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
}
#include "util/windows/unicode.hpp"
#include "util/windows/wmi.hpp"
static const char* detectWithRegistry(FFChassisResult* result)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL)) // SMBIOS
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
uint32_t type = 0;
if(!ffRegReadUint(hKey, L"EnclosureType", &type, NULL))
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\EnclosureType\" doesn't exist";
const char* typeStr = ffChassisTypeToString(type);
if(!typeStr)
return "Unknown chassis type";
ffStrbufAppendS(&result->type, typeStr);
return NULL;
}
FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
{
FFWmiQuery query(L"SELECT Version, ChassisTypes, Manufacturer FROM Win32_SystemEnclosure");
if (!query)
return "Query WMI service failed";
if (FFWmiRecord record = query.next())
{
if (auto vtProp = record.get(L"ChassisTypes"))
{
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
if(len == 0)
return "ChassisTypes contain no data";
for (uint32_t i = 0; i < len; ++i)
{
if (i > 0)
ffStrbufAppendS(&result->type, ", ");
ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) arr[i]));
}
}
else
return "Get ChassisTypes failed";
if (auto vtProp = record.get(L"Version"))
{
ffStrbufSetWSV(&result->version, vtProp.get<std::wstring_view>());
ffCleanUpSmbiosValue(&result->version);
}
if (auto vtProp = record.get(L"Manufacturer"))
{
ffStrbufSetWSV(&result->vendor, vtProp.get<std::wstring_view>());
ffCleanUpSmbiosValue(&result->vendor);
}
return NULL;
}
return "No WMI result returned";
}
extern "C"
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
{
if (options->useWmi)
return detectWithWmi(result);
return detectWithRegistry(result);
}
+23 -33
View File
@@ -1,6 +1,7 @@
#include "cpu.h"
#include "common/sysctl.h"
#include "detection/temps/temps_apple.h"
#include "util/stringUtils.h"
static double detectCpuTemp(const FFstrbuf* cpuName)
{
@@ -35,44 +36,33 @@ static const char* detectFrequency(FFCPUResult* cpu)
{
// https://github.com/giampaolo/psutil/pull/2222/files
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
if (!entryDevice)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if (IORegistryEntryCreateCFProperties(entryDevice, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
return "IORegistryEntryCreateCFProperties() failed";
uint32_t pMin, eMin, aMax, pCoreLength;
if (ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength) != NULL) // pCore
return "\"voltage-states5-sram\" in \"pmgr\" is not found";
if (ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL) != NULL) // eCore
return "\"voltage-states1-sram\" in \"pmgr\" is not found";
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
io_name_t name;
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
continue;
if (strcmp(name, "pmgr") != 0)
continue;
uint32_t pMin, eMin, aMax, pCoreLength;
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
CFRelease(properties);
IOObjectRelease(registryEntry);
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
IOObjectRelease(iterator);
return NULL;
}
#else
+85 -2
View File
@@ -2,8 +2,81 @@
#include "detection/temps/temps_windows.h"
#include "util/windows/registry.h"
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
// 7.5
typedef struct FFSmbiosProcessorInfo
{
FFSmbiosHeader Header;
uint8_t SocketDesignation; // string
uint8_t ProcessorType; // enum
uint8_t ProcessorFamily; // enum
uint8_t ProcessorManufacturer; // string
uint64_t ProcessorID; // varies
uint8_t ProcessorVersion; // string
uint8_t Voltage; // varies
uint16_t ExternalClock; // varies
uint16_t MaxSpeed; // varies
uint16_t CurrentSpeed; // varies
uint8_t Status; // varies
uint8_t ProcessorUpgrade; // enum
// 2.1+
uint16_t L1CacheHandle; // varies
uint16_t L2CacheHandle; // varies
uint16_t L3CacheHandle; // varies
// 2.3+
uint8_t SerialNumber; // string
uint8_t AssertTag; // string
uint8_t PartNumber; // string
// 2.5+
uint8_t CoreCount; // varies
uint8_t CoreEnabled; // varies
uint8_t ThreadCount; // varies
uint16_t ProcessorCharacteristics; // bit field
// 2.6+
uint16_t ProcessorFamily2; // enum
// 3.0+
uint16_t CoreCount2; // varies
uint16_t CoreEnabled2; // varies
uint16_t ThreadCount2; // varies
// 3.6+
uint16_t ThreadEnabled; // varies
} FFSmbiosProcessorInfo;
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
{
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO];
if (!data)
return "Processor information is not found in SMBIOS data";
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
{
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
return "No active CPU is found in SMBIOS data";
}
double speed;
if (data->MaxSpeed > 0 && data->MaxSpeed < 30000) // VMware reports weird values
speed = data->MaxSpeed / 1000.0;
else
speed = data->CurrentSpeed / 1000.0;
if (cpu->frequencyMax < speed)
cpu->frequencyMax = speed;
return NULL;
}
static const char* detectByOS(FFCPUResult* cpu)
{
{
DWORD length = 0;
@@ -42,14 +115,24 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
uint32_t mhz;
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
cpu->frequencyMax = mhz / 1000.0;
cpu->frequencyMin = cpu->frequencyMax = mhz / 1000.0;
}
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
return NULL;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
const char* error = detectByOS(cpu);
if (error)
return error;
if(options->temp)
ffDetectSmbiosTemp(&cpu->temperature, NULL);
detectMaxSpeedBySmbios(cpu);
return NULL;
}
+2 -10
View File
@@ -8,22 +8,14 @@
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
@@ -129,8 +129,9 @@ static void detectDisplays(FFDisplayServerResult* ds)
(uint32_t) (monitorInfo->info.rcMonitor.bottom - monitorInfo->info.rcMonitor.top),
rotation,
&name,
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER ? FF_DISPLAY_TYPE_UNKNOWN :
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED
? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL,
!!(monitorInfo->info.dwFlags & MONITORINFOF_PRIMARY),
@@ -1,5 +1,8 @@
#include "displayserver_linux.h"
#include "common/io/io.h"
#ifdef __FreeBSD__
#include "common/settings.h"
#endif
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
@@ -31,6 +34,26 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
if(ds->displays.length == 0)
ffdsConnectDrm(ds);
#ifdef __FreeBSD__
if(ds->displays.length == 0)
{
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if (ffSettingsGetFreeBSDKenv("screen.width", &buf))
{
uint32_t width = (uint32_t) ffStrbufToUInt(&buf, 0);
if (width)
{
ffStrbufClear(&buf);
if (ffSettingsGetFreeBSDKenv("screen.height", &buf))
{
uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0);
ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0);
}
}
}
}
#endif
//This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(ds);
}
+2 -1
View File
@@ -4,8 +4,9 @@
typedef struct FFGamepadDevice
{
FFstrbuf identifier;
FFstrbuf serial;
FFstrbuf name;
uint8_t battery; // 0-100%
} FFGamepadDevice;
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */);
+39 -15
View File
@@ -1,18 +1,34 @@
#include "gamepad.h"
#include "util/apple/cf_helpers.h"
#include "util/mallocHelper.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
static void enumSet(const void* value, void *context)
static void enumSet(IOHIDDeviceRef value, FFlist* results)
{
CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey));
CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey));
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context);
ffStrbufInit(&device->identifier);
ffCfStrGetString(serialNumber, &device->identifier);
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(results);
ffStrbufInit(&device->serial);
ffStrbufInit(&device->name);
ffCfStrGetString(product, &device->name);
device->battery = 0;
CFStringRef manufacturer = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDManufacturerKey));
ffCfStrGetString(manufacturer, &device->name);
CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey));
if (device->name.length)
{
ffCfStrGetString(product, &device->serial);
ffStrbufAppendC(&device->name, ' ');
ffStrbufAppend(&device->name, &device->serial);
}
else
{
ffCfStrGetString(product, &device->name);
}
CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey));
ffCfStrGetString(serialNumber, &device->serial);
}
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
@@ -21,21 +37,29 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
return "IOHIDManagerOpen() failed";
CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop);
CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFSTR(kIOHIDDeviceUsagePageKey),
CFSTR(kIOHIDDeviceUsageKey)
}, (const void **)(CFNumberRef[]){
genericDesktop,
gamePad
ffCfCreateInt(kHIDPage_GenericDesktop),
ffCfCreateInt(kHIDUsage_GD_Joystick)
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
IOHIDManagerSetDeviceMatching(manager, matching);
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching2 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
CFSTR(kIOHIDDeviceUsagePageKey),
CFSTR(kIOHIDDeviceUsageKey)
}, (const void **)(CFNumberRef[]){
ffCfCreateInt(kHIDPage_GenericDesktop),
ffCfCreateInt(kHIDUsage_GD_GamePad)
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFArrayRef FF_CFTYPE_AUTO_RELEASE matchings = CFArrayCreate(kCFAllocatorDefault, (const void **)(CFTypeRef[]){
matching1, matching2
}, 2, &kCFTypeArrayCallBacks);
IOHIDManagerSetDeviceMatchingMultiple(manager, matchings);
CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
if (set)
CFSetApplyFunction(set, &enumSet, devices);
IOHIDManagerClose(manager, 0);
CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices);
IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
return NULL;
}
+2 -1
View File
@@ -42,8 +42,9 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1)
{
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, di.udi_serial);
ffStrbufInitS(&device->serial, di.udi_serial);
ffStrbufInitF(&device->name, "%s %s", di.udi_vendor, di.udi_product);
device->battery = 0;
}
}
}
+62 -13
View File
@@ -5,39 +5,88 @@
#include <dirent.h>
#include <ctype.h>
static void detectGamepad(FFlist* devices, FFstrbuf* name, FFstrbuf* path)
{
uint32_t baseLen = path->length;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInit(&device->serial);
ffStrbufInitMove(&device->name, name);
device->battery = 0;
ffStrbufAppendS(path, "uniq");
if (ffAppendFileBuffer(path->chars, &device->serial))
ffStrbufTrimRightSpace(&device->serial);
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "device/power_supply/"); // /sys/class/input/jsX/device/device/power_supply
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path->chars);
if (dirp)
{
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.' || (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN))
continue;
ffStrbufAppendS(path, entry->d_name);
ffStrbufAppendS(path, "/capacity"); // /sys/class/input/jsX/device/device/power_supply/XXX/capacity
char capacity[32];
ssize_t nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
if (nRead > 0) // Tested with a PS4 controller
{
capacity[nRead] = '\0';
device->battery = (uint8_t) strtoul(capacity, NULL, 10);
break;
}
ffStrbufAppendS(path, "_level");
nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
if (nRead > 0) // Tested with a NS Pro controller
{
// https://github.com/torvalds/linux/blob/52b1853b080a082ec3749c3a9577f6c71b1d4a90/drivers/power/supply/power_supply_sysfs.c#L124
switch (capacity[0])
{
case 'C': device->battery = 1; break; // Critical
case 'L': device->battery = 25; break; // Low
case 'N': device->battery = 50; break; // Normal
case 'H': device->battery = 75; break; // High
case 'F': device->battery = 100; break; // Full
}
}
}
}
}
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
{
DIR* dirp = opendir("/sys/class/input/");
if(dirp == NULL)
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/");
if (dirp == NULL)
return "opendir(\"/sys/class/input/\") == NULL";
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/");
uint32_t baseLen = path.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
while ((entry = readdir(dirp)) != NULL)
{
if(!ffStrStartsWith(entry->d_name, "js"))
if (!ffStrStartsWith(entry->d_name, "js"))
continue;
if(!isdigit(entry->d_name[2]))
if (!isdigit(entry->d_name[2]))
continue;
ffStrbufAppendS(&path, entry->d_name);
ffStrbufAppendS(&path, "/device/name");
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
if (ffAppendFileBuffer(path.chars, &name))
{
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, entry->d_name);
ffStrbufInit(&device->name);
if (ffAppendFileBuffer(path.chars, &device->name))
ffStrbufTrimRightSpace(&device->name);
ffStrbufTrimRightSpace(&name);
ffStrbufSubstrBefore(&path, path.length - 4);
detectGamepad(devices, &name, &path);
}
ffStrbufSubstrBefore(&path, baseLen);
}
closedir(dirp);
return NULL;
}
+90 -37
View File
@@ -3,10 +3,11 @@
#include "util/mallocHelper.h"
#include "util/windows/unicode.h"
#include <winternl.h>
#include <windows.h>
#include <hidsdi.h>
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
static const char* detectKnownDeviceName(uint32_t vendorId, uint32_t productId)
{
switch (vendorId)
{
@@ -30,38 +31,14 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
{
switch (productId)
{
case 0x0268: return "Sony Playstation 3 Controller";
case 0x0268: return "Sony DualShock 3 / Six Axis";
case 0x05C4: return "Sony DualShock 4 Gen1";
case 0x09CC: return "Sony DualShock 4 Gen2";
case 0x0BA0: return "Sony PS4 Controller USB receiver";
case 0x0BA0: return "Sony DualShock 4 USB receiver";
case 0x0CE6: return "Sony DualSense";
default: return NULL;
}
}
// Microsoft
case 0x045E:
{
switch (productId)
{
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
case 0x028E: return "Microsoft XBox 360";
case 0x028F: return "Microsoft XBox 360 v2";
case 0x02A1: return "Microsoft XBox 360";
case 0x0291: return "Microsoft XBox 360 USB receiver";
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
case 0x02DD: return "Microsoft XBox One";
case 0xB326: return "Microsoft XBox One Firmware 2015";
case 0x02E3: return "Microsoft XBox One Elite";
case 0x02FF: return "Microsoft XBox One Elite";
case 0x02EA: return "Microsoft XBox One S";
case 0x0DF2: return "Sony DualSense Edge";
default: return NULL;
}
@@ -83,6 +60,7 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
}
}
case 0x045E: // Microsoft Xbox compatible controllers should be handled by Windows without problems
default: return NULL;
}
}
@@ -98,7 +76,8 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
for (UINT i = 0; i < nDevices; ++i) {
for (UINT i = 0; i < nDevices; ++i)
{
if (pRawInputDeviceList[i].dwType != 2) continue;
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
@@ -117,20 +96,94 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
continue;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitWS(&device->identifier, devName);
ffStrbufInit(&device->serial);
ffStrbufInit(&device->name);
device->battery = 0;
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
const char* knownGamepad = detectKnownDeviceName(rdi.hid.dwVendorId, rdi.hid.dwProductId);
if (knownGamepad)
ffStrbufSetS(&device->name, knownGamepad);
else
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (!hHidFile)
{
if (!knownGamepad)
ffStrbufSetF(&device->name, "Unknown gamepad %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
continue;
}
if (!knownGamepad)
{
wchar_t displayName[126];
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
ffStrbufSetWS(&device->name, displayName);
else
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
if (HidD_GetProductString(hHidFile, displayName, sizeof(displayName)))
{
wchar_t manufacturer[126];
if (HidD_GetManufacturerString(hHidFile, manufacturer, sizeof(manufacturer)))
{
ffStrbufSetWS(&device->name, manufacturer);
FF_STRBUF_AUTO_DESTROY displayNameStr = ffStrbufCreateWS(displayName);
ffStrbufAppendC(&device->name, ' ');
ffStrbufAppend(&device->name, &displayNameStr);
}
else
{
ffStrbufSetWS(&device->name, displayName);
}
}
}
PHIDP_PREPARSED_DATA preparsedData = NULL;
if (HidD_GetPreparsedData(hHidFile, &preparsedData))
{
HIDP_CAPS caps;
NTSTATUS capsResult = HidP_GetCaps(preparsedData, &caps);
HidD_FreePreparsedData(preparsedData);
if (!NT_SUCCESS(capsResult))
continue;
wchar_t serialNumber[127] = L"";
if (HidD_GetSerialNumberString(hHidFile, serialNumber, sizeof(serialNumber)))
ffStrbufSetWS(&device->serial, serialNumber);
if (
(rdi.hid.dwVendorId == 0x054C && (
rdi.hid.dwProductId == 0x05C4 || // PS4 Gen1
rdi.hid.dwProductId == 0x09CC // PS4 Gen2
)) ||
(rdi.hid.dwVendorId == 0x057E && (
rdi.hid.dwProductId == 0x2009 // NS Pro
))
)
{
// Controller must be connected by other programs
FF_AUTO_FREE uint8_t* reportBuffer = malloc(caps.InputReportByteLength);
OVERLAPPED overlapped = { };
DWORD nBytes;
if (ReadFile(hHidFile, reportBuffer, caps.InputReportByteLength, &nBytes, &overlapped) ||
(WaitForSingleObject(hHidFile, FF_IO_TERM_RESP_WAIT_MS) == WAIT_OBJECT_0 && GetOverlappedResult(hHidFile, &overlapped, &nBytes, FALSE)))
{
if (rdi.hid.dwVendorId == 0x054C)
{
if (nBytes > 31)
{
uint8_t batteryInfo = reportBuffer[caps.InputReportByteLength == 64 /*USB?*/ ? 30 : 32];
device->battery = (uint8_t) ((batteryInfo & 0x0f) * 100 / (batteryInfo & 0x10 /*charging?*/ ? 11 /*BATTERY_MAX_USB*/ : 8 /*BATTERY_MAX*/));
if (device->battery > 100) device->battery = 100;
}
}
else
{
if (nBytes > 3 && reportBuffer[0] == 0x30)
{
uint8_t batteryInfo = reportBuffer[2];
device->battery = (uint8_t) (((batteryInfo & 0xE0) >> 4) * 100 / 8);
if (device->battery == 0) device->battery = 1;
else if (device->battery > 100) device->battery = 100;
}
}
}
else
CancelIo(hHidFile);
}
}
}
+6 -4
View File
@@ -73,15 +73,17 @@ const char* detectByOpenGL(FFlist* gpus)
if (!gpu->vendor.length)
{
if (ffStrbufContainS(&result.renderer, "Apple"))
if (ffStrbufContainS(&gpu->name, "Apple"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
else if (ffStrbufContainS(&result.renderer, "Intel"))
else if (ffStrbufContainS(&gpu->name, "Intel"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
else if (ffStrbufContainS(&result.renderer, "AMD") || ffStrbufContainS(&result.renderer, "ATI"))
else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
else if (ffStrbufContainS(&result.renderer, "NVIDIA"))
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
}
if (ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE))
gpu->type = FF_GPU_TYPE_INTEGRATED;
}
ffStrbufDestroy(&result.version);
+3 -5
View File
@@ -38,12 +38,12 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
@@ -106,8 +106,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
ffGpuDetectMetal(gpus);
return NULL;
}
+15 -4
View File
@@ -15,7 +15,7 @@ const char* ffGpuDetectMetal(FFlist* gpus)
FFGPUResult* gpu = NULL;
FF_LIST_FOR_EACH(FFGPUResult, x, *gpus)
{
if (x->deviceId == device.registryID || ffStrbufEqualS(&x->name, device.name.UTF8String))
if (x->deviceId == device.registryID)
{
gpu = x;
break;
@@ -32,9 +32,20 @@ const char* ffGpuDetectMetal(FFlist* gpus)
else if ([device supportsFamily:MTLGPUFamilyCommon1])
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
if (gpu->type == device.hasUnifiedMemory)
{
gpu->type = FF_GPU_TYPE_INTEGRATED;
gpu->shared.total = device.recommendedMaxWorkingSetSize;
gpu->shared.used = device.currentAllocatedSize;
}
else
{
gpu->type = FF_GPU_TYPE_DISCRETE;
gpu->dedicated.total = device.recommendedMaxWorkingSetSize;
gpu->dedicated.used = device.currentAllocatedSize;
}
}
return NULL;
}
return NULL;
return "Metal API is not supported by this macOS version";
}
+6 -1
View File
@@ -1,7 +1,10 @@
#include "detection/gpu/gpu.h"
#include "detection/gpu/gpu_driver_specific.h"
#include "detection/vulkan/vulkan.h"
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
#include "detection/gpu/gpu_driver_specific.h"
#endif
#ifdef FF_HAVE_LIBPCI
#include "common/io/io.h"
#include "common/library.h"
@@ -245,6 +248,7 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
{
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
@@ -266,6 +270,7 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
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;
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
#ifdef __linux__
if(options->temp && gpu->temperature != gpu->temperature)
+20
View File
@@ -12,6 +12,7 @@ struct FFNvmlData {
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
FF_LIBRARY_SYMBOL(nvmlDeviceGetClockInfo)
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
bool inited;
} nvmlData;
@@ -32,6 +33,7 @@ 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, nvmlDeviceGetClockInfo)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
if (ffnvmlInit_v2() != NVML_SUCCESS)
{
@@ -79,6 +81,24 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
if (!device) return "Device not found";
}
nvmlBrandType_t brand;
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
{
switch (brand)
{
case NVML_BRAND_NVIDIA_RTX:
case NVML_BRAND_QUADRO_RTX:
case NVML_BRAND_GEFORCE:
case NVML_BRAND_TITAN:
case NVML_BRAND_TESLA:
case NVML_BRAND_QUADRO:
*result.type = FF_GPU_TYPE_DISCRETE;
break;
default:
break;
}
}
if (result.temp)
{
uint32_t value;
+8 -1
View File
@@ -1,8 +1,11 @@
#include "gpu.h"
#include "detection/gpu/gpu_driver_specific.h"
#include "util/windows/unicode.h"
#include "util/windows/registry.h"
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
#include "detection/gpu/gpu_driver_specific.h"
#endif
#include <inttypes.h>
static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
@@ -10,6 +13,7 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
return ffStrbufEqual(&gpu->name, name);
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
{
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
@@ -44,6 +48,7 @@ static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&
return true;
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
@@ -139,6 +144,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
}
}
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
const char* dllName;
@@ -168,6 +174,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
);
}
}
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
}
return NULL;
+2
View File
@@ -98,6 +98,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
ffStrbufSetStatic(&gpu->vendor, vendorStr);
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && (options->driverSpecific || options->temp))
{
FFGpuDriverCondition cond = {
@@ -117,6 +118,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
.frequency = &gpu->frequency,
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
}
#endif
}
}
+7 -5
View File
@@ -4,11 +4,13 @@
typedef struct FFHostResult
{
FFstrbuf productFamily;
FFstrbuf productName;
FFstrbuf productVersion;
FFstrbuf productSku;
FFstrbuf sysVendor;
FFstrbuf family;
FFstrbuf name;
FFstrbuf version;
FFstrbuf sku;
FFstrbuf serial;
FFstrbuf uuid;
FFstrbuf vendor;
} FFHostResult;
const char* ffDetectHost(FFHostResult* host);
+17 -17
View File
@@ -5,32 +5,32 @@
const char* ffDetectHost(FFHostResult* host)
{
// http://newandroidbook.com/ddb/
ffSettingsGetAndroidProperty("ro.product.device", &host->productFamily);
ffSettingsGetAndroidProperty("ro.product.device", &host->family);
ffSettingsGetAndroidProperty("ro.product.marketname", &host->productName)
|| ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->productName)
|| ffSettingsGetAndroidProperty("ro.config.devicename", &host->productName)
|| ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->productName)
|| ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->productName)
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->productName)
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->productName)
|| ffSettingsGetAndroidProperty("ro.product.brand", &host->productName);
ffSettingsGetAndroidProperty("ro.product.marketname", &host->name)
|| ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->name)
|| ffSettingsGetAndroidProperty("ro.config.devicename", &host->name)
|| ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name)
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name)
|| ffSettingsGetAndroidProperty("ro.product.brand", &host->name);
if (ffSettingsGetAndroidProperty("ro.product.model", &host->productVersion))
if (ffSettingsGetAndroidProperty("ro.product.model", &host->version))
{
if (ffStrbufStartsWithIgnCase(&host->productVersion, &host->productName))
if (ffStrbufStartsWithIgnCase(&host->version, &host->name))
{
ffStrbufSubstrAfter(&host->productVersion, host->productName.length);
ffStrbufTrimLeft(&host->productVersion, ' ');
ffStrbufSubstrAfter(&host->version, host->name.length);
ffStrbufTrimLeft(&host->version, ' ');
}
}
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->sysVendor);
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->vendor);
if(host->sysVendor.length && !ffStrbufStartsWithIgnCase(&host->productName, &host->sysVendor))
if(host->vendor.length && !ffStrbufStartsWithIgnCase(&host->name, &host->vendor))
{
ffStrbufPrependS(&host->productName, " ");
ffStrbufPrepend(&host->productName, &host->sysVendor);
ffStrbufPrependS(&host->name, " ");
ffStrbufPrepend(&host->name, &host->vendor);
}
return NULL;
+33 -25
View File
@@ -169,40 +169,48 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel)
const char* getProductNameWithIokit(FFstrbuf* result)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("product"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("product"));
if (!registryEntry)
return "IOServiceGetMatchingService() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
FF_CFTYPE_AUTO_RELEASE CFStringRef productName = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("product-name"), kCFAllocatorDefault, kNilOptions);
if (!productName)
return "IORegistryEntryCreateCFProperty() failed";
if (ffCfDictGetString(properties, CFSTR("product-name"), result))
break;
}
return ffCfStrGetString(productName, result);
}
const char* getOthersByIokit(FFHostResult* host)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice"));
if (!registryEntry)
return "IOServiceGetMatchingService() failed";
FF_CFTYPE_AUTO_RELEASE CFStringRef serialNumber = IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, kNilOptions);
if (serialNumber)
ffCfStrGetString(serialNumber, &host->serial);
FF_CFTYPE_AUTO_RELEASE CFStringRef uuid = IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, kNilOptions);
if (uuid)
ffCfStrGetString(uuid, &host->uuid);
FF_CFTYPE_AUTO_RELEASE CFStringRef manufacturer = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
if (manufacturer)
ffCfStrGetString(manufacturer, &host->vendor);
IOObjectRelease(registryEntry);
return NULL;
}
const char* ffDetectHost(FFHostResult* host)
{
ffStrbufSetStatic(&host->sysVendor, "Apple");
const char* error = ffSysctlGetString("hw.model", &host->productFamily);
const char* error = ffSysctlGetString("hw.model", &host->family);
if (error) return error;
ffStrbufSetStatic(&host->productName, getProductNameWithHwModel(&host->productFamily));
if (host->productName.length == 0)
getProductNameWithIokit(&host->productName);
if (host->productName.length == 0)
ffStrbufSet(&host->productName, &host->productFamily);
ffStrbufSetStatic(&host->name, getProductNameWithHwModel(&host->family));
if (host->name.length == 0)
getProductNameWithIokit(&host->name);
if (host->name.length == 0)
ffStrbufSet(&host->name, &host->family);
getOthersByIokit(host);
return NULL;
}
+14 -10
View File
@@ -4,16 +4,20 @@
const char* ffDetectHost(FFHostResult* host)
{
ffSettingsGetFreeBSDKenv("smbios.system.product", &host->productName);
ffCleanUpSmbiosValue(&host->productName);
ffSettingsGetFreeBSDKenv("smbios.system.family", &host->productFamily);
ffCleanUpSmbiosValue(&host->productFamily);
ffSettingsGetFreeBSDKenv("smbios.system.version", &host->productVersion);
ffCleanUpSmbiosValue(&host->productVersion);
ffSettingsGetFreeBSDKenv("smbios.system.sku", &host->productSku);
ffCleanUpSmbiosValue(&host->productSku);
ffSettingsGetFreeBSDKenv("smbios.system.maker", &host->sysVendor);
ffCleanUpSmbiosValue(&host->sysVendor);
ffSettingsGetFreeBSDKenv("smbios.system.product", &host->name);
ffCleanUpSmbiosValue(&host->name);
ffSettingsGetFreeBSDKenv("smbios.system.family", &host->family);
ffCleanUpSmbiosValue(&host->family);
ffSettingsGetFreeBSDKenv("smbios.system.version", &host->version);
ffCleanUpSmbiosValue(&host->version);
ffSettingsGetFreeBSDKenv("smbios.system.sku", &host->sku);
ffCleanUpSmbiosValue(&host->sku);
ffSettingsGetFreeBSDKenv("smbios.system.serial", &host->serial);
ffCleanUpSmbiosValue(&host->serial);
ffSettingsGetFreeBSDKenv("smbios.system.uuid", &host->uuid);
ffCleanUpSmbiosValue(&host->uuid);
ffSettingsGetFreeBSDKenv("smbios.system.maker", &host->vendor);
ffCleanUpSmbiosValue(&host->vendor);
return NULL;
}
+54 -26
View File
@@ -7,48 +7,76 @@
static void getHostProductName(FFstrbuf* name)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name);
if(name->length > 0)
return;
if (ffReadFileBuffer("/sys/firmware/devicetree/base/model", name))
{
ffStrbufTrimRightSpace(name);
ffStrbufTrimRight(name, '\0');
if(ffIsSmbiosValueSet(name))
return;
}
ffReadFileBuffer("/sys/firmware/devicetree/base/model", name);
if(ffIsSmbiosValueSet(name))
return;
if (ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name))
{
ffStrbufTrimRightSpace(name);
ffStrbufTrimRight(name, '\0');
if(ffIsSmbiosValueSet(name))
return;
}
ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name);
if(ffIsSmbiosValueSet(name))
return;
//does a clear before the read
ffReadFileBuffer("/tmp/sysinfo/model", name);
if(ffIsSmbiosValueSet(name))
return;
if (ffReadFileBuffer("/tmp/sysinfo/model", name))
{
ffStrbufTrimRightSpace(name);
ffStrbufTrimRight(name, '\0');
if(ffIsSmbiosValueSet(name))
return;
}
ffStrbufClear(name);
}
static void getHostSerialNumber(FFstrbuf* serial)
{
if (ffReadFileBuffer("/sys/firmware/devicetree/base/serial-number", serial))
{
ffStrbufTrimRightSpace(serial);
ffStrbufTrimRight(serial, '\0');
if(ffIsSmbiosValueSet(serial))
return;
}
ffStrbufClear(serial);
}
const char* ffDetectHost(FFHostResult* host)
{
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
getHostProductName(&host->productName);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->family);
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &host->name))
getHostProductName(&host->name);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->version);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->sku);
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_serial", "/sys/class/dmi/id/product_serial", &host->serial))
getHostSerialNumber(&host->serial);
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_uuid", "/sys/class/dmi/id/product_uuid", &host->uuid);
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->vendor))
{
if (ffStrbufStartsWithS(&host->name, "Apple "))
ffStrbufSetStatic(&host->vendor, "Apple Inc.");
}
//KVM/Qemu virtual machine
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
if(ffStrbufStartsWithS(&host->name, "Standard PC"))
ffStrbufPrependS(&host->name, "KVM/QEMU ");
if(host->productFamily.length == 0 && host->productName.length == 0)
if(host->family.length == 0 && host->name.length == 0)
{
const char* wslDistroName = getenv("WSL_DISTRO_NAME");
//On WSL, the real host can't be detected. Instead use WSL as host.
if(wslDistroName != NULL || getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
{
ffStrbufAppendS(&host->productName, "Windows Subsystem for Linux");
ffStrbufAppendS(&host->name, "Windows Subsystem for Linux");
if (wslDistroName)
ffStrbufAppendF(&host->productName, " - %s", wslDistroName);
ffStrbufAppendS(&host->productFamily, "WSL");
ffStrbufAppendF(&host->name, " - %s", wslDistroName);
ffStrbufAppendS(&host->family, "WSL");
FF_STRBUF_AUTO_DESTROY wslVer = ffStrbufCreate(); //Wide characters
if(!ffProcessAppendStdOut(&wslVer, (char* const[]){
@@ -61,7 +89,7 @@ const char* ffDetectHost(FFHostResult* host)
ffStrbufSubstrAfterLastC(&wslVer, ' ');
for(uint32_t i = 0; i < wslVer.length; ++i) {
if(wslVer.chars[i]) //don't append \0
ffStrbufAppendC(&host->productVersion, wslVer.chars[i]);
ffStrbufAppendC(&host->version, wslVer.chars[i]);
}
}
}
+59 -14
View File
@@ -1,24 +1,69 @@
#include "host.h"
#include "util/windows/registry.h"
#include "util/smbiosHelper.h"
typedef struct FFSmbiosSystemInfo
{
FFSmbiosHeader Header;
uint8_t Manufacturer; // string
uint8_t ProductName; // string
uint8_t Version; // string
uint8_t SerialNumber; // string
// 2.1+
struct {
uint32_t TimeLow;
uint16_t TimeMid;
uint16_t TimeHighAndVersion;
uint8_t ClockSeqHiAndReserved;
uint8_t ClockSeqLow;
uint8_t Node[6];
} UUID; // varies
uint8_t WakeUpType; // enum
// 2.4+
uint8_t SKUNumber; // string
uint8_t Family; // string
} FFSmbiosSystemInfo;
const char* ffDetectHost(FFHostResult* host)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
const FFSmbiosSystemInfo* data = (const FFSmbiosSystemInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_SYSTEM_INFO];
if (!data)
return "System information is not found in SMBIOS data";
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
const char* strings = (const char*) data + data->Header.Length;
ffRegReadStrbuf(hKey, L"SystemProductName", &host->productName, NULL);
ffCleanUpSmbiosValue(&host->productName);
ffRegReadStrbuf(hKey, L"SystemFamily", &host->productFamily, NULL);
ffCleanUpSmbiosValue(&host->productFamily);
ffRegReadStrbuf(hKey, L"SystemVersion", &host->productVersion, NULL);
ffCleanUpSmbiosValue(&host->productVersion);
ffRegReadStrbuf(hKey, L"SystemSKU", &host->productSku, NULL);
ffCleanUpSmbiosValue(&host->productSku);
ffRegReadStrbuf(hKey, L"SystemManufacturer", &host->sysVendor, NULL);
ffCleanUpSmbiosValue(&host->sysVendor);
ffStrbufSetStatic(&host->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
ffCleanUpSmbiosValue(&host->vendor);
ffStrbufSetStatic(&host->name, ffSmbiosLocateString(strings, data->ProductName));
ffCleanUpSmbiosValue(&host->name);
ffStrbufSetStatic(&host->version, ffSmbiosLocateString(strings, data->Version));
ffCleanUpSmbiosValue(&host->version);
ffStrbufSetStatic(&host->serial, ffSmbiosLocateString(strings, data->SerialNumber));
ffCleanUpSmbiosValue(&host->serial);
static_assert(offsetof(FFSmbiosSystemInfo, UUID) == 0x08, "FFSmbiosSystemInfo.UUID offset is wrong");
if (data->Header.Length > offsetof(FFSmbiosSystemInfo, UUID))
{
ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
data->UUID.TimeLow, data->UUID.TimeMid, data->UUID.TimeHighAndVersion,
data->UUID.ClockSeqHiAndReserved, data->UUID.ClockSeqLow,
data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]);
}
static_assert(offsetof(FFSmbiosSystemInfo, SKUNumber) == 0x19, "FFSmbiosSystemInfo.SKUNumber offset is wrong");
if (data->Header.Length > offsetof(FFSmbiosSystemInfo, SKUNumber))
{
ffStrbufSetStatic(&host->sku, ffSmbiosLocateString(strings, data->SKUNumber));
ffCleanUpSmbiosValue(&host->sku);
}
if (data->Header.Length > offsetof(FFSmbiosSystemInfo, Family))
{
ffStrbufSetStatic(&host->family, ffSmbiosLocateString(strings, data->Family));
ffCleanUpSmbiosValue(&host->family);
}
return NULL;
}
@@ -21,14 +21,14 @@ static void getLocaleFromEnv(FFstrbuf* locale)
static void getLocaleFromStdFn(FFstrbuf* locale)
{
ffStrbufAppendS(locale, setlocale(LC_ALL, NULL));
#ifdef LC_MESSAGES
ffStrbufAppendS(locale, setlocale(LC_MESSAGES, NULL));
if(locale->length > 0)
return;
ffStrbufAppendS(locale, setlocale(LC_MESSAGES, NULL));
#endif
ffStrbufAppendS(locale, setlocale(LC_ALL, NULL));
}
void ffDetectLocale(FFstrbuf* result)
+18
View File
@@ -0,0 +1,18 @@
#include "detection/locale/locale.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <locale.h>
void ffDetectLocale(FFstrbuf* result)
{
wchar_t name[LOCALE_NAME_MAX_LENGTH];
int size = GetUserDefaultLocaleName(name, LOCALE_NAME_MAX_LENGTH);
if (size > 1) // including '\0'
{
ffStrbufSetNWS(result, (uint32_t)size - 1, name);
ffStrbufAppendS(result, ".UTF-8"); // set explicitly in `ffInitInstance`
}
else
ffStrbufSetS(result, setlocale(LC_ALL, NULL));
}
-2
View File
@@ -1,6 +1,5 @@
#include "fastfetch.h"
#include "detection/media/media.h"
#include "common/thread.h"
#include "util/stringUtils.h"
#include <string.h>
@@ -11,7 +10,6 @@
#ifdef FF_HAVE_DBUS
#include "common/dbus.h"
#include "common/library.h"
#include "common/parsing.h"
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
{
+3
View File
@@ -8,6 +8,9 @@ typedef struct FFMonitorResult
uint32_t physicalWidth; // in mm
uint32_t physicalHeight; // in mm
bool hdrCompatible;
uint16_t manufactureYear;
uint16_t manufactureWeek;
uint32_t serial;
} FFMonitorResult;
const char* ffDetectMonitor(FFlist* results);
+13 -1
View File
@@ -40,9 +40,13 @@ const char* ffDetectMonitor(FFlist* results)
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
if(!displayInfo) continue;
bool isVirtual = false;
if (ffCfDictGetBool(displayInfo, CFSTR("kCGDisplayIsVirtualDevice"), &isVirtual) == NULL && isVirtual)
continue;
uint8_t edidData[128] = {};
uint32_t edidLength = 0;
if (false || !ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength))
if (ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength) == NULL)
{
uint32_t width, height;
ffEdidGetPhysicalResolution(edidData, &width, &height);
@@ -75,6 +79,14 @@ const char* ffDetectMonitor(FFlist* results)
monitor->physicalHeight = (uint32_t) (size.height + 0.5);
monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) ||
detectHdrSupportWithNSScreen(display);
int64_t serial, year, week;
if (ffCfDictGetInt64(displayInfo, CFSTR("DisplaySerialNumber"), &serial) == NULL)
monitor->serial = (uint32_t) (uint64_t) serial;
if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayYearManufacture"), &year) == NULL)
monitor->manufactureYear = (uint16_t) year;
if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayWeekManufacture"), &week) == NULL)
monitor->manufactureWeek = (uint16_t) week;
}
return NULL;
+5 -4
View File
@@ -29,10 +29,10 @@ const char* ffDetectMonitor(FFlist* results)
ffStrbufAppendS(&drmDir, entry->d_name);
uint32_t drmDirWithDnameLength = drmDir.length;
ffStrbufAppendS(&drmDir, "/enabled");
char enabled = 'd'; // disabled
ffReadFileData(drmDir.chars, sizeof(enabled), &enabled);
if (enabled != 'e') // enabled
ffStrbufAppendS(&drmDir, "/status");
char status = 'd'; // disconnected
ffReadFileData(drmDir.chars, sizeof(status), &status);
if (status != 'c') // connected
{
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
@@ -59,6 +59,7 @@ const char* ffDetectMonitor(FFlist* results)
ffStrbufInit(&display->name);
ffEdidGetName(edidData, &display->name);
ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight);
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
}
+1
View File
@@ -44,6 +44,7 @@ const char* ffDetectMonitor(FFlist* results)
FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results);
display->width = width;
display->height = height;
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, edidLength); // Doesn't work. edidLength is always 128
ffStrbufInit(&display->name);
ffEdidGetName(edidData, &display->name);
+4 -7
View File
@@ -1,6 +1,8 @@
#include "os.h"
#include "common/io/io.h"
#include "common/sysctl.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <string.h>
@@ -72,11 +74,11 @@ static bool detectOSCodeName(FFOSResult* os)
static void parseOSXSoftwareLicense(FFOSResult* os)
{
FILE* rtf = fopen("/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf", "r");
FF_AUTO_CLOSE_FILE FILE* rtf = fopen("/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf", "r");
if(rtf == NULL)
return;
char* line = NULL;
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
const char* searchStr = "\\f0\\b SOFTWARE LICENSE AGREEMENT FOR macOS ";
while(getline(&line, &len, rtf) != EOF)
@@ -89,11 +91,6 @@ static void parseOSXSoftwareLicense(FFOSResult* os)
break;
}
}
if(line != NULL)
free(line);
fclose(rtf);
}
void ffDetectOSImpl(FFOSResult* os)
@@ -9,14 +9,6 @@
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
#include <IOKit/storage/nvme/NVMeSMARTLibExternal.h>
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
static inline void wrapIoDestroyPlugInInterface(IOCFPlugInInterface*** pluginInf)
{
assert(pluginInf);
@@ -49,11 +41,11 @@ static const char* detectSsdTemp(io_service_t entryPhysical, double* temp)
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
+2 -2
View File
@@ -8,10 +8,10 @@ typedef struct FFPowerAdapterResult
FFstrbuf name;
FFstrbuf modelName;
FFstrbuf manufacturer;
FFstrbuf serial;
int watts;
} FFPowerAdapterResult;
const char* ffDetectPowerAdapterImpl(FFlist* results);
const char* ffDetectPowerAdapter(FFlist* results);
#define FF_POWERADAPTER_UNSET -2
#define FF_POWERADAPTER_NOT_CONNECTED -1
+19 -40
View File
@@ -2,51 +2,30 @@
#include "poweradapter.h"
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
const char* ffDetectPowerAdapterImpl(FFlist* results)
const char* ffDetectPowerAdapter(FFlist* results)
{
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
FFPowerAdapterResult* adapter = ffListAdd(results);
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
ffStrbufInit(&adapter->name);
ffStrbufInit(&adapter->description);
ffStrbufInit(&adapter->manufacturer);
ffStrbufInit(&adapter->modelName);
ffStrbufInit(&adapter->serial);
adapter->watts = FF_POWERADAPTER_NOT_CONNECTED;
if (details)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
FFPowerAdapterResult* adapter = ffListAdd(results);
ffStrbufInit(&adapter->name);
ffStrbufInit(&adapter->description);
ffStrbufInit(&adapter->manufacturer);
ffStrbufInit(&adapter->modelName);
adapter->watts = FF_POWERADAPTER_UNSET;
CFDictionaryRef adapterDict;
if(!ffCfDictGetDict(properties, CFSTR("AdapterDetails"), &adapterDict))
{
if (ffCfDictGetInt(adapterDict, CFSTR("Watts"), &adapter->watts))
{
adapter->watts = FF_POWERADAPTER_NOT_CONNECTED;
continue;
}
ffCfDictGetString(adapterDict, CFSTR("Name"), &adapter->name);
ffCfDictGetString(adapterDict, CFSTR("Description"), &adapter->description);
ffCfDictGetString(adapterDict, CFSTR("Manufacturer"), &adapter->manufacturer);
ffCfDictGetString(adapterDict, CFSTR("Model"), &adapter->modelName);
}
CFRelease(properties);
IOObjectRelease(registryEntry);
ffCfDictGetString(details, CFSTR(kIOPSNameKey), &adapter->name);
ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName);
ffCfDictGetString(details, CFSTR("Manufacturer"), &adapter->manufacturer);
ffCfDictGetString(details, CFSTR("Description"), &adapter->description);
ffCfDictGetString(details, CFSTR("SerialString"), &adapter->serial);
ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterWattsKey), &adapter->watts);
}
IOObjectRelease(iterator);
return NULL;
}
@@ -0,0 +1,102 @@
#include "poweradapter.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include <dirent.h>
static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFlist* results)
{
uint32_t dirLength = dir->length;
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
//type must exist and be "Mains"
ffStrbufAppendS(dir, "/type");
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
ffStrbufTrimRightSpace(&tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Mains"))
return;
//scope may not exist or must not be "Device" (?)
ffStrbufAppendS(dir, "/scope");
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
ffStrbufTrimRightSpace(&tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
return;
//input_power_limit must exist and be not empty
ffStrbufAppendS(dir, "/input_power_limit");
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
ffStrbufSubstrBefore(dir, dirLength);
if (!available)
return;
FFPowerAdapterResult* result = ffListAdd(results);
ffStrbufInit(&result->name);
ffStrbufInit(&result->description);
ffStrbufAppendS(dir, "/online");
char online = '1';
ffReadFileData(dir->chars, sizeof(online), &online);
ffStrbufSubstrBefore(dir, dirLength);
if (online == '0')
result->watts = FF_POWERADAPTER_NOT_CONNECTED;
else
result->watts = (int) (ffStrbufToDouble(&tmpBuffer) / 1e6 + 0.5);
//At this point, we have a battery. Try to get as much values as possible.
ffStrbufInit(&result->manufacturer);
ffStrbufAppendS(dir, "/manufacturer");
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
ffStrbufTrimRightSpace(&result->manufacturer);
else if (ffStrEquals(id, "macsmc-ac")) // asahi
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->modelName);
ffStrbufAppendS(dir, "/model_name");
if (ffReadFileBuffer(dir->chars, &result->modelName))
ffStrbufTrimRightSpace(&result->modelName);
ffStrbufSubstrBefore(dir, dirLength);
ffStrbufInit(&result->serial);
ffStrbufAppendS(dir, "/serial_number");
if (ffReadFileBuffer(dir->chars, &result->serial))
ffStrbufTrimRightSpace(&result->serial);
ffStrbufSubstrBefore(dir, dirLength);
}
const char* ffDetectPowerAdapter(FFlist* results)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
uint32_t baseDirLength = baseDir.length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
return "opendir(\"/sys/class/power_supply/\") == NULL";
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, ".."))
continue;
ffStrbufAppendS(&baseDir, entry->d_name);
parsePowerAdapter(&baseDir, entry->d_name, results);
ffStrbufSubstrBefore(&baseDir, baseDirLength);
}
if(results->length == 0)
return "\"/sys/class/power_supply/\" doesn't contain any power adapter folder";
return NULL;
}
@@ -1,7 +1,6 @@
#include "fastfetch.h"
#include "poweradapter.h"
const char* ffDetectPowerAdapterImpl(FFlist* results)
const char* ffDetectPowerAdapter(FF_MAYBE_UNUSED FFlist* results)
{
FF_UNUSED(results);
return "Not supported on this platform";
}
+48
View File
@@ -0,0 +1,48 @@
#include "sound.h"
#include "common/io/io.h"
#include "common/sysctl.h"
#include <fcntl.h>
#include <sys/soundcard.h>
const char* ffDetectSound(FFlist* devices)
{
char path[] = "/dev/mixer0";
int defaultDev = ffSysctlGetInt("hw.snd.default_unit", -1);
for (int idev = 0; idev <= 9; ++idev)
{
path[strlen("/dev/mixer")] = (char) ('0' + idev);
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
if (fd < 0) break;
uint32_t devmask = 0;
if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0)
continue;
if (!(devmask & SOUND_MASK_VOLUME))
continue;
uint32_t mutemask = 0;
if (ioctl(fd, SOUND_MIXER_READ_MUTE, &mutemask) < 0)
continue;
struct oss_card_info ci = { .card = idev };
if (ioctl(fd, SNDCTL_CARDINFO, &ci) < 0)
continue;
uint32_t volume;
if (ioctl(fd, SOUND_MIXER_READ_VOLUME, &volume) < 0)
continue;
FFSoundDevice* device = ffListAdd(devices);
ffStrbufInitS(&device->identifier, path);
ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info);
device->volume = mutemask & SOUND_MASK_VOLUME
? 0
: ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2;
device->active = true;
device->main = defaultDev == idev;
}
return NULL;
}
+12 -16
View File
@@ -85,12 +85,9 @@ static void smcUltostr(char *str, uint32_t val)
static const char *smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t *inputStructure, SmcKeyData_t *outputStructure)
{
size_t structureInputSize;
size_t structureOutputSize;
structureInputSize = sizeof(SmcKeyData_t);
structureOutputSize = sizeof(SmcKeyData_t);
size_t size = sizeof(SmcKeyData_t);
if (IOConnectCallStructMethod(conn, selector, inputStructure, structureInputSize, outputStructure, &structureOutputSize) != kIOReturnSuccess)
if (IOConnectCallStructMethod(conn, selector, inputStructure, size, outputStructure, &size) != kIOReturnSuccess)
return "IOConnectCallStructMethod(conn) failed";
return NULL;
}
@@ -140,17 +137,13 @@ static const char *smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcV
static const char *smcOpen(io_connect_t *conn)
{
io_iterator_t iterator;
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSMC"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_object_t device = IOIteratorNext(iterator);
IOObjectRelease(iterator);
if (device == 0)
io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC"));
if (!device)
return "No SMC device found";
kern_return_t result = IOServiceOpen(device, mach_task_self(), 0, conn);
IOObjectRelease(device);
if (result != kIOReturnSuccess)
return "IOServiceOpen() failed";
@@ -290,10 +283,13 @@ static bool detectTemp(io_connect_t conn, const char *sensor, double* sum)
const char *ffDetectSmcTemps(enum FFTempType type, double *result)
{
static io_connect_t conn;
static dispatch_once_t once_control;
dispatch_once_f(&once_control, &conn, (dispatch_function_t) smcOpen);
if(!conn)
return "smcOpen() failed";
if (!conn)
{
if (smcOpen(&conn) != NULL)
conn = (io_connect_t) -1;
}
else if (conn == (io_connect_t) -1)
return "Could not open SMC connection";
uint32_t count = 0;
*result = 0;
+20 -20
View File
@@ -394,35 +394,35 @@ static bool detectContour(const FFstrbuf* exe, FFTerminalFontResult* result)
return true;
}
void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont);
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont);
static bool detectTerminalFontCommon(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "alacritty"))
if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "alacritty"))
detectAlacritty(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "terminator"))
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "terminator"))
detectTerminator(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "wezterm-gui"))
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "wezterm-gui"))
detectWezterm(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "tabby"))
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "tabby"))
detectTabby(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "contour"))
detectContour(&terminalShell->terminalExe, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "contour"))
detectContour(&terminal->exe, terminalFont);
#ifndef _WIN32
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/pts/"))
else if(ffStrbufStartsWithIgnCaseS(&terminal->exe, "/dev/pts/"))
ffStrbufAppendS(&terminalFont->error, "Terminal font detection is not supported on PTS");
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kitty"))
detectKitty(&terminalShell->terminalExe, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "kitty"))
detectKitty(&terminal->exe, terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminal->exe, "/dev/tty"))
detectTTY(terminalFont);
#endif
#if defined(_WIN32) || defined(__linux__)
//Used by both Linux (WSL) and Windows
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "Windows Terminal") ||
ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "WindowsTerminal.exe"))
detectFromWindowsTeriminal(&terminalShell->terminalExe, terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "Windows Terminal") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "WindowsTerminal.exe"))
detectFromWindowsTeriminal(&terminal->exe, terminalFont);
#endif
else
@@ -433,16 +433,16 @@ static bool detectTerminalFontCommon(const FFTerminalShellResult* terminalShell,
bool ffDetectTerminalFont(FFTerminalFontResult* result)
{
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell();
const FFTerminalResult* terminal = ffDetectTerminal();
if(terminalShell->terminalProcessName.length == 0)
if(terminal->processName.length == 0)
ffStrbufAppendS(&result->error, "Terminal font needs successful terminal detection");
else if(!detectTerminalFontCommon(terminalShell, result))
ffDetectTerminalFontPlatform(terminalShell, result);
else if(!detectTerminalFontCommon(terminal, result))
ffDetectTerminalFontPlatform(terminal, result);
if(result->error.length == 0 && result->font.pretty.length == 0)
ffStrbufAppendF(&result->error, "Unknown terminal: %s", terminalShell->terminalProcessName.chars);
ffStrbufAppendF(&result->error, "Unknown terminal: %s", terminal->processName.chars);
return result->error.length == 0;
}
@@ -53,9 +53,9 @@ exit:
#endif
}
void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufCompS(&terminalShell->terminalProcessName, "com.termux") != 0)
if(ffStrbufCompS(&terminal->processName, "com.termux") != 0)
{
ffStrbufSetS(&terminalFont->error, "Unsupported terminal");
return;
@@ -91,13 +91,13 @@ static void detectWarpTerminal(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.UTF8String, fontSize.UTF8String);
}
void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "iterm.app") == 0 ||
ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "iTermServer-"))
if(ffStrbufIgnCaseEqualS(&terminal->processName, "iterm.app") ||
ffStrbufStartsWithIgnCaseS(&terminal->processName, "iTermServer-"))
detectIterm2(terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Apple_Terminal") == 0)
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "Apple_Terminal"))
detectAppleTerminal(terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WarpTerminal") == 0)
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "WarpTerminal"))
detectWarpTerminal(terminalFont);
}
+15 -15
View File
@@ -303,32 +303,32 @@ static void detectSt(FFTerminalFontResult* terminalFont, uint32_t pid)
ffFontInitValues(&terminalFont->font, font.chars, size.chars);
}
void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "konsole"))
if(ffStrbufIgnCaseEqualS(&terminal->processName, "konsole"))
detectKonsole(terminalFont, "konsolerc");
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "yakuake"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "yakuake"))
detectKonsole(terminalFont, "yakuakerc");
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "xfce4-terminal"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "xfce4-terminal"))
detectXFCETerminal(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "lxterminal"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "lxterminal"))
detectFromConfigFile("lxterminal/lxterminal.conf", "fontname =", terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "tilix"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "tilix"))
detectFromGSettings("/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", "default", terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "gnome-terminal-"))
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "gnome-terminal-"))
detectFromGSettings("/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", "default", terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kgx"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "kgx"))
detectKgx(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "mate-terminal"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "mate-terminal"))
detectFromGSettings("/org/mate/terminal/profiles/", "org.mate.terminal.global", "org.mate.terminal.profile", "default-profile", terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "deepin-terminal"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "deepin-terminal"))
detectDeepinTerminal(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "foot"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "foot"))
detectFootTerminal(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "qterminal"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "qterminal"))
detectQTerminal(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "xterm"))
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "xterm"))
detectXterm(terminalFont);
else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "st"))
detectSt(terminalFont, terminalShell->terminalPid);
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "st"))
detectSt(terminalFont, terminal->pid);
}
@@ -85,12 +85,12 @@ static void detectConEmu(FFTerminalFontResult* terminalFont)
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
}
void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0)
if(ffStrbufIgnCaseEqualS(&terminal->processName, "mintty"))
detectMintty(terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0)
else if(ffStrbufIgnCaseEqualS(&terminal->processName, "conhost.exe"))
detectConhost(terminalFont);
else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "ConEmu"))
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "ConEmu"))
detectConEmu(terminalFont);
}
@@ -152,6 +152,22 @@ static bool getShellVersionNushell(FFstrbuf* exe, FFstrbuf* version)
return getExeVersionRaw(exe, version); //0.73.0
}
static bool getShellVersionAsh(FFstrbuf* exe, FFstrbuf* version)
{
if(ffProcessAppendStdErr(version, (char* const[]) {
exe->chars,
"--help",
NULL
}) != NULL)
return false;
// BusyBox v1.36.1 (2023-11-07 18:53:09 UTC) multi-call binary...
ffStrbufSubstrAfterFirstC(version, ' ');
ffStrbufSubstrBeforeFirstC(version, ' ');
ffStrbufTrimLeft(version, 'v');
return true;
}
#ifdef _WIN32
static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
{
@@ -210,6 +226,8 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
return getShellVersionOils(exe, version);
if(strcasecmp(exeName, "elvish") == 0)
return getExeVersionRaw(exe, version);
if(strcasecmp(exeName, "ash") == 0)
return getShellVersionAsh(exe, version);
if(strcasecmp(exeName, "python") == 0 && getenv("XONSH_VERSION"))
{
ffStrbufSetS(version, getenv("XONSH_VERSION"));
+21 -15
View File
@@ -2,21 +2,27 @@
#include "fastfetch.h"
typedef struct FFTerminalShellResult
typedef struct FFShellResult
{
FFstrbuf shellProcessName;
FFstrbuf shellExe;
const char* shellExeName; //pointer to a char in shellExe
FFstrbuf shellPrettyName;
FFstrbuf shellVersion;
uint32_t shellPid;
FFstrbuf processName;
FFstrbuf exe;
const char* exeName; //pointer to a char in exe
FFstrbuf prettyName;
FFstrbuf version;
uint32_t pid;
uint32_t ppid;
} FFShellResult;
FFstrbuf terminalProcessName;
FFstrbuf terminalExe;
FFstrbuf terminalPrettyName;
const char* terminalExeName; //pointer to a char in terminalExe
FFstrbuf terminalVersion;
uint32_t terminalPid;
} FFTerminalShellResult;
typedef struct FFTerminalResult
{
FFstrbuf processName;
FFstrbuf exe;
FFstrbuf prettyName;
const char* exeName; //pointer to a char in exe
FFstrbuf version;
uint32_t pid;
uint32_t ppid;
} FFTerminalResult;
const FFTerminalShellResult* ffDetectTerminalShell();
const FFShellResult* ffDetectShell();
const FFTerminalResult* ffDetectTerminal();
+220 -175
View File
@@ -75,7 +75,7 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
char buf[PROC_FILE_BUFFSIZ];
ssize_t nRead = ffReadFileData(statFilePath, sizeof(buf) - 1, buf);
if(nRead < 0)
return "ffReadFileData(statFilePath, sizeof(buf)-1, buf)";
return "ffReadFileData(statFilePath, sizeof(buf)-1, buf) failed";
buf[nRead] = '\0';
*ppid = 0;
@@ -118,95 +118,114 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid)
return NULL;
}
static void getTerminalShell(FFTerminalShellResult* result, pid_t pid)
static pid_t getShellInfo(FFShellResult* result, pid_t pid)
{
char name[256];
name[0] = '\0';
pid_t ppid = 0;
if(getProcessNameAndPpid(pid, name, &ppid))
return;
//Common programs that are between terminal and own process, but are not the shell
if(
strcasecmp(name, "sh") == 0 || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell
strcasecmp(name, "sudo") == 0 ||
strcasecmp(name, "su") == 0 ||
strcasecmp(name, "strace") == 0 ||
strcasecmp(name, "sshd") == 0 ||
strcasecmp(name, "gdb") == 0 ||
strcasecmp(name, "lldb") == 0 ||
strcasecmp(name, "login") == 0 ||
strcasecmp(name, "ltrace") == 0 ||
strcasecmp(name, "perf") == 0 ||
strcasecmp(name, "guake-wrapped") == 0 ||
strcasestr(name, "debug") != NULL ||
strcasestr(name, "command-not-found") != NULL ||
ffStrEndsWith(name, ".sh")
) {
getTerminalShell(result, ppid);
return;
}
//Known shells
if (
strcasecmp(name, "ash") == 0 ||
strcasecmp(name, "bash") == 0 ||
strcasecmp(name, "zsh") == 0 ||
strcasecmp(name, "ksh") == 0 ||
strcasecmp(name, "mksh") == 0 ||
strcasecmp(name, "oksh") == 0 ||
strcasecmp(name, "csh") == 0 ||
strcasecmp(name, "tcsh") == 0 ||
strcasecmp(name, "fish") == 0 ||
strcasecmp(name, "dash") == 0 ||
strcasecmp(name, "pwsh") == 0 ||
strcasecmp(name, "nu") == 0 ||
strcasecmp(name, "git-shell") == 0 ||
strcasecmp(name, "elvish") == 0 ||
strcasecmp(name, "oil.ovm") == 0 ||
(strcasecmp(name, "python") == 0 && getenv("XONSH_VERSION"))
) {
if (result->shellProcessName.length == 0)
while (getProcessNameAndPpid(pid, name, &ppid) == NULL)
{
//Common programs that are between terminal and own process, but are not the shell
if(
ffStrEquals(name, "sh") || //This prevents us from detecting things like pipes and redirects, i hope nobody uses plain `sh` as shell
ffStrEquals(name, "sudo") ||
ffStrEquals(name, "su") ||
ffStrEquals(name, "strace") ||
ffStrEquals(name, "sshd") ||
ffStrEquals(name, "gdb") ||
ffStrEquals(name, "lldb") ||
ffStrEquals(name, "lldb-mi") ||
ffStrEquals(name, "login") ||
ffStrEquals(name, "ltrace") ||
ffStrEquals(name, "perf") ||
ffStrEquals(name, "guake-wrapped") ||
ffStrContainsIgnCase(name, "debug") ||
ffStrContainsIgnCase(name, "not-found") ||
ffStrEndsWith(name, ".sh")
)
{
result->shellPid = (uint32_t) pid;
ffStrbufSetS(&result->shellProcessName, name);
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
pid = ppid;
continue;
}
getTerminalShell(result, ppid);
return;
result->pid = (uint32_t) pid;
result->ppid = (uint32_t) ppid;
ffStrbufSetS(&result->processName, name);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName);
break;
}
#ifdef __APPLE__
// https://github.com/fastfetch-cli/fastfetch/discussions/501
if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)"))
getProcessNameAndPpid(ppid, name, &ppid);
#endif
result->terminalPid = (uint32_t) pid;
ffStrbufSetS(&result->terminalProcessName, name);
getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName);
return ppid;
}
static void getTerminalFromEnv(FFTerminalShellResult* result)
static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
{
if(
result->terminalProcessName.length > 0 &&
!ffStrbufStartsWithIgnCaseS(&result->terminalProcessName, "login") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(login)") &&
char name[256];
name[0] = '\0';
pid_t ppid = 0;
while (getProcessNameAndPpid(pid, name, &ppid) == NULL)
{
//Known shells
if (
ffStrEquals(name, "ash") ||
ffStrEquals(name, "bash") ||
ffStrEquals(name, "zsh") ||
ffStrEquals(name, "ksh") ||
ffStrEquals(name, "mksh") ||
ffStrEquals(name, "oksh") ||
ffStrEquals(name, "csh") ||
ffStrEquals(name, "tcsh") ||
ffStrEquals(name, "fish") ||
ffStrEquals(name, "dash") ||
ffStrEquals(name, "pwsh") ||
ffStrEquals(name, "nu") ||
ffStrEquals(name, "git-shell") ||
ffStrEquals(name, "elvish") ||
ffStrEquals(name, "oil.ovm") ||
(ffStrEquals(name, "python") && getenv("XONSH_VERSION"))
)
{
pid = ppid;
continue;
}
#ifdef __APPLE__
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "launchd") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "stable") && //for WarpTerminal
#else
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "systemd") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "init") &&
!ffStrbufIgnCaseEqualS(&result->terminalProcessName, "(init)") &&
// https://github.com/fastfetch-cli/fastfetch/discussions/501
if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)"))
{
if (__builtin_expect(getProcessNameAndPpid(ppid, name, &ppid) != NULL, false))
return 0;
}
#endif
ffStrbufIgnCaseCompS(&result->terminalProcessName, "0") != 0
result->pid = (uint32_t) pid;
ffStrbufSetS(&result->processName, name);
getProcessInformation(pid, &result->processName, &result->exe, &result->exeName);
break;
}
return ppid;
}
static void getTerminalFromEnv(FFTerminalResult* result)
{
if(
result->processName.length > 0 &&
!ffStrbufStartsWithS(&result->processName, "login") &&
!ffStrbufEqualS(&result->processName, "(login)") &&
#ifdef __APPLE__
!ffStrbufEqualS(&result->processName, "launchd") &&
!ffStrbufEqualS(&result->processName, "stable") && //for WarpTerminal
#else
!ffStrbufEqualS(&result->processName, "systemd") &&
!ffStrbufEqualS(&result->processName, "init") &&
!ffStrbufEqualS(&result->processName, "(init)") &&
#endif
!ffStrbufEqualS(&result->processName, "0")
) return;
const char* term = NULL;
@@ -262,25 +281,25 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
term = getenv("TERM");
//TTY
if(!ffStrSet(term) || strcasecmp(term, "linux") == 0)
if(!ffStrSet(term) || ffStrEquals(term, "linux"))
term = ttyname(STDIN_FILENO);
if(ffStrSet(term))
{
ffStrbufSetS(&result->terminalProcessName, term);
ffStrbufSetS(&result->terminalExe, term);
setExeName(&result->terminalExe, &result->terminalExeName);
ffStrbufSetS(&result->processName, term);
ffStrbufSetS(&result->exe, term);
setExeName(&result->exe, &result->exeName);
}
}
static void getUserShellFromEnv(FFTerminalShellResult* result)
static void getUserShellFromEnv(FFShellResult* result)
{
//If shell detection via processes failed
if(result->shellProcessName.length == 0 && instance.state.platform.userShell.length > 0)
if(result->processName.length == 0 && instance.state.platform.userShell.length > 0)
{
ffStrbufSet(&result->shellExe, &instance.state.platform.userShell);
setExeName(&result->shellExe, &result->shellExeName);
ffStrbufAppendS(&result->shellProcessName, result->shellExeName);
ffStrbufSet(&result->exe, &instance.state.platform.userShell);
setExeName(&result->exe, &result->exeName);
ffStrbufAppendS(&result->processName, result->exeName);
}
}
@@ -288,107 +307,133 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
const FFTerminalShellResult* ffDetectTerminalShell()
static void setShellInfoDetails(FFShellResult* result)
{
static FFTerminalShellResult result;
ffStrbufClear(&result->version);
fftsGetShellVersion(&result->exe, result->exeName, &result->version);
if(ffStrbufEqualS(&result->processName, "pwsh"))
ffStrbufInitStatic(&result->prettyName, "PowerShell");
else if(ffStrbufEqualS(&result->processName, "nu"))
ffStrbufInitStatic(&result->prettyName, "nushell");
else if(ffStrbufEqualS(&result->processName, "python") && getenv("XONSH_VERSION"))
ffStrbufInitStatic(&result->prettyName, "xonsh");
else if(ffStrbufEqualS(&result->processName, "oil.ovm"))
ffStrbufInitStatic(&result->prettyName, "Oils");
else
{
// https://github.com/fastfetch-cli/fastfetch/discussions/280#discussioncomment-3831734
ffStrbufInitS(&result->prettyName, result->exeName);
}
}
static void setTerminalInfoDetails(FFTerminalResult* result)
{
if(result->exeName[0] == '.' && ffStrEndsWith(result->exeName, "-wrapped"))
{
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
// We use processName when detecting version and font, overriding it for simplification
ffStrbufSetNS(
&result->processName,
(uint32_t) (strlen(result->exeName) - strlen(".-wrapped")),
result->exeName + 1);
}
if(ffStrbufEqualS(&result->processName, "wezterm-gui"))
ffStrbufInitStatic(&result->prettyName, "WezTerm");
else if(ffStrbufStartsWithS(&result->processName, "tmux:"))
ffStrbufInitStatic(&result->prettyName, "tmux");
#if defined(__ANDROID__)
else if(ffStrbufEqualS(&result->processName, "com.termux"))
ffStrbufInitStatic(&result->prettyName, "Termux");
#elif defined(__linux__) || defined(__FreeBSD__)
else if(ffStrbufStartsWithS(&result->processName, "gnome-terminal-"))
ffStrbufInitStatic(&result->prettyName, "GNOME Terminal");
else if(ffStrbufStartsWithS(&result->processName, "kgx"))
ffStrbufInitStatic(&result->prettyName, "GNOME Console");
else if(ffStrbufEqualS(&result->processName, "urxvt") ||
ffStrbufEqualS(&result->processName, "urxvtd") ||
ffStrbufEqualS(&result->processName, "rxvt")
)
ffStrbufInitStatic(&result->prettyName, "rxvt-unicode");
#elif defined(__APPLE__)
else if(ffStrbufEqualS(&result->processName, "iTerm.app") || ffStrbufStartsWithS(&result->processName, "iTermServer-"))
ffStrbufInitStatic(&result->prettyName, "iTerm");
else if(ffStrbufEqualS(&result->processName, "Apple_Terminal"))
ffStrbufInitStatic(&result->prettyName, "Apple Terminal");
else if(ffStrbufEqualS(&result->processName, "WarpTerminal"))
ffStrbufInitStatic(&result->prettyName, "Warp");
#endif
else if(strncmp(result->exeName, result->processName.chars, result->processName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
ffStrbufInitS(&result->prettyName, result->exeName);
else
ffStrbufInitCopy(&result->prettyName, &result->processName);
ffStrbufInit(&result->version);
fftsGetTerminalVersion(&result->processName, &result->exe, &result->version);
}
#ifdef __APPLE__
#define FF_EXE_PATH_LEN PROC_PIDPATHINFO_MAXSIZE
#elif defined(MAXPATH)
#define FF_EXE_PATH_LEN MAXPATH
#elif defined(PATH_MAX)
#define FF_EXE_PATH_LEN PATH_MAX
#else
#define FF_EXE_PATH_LEN 260
#endif
const FFShellResult* ffDetectShell()
{
static FFShellResult result;
static bool init = false;
if(init)
return &result;
init = true;
#ifdef __APPLE__
const uint32_t exePathLen = PROC_PIDPATHINFO_MAXSIZE;
#elif defined(MAXPATH)
const uint32_t exePathLen = MAXPATH;
#elif defined(PATH_MAX)
const uint32_t exePathLen = PATH_MAX;
#else
const uint32_t exePathLen = 260;
#endif
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, FF_EXE_PATH_LEN);
result.exeName = result.exe.chars;
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
ffStrbufInit(&result.shellProcessName);
ffStrbufInitA(&result.shellExe, exePathLen);
result.shellExeName = result.shellExe.chars;
ffStrbufInit(&result.shellVersion);
result.shellPid = 0;
ffStrbufInit(&result.terminalProcessName);
ffStrbufInitA(&result.terminalExe, exePathLen);
result.terminalExeName = result.terminalExe.chars;
result.terminalPid = 0;
getTerminalShell(&result, getppid());
getTerminalFromEnv(&result);
pid_t ppid = getppid();
ppid = getShellInfo(&result, ppid);
getUserShellFromEnv(&result);
ffStrbufClear(&result.shellVersion);
fftsGetShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion);
if(ffStrbufEqualS(&result.shellProcessName, "pwsh"))
ffStrbufInitStatic(&result.shellPrettyName, "PowerShell");
else if(ffStrbufEqualS(&result.shellProcessName, "nu"))
ffStrbufInitStatic(&result.shellPrettyName, "nushell");
else if(ffStrbufIgnCaseEqualS(&result.shellProcessName, "python") && getenv("XONSH_VERSION"))
ffStrbufInitStatic(&result.shellPrettyName, "xonsh");
else if(ffStrbufIgnCaseEqualS(&result.shellProcessName, "oil.ovm"))
ffStrbufInitStatic(&result.shellPrettyName, "Oils");
else
{
// https://github.com/fastfetch-cli/fastfetch/discussions/280#discussioncomment-3831734
ffStrbufInitS(&result.shellPrettyName, result.shellExeName);
}
if(result.terminalExeName[0] == '.' && ffStrEndsWith(result.terminalExeName, "-wrapped"))
{
// For NixOS. Ref: #510 and https://github.com/NixOS/nixpkgs/pull/249428
// We use terminalProcessName when detecting version and font, overriding it for simplification
ffStrbufSetNS(
&result.terminalProcessName,
(uint32_t) (strlen(result.terminalExeName) - strlen(".-wrapped")),
result.terminalExeName + 1);
}
if(ffStrbufEqualS(&result.terminalProcessName, "wezterm-gui"))
ffStrbufInitStatic(&result.terminalPrettyName, "WezTerm");
if(ffStrbufStartsWithS(&result.terminalProcessName, "tmux:"))
ffStrbufInitStatic(&result.terminalPrettyName, "tmux");
#if defined(__ANDROID__)
else if(ffStrbufEqualS(&result.terminalProcessName, "com.termux"))
ffStrbufInitStatic(&result.terminalPrettyName, "Termux");
#elif defined(__linux__) || defined(__FreeBSD__)
else if(ffStrbufStartsWithS(&result.terminalProcessName, "gnome-terminal-"))
ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Terminal");
else if(ffStrbufStartsWithS(&result.terminalProcessName, "kgx"))
ffStrbufInitStatic(&result.terminalPrettyName, "GNOME Console");
else if(ffStrbufEqualS(&result.terminalProcessName, "urxvt") ||
ffStrbufEqualS(&result.terminalProcessName, "urxvtd") ||
ffStrbufEqualS(&result.terminalProcessName, "rxvt")
)
ffStrbufInitStatic(&result.terminalPrettyName, "rxvt-unicode");
#elif defined(__APPLE__)
else if(ffStrbufEqualS(&result.terminalProcessName, "iTerm.app") || ffStrbufStartsWithS(&result.terminalProcessName, "iTermServer-"))
ffStrbufInitStatic(&result.terminalPrettyName, "iTerm");
else if(ffStrbufEqualS(&result.terminalProcessName, "Apple_Terminal"))
ffStrbufInitStatic(&result.terminalPrettyName, "Apple Terminal");
else if(ffStrbufEqualS(&result.terminalProcessName, "WarpTerminal"))
ffStrbufInitStatic(&result.terminalPrettyName, "Warp");
#endif
else if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName);
else
ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName);
ffStrbufInit(&result.terminalVersion);
fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
setShellInfoDetails(&result);
return &result;
}
const FFTerminalResult* ffDetectTerminal()
{
static FFTerminalResult result;
static bool init = false;
if(init)
return &result;
init = true;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, FF_EXE_PATH_LEN);
result.exeName = result.exe.chars;
result.pid = 0;
result.ppid = 0;
pid_t ppid = (pid_t) ffDetectShell()->ppid;
if (ppid)
ppid = getTerminalInfo(&result, ppid);
getTerminalFromEnv(&result);
setTerminalInfoDetails(&result);
return &result;
}
@@ -83,55 +83,71 @@ static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrb
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
{
uint32_t ppid;
if(pid == 0 || !getProcessInfo(pid, &ppid, &result->shellProcessName, &result->shellExe, &result->shellExeName))
return 0;
ffStrbufSet(&result->shellPrettyName, &result->shellProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->shellPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->shellPrettyName, result->shellPrettyName.length - 4);
//Common programs that are between terminal and own process, but are not the shell
if(
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "sudo") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "su") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "doas") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "strace") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "sshd") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "gdb") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "lldb") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "guake-wrapped") ||
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "fastfetch") || //scoop warps the real binaries with a "shim" exe
ffStrbufIgnCaseEqualS(&result->shellPrettyName, "flashfetch") ||
ffStrbufContainIgnCaseS(&result->shellPrettyName, "debug") ||
ffStrbufStartsWithIgnCaseS(&result->shellPrettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014
) {
ffStrbufClear(&result->shellProcessName);
ffStrbufClear(&result->shellPrettyName);
ffStrbufClear(&result->shellExe);
result->shellExeName = NULL;
return getShellInfo(result, ppid);
}
ffStrbufClear(&result->shellVersion);
fftsGetShellVersion(&result->shellExe, result->shellPrettyName.chars, &result->shellVersion);
result->shellPid = pid;
if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "pwsh"))
ffStrbufSetS(&result->shellPrettyName, "PowerShell");
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "powershell"))
ffStrbufSetS(&result->shellPrettyName, "Windows PowerShell");
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "powershell_ise"))
ffStrbufSetS(&result->shellPrettyName, "Windows PowerShell ISE");
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "cmd"))
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName))
{
ffStrbufClear(&result->shellPrettyName);
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4);
//Common programs that are between terminal and own process, but are not the shell
if(
ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "su") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "doas") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "strace") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "guake-wrapped") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "fastfetch") || //scoop warps the real binaries with a "shim" exe
ffStrbufIgnCaseEqualS(&result->prettyName, "flashfetch") ||
ffStrbufContainIgnCaseS(&result->prettyName, "debug") ||
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmu") // https://github.com/fastfetch-cli/fastfetch/issues/488#issuecomment-1619982014
) {
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
result->exeName = NULL;
pid = ppid;
continue;
}
ffStrbufClear(&result->version);
fftsGetShellVersion(&result->exe, result->prettyName.chars, &result->version);
result->pid = pid;
result->ppid = ppid;
if(ffStrbufIgnCaseEqualS(&result->prettyName, "explorer"))
{
ffStrbufSetS(&result->prettyName, "Windows Explorer"); // Started without shell
// In this case, terminal process will be created by fastfetch itself.
ppid = 0;
}
break;
}
return ppid;
}
static void setShellInfoDetails(FFShellResult* result)
{
if(ffStrbufIgnCaseEqualS(&result->prettyName, "pwsh"))
ffStrbufSetS(&result->prettyName, "PowerShell");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "powershell"))
ffStrbufSetS(&result->prettyName, "Windows PowerShell");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "powershell_ise"))
ffStrbufSetS(&result->prettyName, "Windows PowerShell ISE");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "cmd"))
{
ffStrbufClear(&result->prettyName);
FF_AUTO_CLOSE_FD HANDLE snapshot = NULL;
while(!(snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid)) && GetLastError() == ERROR_BAD_LENGTH) {}
while(!(snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, result->pid)) && GetLastError() == ERROR_BAD_LENGTH) {}
if(snapshot)
{
@@ -141,33 +157,27 @@ static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
{
if(wcsncmp(module.szModule, L"clink_dll_", strlen("clink_dll_")) == 0)
{
ffStrbufAppendS(&result->shellPrettyName, "CMD (with Clink ");
getProductVersion(module.szExePath, &result->shellPrettyName);
ffStrbufAppendC(&result->shellPrettyName, ')');
ffStrbufAppendS(&result->prettyName, "CMD (with Clink ");
getProductVersion(module.szExePath, &result->prettyName);
ffStrbufAppendC(&result->prettyName, ')');
break;
}
}
}
if(result->shellPrettyName.length == 0)
ffStrbufAppendS(&result->shellPrettyName, "Command Prompt");
if(result->prettyName.length == 0)
ffStrbufAppendS(&result->prettyName, "Command Prompt");
}
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "nu"))
ffStrbufSetS(&result->shellPrettyName, "nushell");
else if(ffStrbufIgnCaseEqualS(&result->shellPrettyName, "explorer"))
{
ffStrbufSetS(&result->shellPrettyName, "Windows Explorer"); // Started without shell
// In this case, terminal process will be created by fastfetch itself.
return 0;
}
return ppid;
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "nu"))
ffStrbufSetS(&result->prettyName, "nushell");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "explorer"))
ffStrbufSetS(&result->prettyName, "Windows Explorer");
}
static bool getTerminalFromEnv(FFTerminalShellResult* result)
static bool getTerminalFromEnv(FFTerminalResult* result)
{
if(
result->terminalProcessName.length > 0 &&
ffStrbufIgnCaseCompS(&result->terminalProcessName, "explorer") != 0
result->processName.length > 0 &&
ffStrbufIgnCaseCompS(&result->processName, "explorer") != 0
) return false;
const char* term = getenv("ConEmuPID");
@@ -176,12 +186,12 @@ static bool getTerminalFromEnv(FFTerminalShellResult* result)
{
//ConEmu
uint32_t pid = (uint32_t) strtoul(term, NULL, 10);
result->terminalPid = pid;
if(getProcessInfo(pid, NULL, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName))
result->pid = pid;
if(getProcessInfo(pid, NULL, &result->processName, &result->exe, &result->exeName))
{
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4);
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4);
return true;
}
else
@@ -198,7 +208,7 @@ static bool getTerminalFromEnv(FFTerminalShellResult* result)
if(!term && (
getenv("WT_SESSION") != NULL ||
getenv("WT_PROFILE_ID") != NULL
)) term = "Windows Terminal";
)) term = "WindowsTerminal";
//Alacritty
if(!term && (
@@ -216,17 +226,17 @@ static bool getTerminalFromEnv(FFTerminalShellResult* result)
if(term)
{
ffStrbufSetS(&result->terminalProcessName, term);
ffStrbufSetS(&result->terminalPrettyName, term);
ffStrbufSetS(&result->terminalExe, term);
result->terminalExeName = "";
ffStrbufSetS(&result->processName, term);
ffStrbufSetS(&result->prettyName, term);
ffStrbufSetS(&result->exe, term);
result->exeName = "";
return true;
}
return false;
}
static bool detectDefaultTerminal(FFTerminalShellResult* result)
static bool detectDefaultTerminal(FFTerminalResult* result)
{
wchar_t regPath[128] = L"SOFTWARE\\Classes\\PackagedCom\\ClassIndex\\";
wchar_t* uuid = regPath + strlen("SOFTWARE\\Classes\\PackagedCom\\ClassIndex\\");
@@ -251,18 +261,18 @@ static bool detectDefaultTerminal(FFTerminalShellResult* result)
{
if (ffStrbufStartsWithS(&path, "Microsoft.WindowsTerminal"))
{
ffStrbufSetS(&result->terminalProcessName, "WindowsTerminal.exe");
ffStrbufSetS(&result->terminalPrettyName, "WindowsTerminal");
ffStrbufSetF(&result->terminalExe, "%s\\WindowsApps\\%s\\WindowsTerminal.exe", getenv("ProgramFiles"), path.chars);
if(ffPathExists(result->terminalExe.chars, FF_PATHTYPE_FILE))
ffStrbufSetS(&result->processName, "WindowsTerminal.exe");
ffStrbufSetS(&result->prettyName, "WindowsTerminal");
ffStrbufSetF(&result->exe, "%s\\WindowsApps\\%s\\WindowsTerminal.exe", getenv("ProgramFiles"), path.chars);
if(ffPathExists(result->exe.chars, FF_PATHTYPE_FILE))
{
result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\') + 1;
result->exeName = result->exe.chars + ffStrbufLastIndexC(&result->exe, '\\') + 1;
}
else
{
ffStrbufDestroy(&result->terminalExe);
ffStrbufInitMove(&result->terminalExe, &path);
result->terminalExeName = "";
ffStrbufDestroy(&result->exe);
ffStrbufInitMove(&result->exe, &path);
result->exeName = "";
}
return true;
}
@@ -271,122 +281,148 @@ static bool detectDefaultTerminal(FFTerminalShellResult* result)
}
conhost:
ffStrbufSetF(&result->terminalExe, "%s\\System32\\conhost.exe", getenv("SystemRoot"));
if(ffPathExists(result->terminalExe.chars, FF_PATHTYPE_FILE))
ffStrbufSetF(&result->exe, "%s\\System32\\conhost.exe", getenv("SystemRoot"));
if(ffPathExists(result->exe.chars, FF_PATHTYPE_FILE))
{
ffStrbufSetS(&result->terminalProcessName, "conhost.exe");
ffStrbufSetS(&result->terminalPrettyName, "conhost");
result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\') + 1;
ffStrbufSetS(&result->processName, "conhost.exe");
ffStrbufSetS(&result->prettyName, "conhost");
result->exeName = result->exe.chars + ffStrbufLastIndexC(&result->exe, '\\') + 1;
return true;
}
ffStrbufClear(&result->terminalExe);
ffStrbufClear(&result->exe);
return false;
}
static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
static uint32_t getTerminalInfo(FFTerminalResult* result, uint32_t pid)
{
uint32_t ppid;
if(pid == 0 || !getProcessInfo(pid, &ppid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName))
return 0;
while (pid != 0 && getProcessInfo(pid, &ppid, &result->processName, &result->exe, &result->exeName))
{
ffStrbufSet(&result->prettyName, &result->processName);
if(ffStrbufEndsWithIgnCaseS(&result->prettyName, ".exe"))
ffStrbufSubstrBefore(&result->prettyName, result->prettyName.length - 4);
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4);
if(
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "pwsh") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "cmd") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "bash") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "zsh") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "fish") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "nu") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "powershell") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "powershell_ise") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "wsl") || // running inside wsl
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "servercoreshell") || // ServerCore Shell Launcher
ffStrbufStartsWithIgnCaseS(&result->terminalPrettyName, "ConEmuC") // wrapper process of ConEmu
) {
//We are nested shell
ffStrbufClear(&result->terminalProcessName);
ffStrbufClear(&result->terminalPrettyName);
ffStrbufClear(&result->terminalExe);
result->terminalExeName = "";
return getTerminalInfo(result, ppid);
}
if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "sihost") ||
ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "explorer")
) {
// A CUI program created by Windows Explorer will spawn a conhost as its child.
// However the conhost process is just a placeholder;
// The true terminal can be Windows Terminal or others.
if (!getTerminalFromEnv(result) && !detectDefaultTerminal(result))
{
ffStrbufClear(&result->terminalProcessName);
ffStrbufClear(&result->terminalPrettyName);
ffStrbufClear(&result->terminalExe);
result->terminalExeName = "";
return 0;
if(
ffStrbufIgnCaseEqualS(&result->prettyName, "pwsh") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "cmd") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "bash") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "zsh") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "fish") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "nu") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "powershell") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "powershell_ise") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "wsl") || // running inside wsl
ffStrbufIgnCaseEqualS(&result->prettyName, "servercoreshell") || // ServerCore Shell Launcher
ffStrbufStartsWithIgnCaseS(&result->prettyName, "ConEmuC") // wrapper process of ConEmu
) {
//We are nested shell
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
result->exeName = "";
pid = ppid;
continue;
}
}
else
result->terminalPid = pid;
if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "WindowsTerminal"))
ffStrbufSetStatic(&result->terminalPrettyName, ffStrbufContainIgnCaseS(&result->terminalExe, ".WindowsTerminalPreview_")
if(ffStrbufIgnCaseEqualS(&result->prettyName, "sihost") ||
ffStrbufIgnCaseEqualS(&result->prettyName, "explorer")
) {
// A CUI program created by Windows Explorer will spawn a conhost as its child.
// However the conhost process is just a placeholder;
// The true terminal can be Windows Terminal or others.
if (!getTerminalFromEnv(result) && !detectDefaultTerminal(result))
{
ffStrbufClear(&result->processName);
ffStrbufClear(&result->prettyName);
ffStrbufClear(&result->exe);
result->exeName = "";
return 0;
}
}
else
{
result->pid = pid;
result->ppid = ppid;
}
break;
}
return ppid;
}
static void setTerminalInfoDetails(FFTerminalResult* result)
{
if(ffStrbufIgnCaseEqualS(&result->prettyName, "WindowsTerminal"))
ffStrbufSetStatic(&result->prettyName, ffStrbufContainIgnCaseS(&result->exe, ".WindowsTerminalPreview_")
? "Windows Terminal Preview"
: "Windows Terminal"
);
else if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "conhost"))
ffStrbufSetStatic(&result->terminalPrettyName, "Console Window Host");
else if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "Code"))
ffStrbufSetStatic(&result->terminalPrettyName, "Visual Studio Code");
else if(ffStrbufIgnCaseEqualS(&result->terminalPrettyName, "explorer"))
ffStrbufSetStatic(&result->terminalPrettyName, "Windows Explorer");
else if(ffStrbufEqualS(&result->terminalPrettyName, "wezterm-gui"))
ffStrbufSetStatic(&result->terminalPrettyName, "WezTerm");
return ppid;
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "conhost"))
ffStrbufSetStatic(&result->prettyName, "Console Window Host");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "Code"))
ffStrbufSetStatic(&result->prettyName, "Visual Studio Code");
else if(ffStrbufIgnCaseEqualS(&result->prettyName, "explorer"))
ffStrbufSetStatic(&result->prettyName, "Windows Explorer");
else if(ffStrbufEqualS(&result->prettyName, "wezterm-gui"))
ffStrbufSetStatic(&result->prettyName, "WezTerm");
}
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
const FFTerminalShellResult* ffDetectTerminalShell(void)
const FFShellResult* ffDetectShell(void)
{
static FFTerminalShellResult result;
static FFShellResult result;
static bool init = false;
if(init)
return &result;
init = true;
ffStrbufInit(&result.shellProcessName);
ffStrbufInitA(&result.shellExe, 128);
result.shellExeName = "";
ffStrbufInit(&result.shellPrettyName);
ffStrbufInit(&result.shellVersion);
result.shellPid = 0;
ffStrbufInit(&result.terminalProcessName);
ffStrbufInitA(&result.terminalExe, 128);
result.terminalExeName = "";
ffStrbufInit(&result.terminalPrettyName);
result.terminalPid = 0;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, 128);
result.exeName = "";
ffStrbufInit(&result.prettyName);
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
uint32_t ppid;
if(!getProcessInfo(0, &ppid, NULL, NULL, NULL))
return &result;
ppid = getShellInfo(&result, ppid);
if(ppid)
getTerminalInfo(&result, ppid);
if(result.terminalProcessName.length == 0)
getTerminalFromEnv(&result);
ffStrbufInit(&result.terminalVersion);
fftsGetTerminalVersion(&result.terminalProcessName, &result.terminalExe, &result.terminalVersion);
setShellInfoDetails(&result);
return &result;
}
const FFTerminalResult* ffDetectTerminal(void)
{
static FFTerminalResult result;
static bool init = false;
if(init)
return &result;
init = true;
ffStrbufInit(&result.processName);
ffStrbufInitA(&result.exe, 128);
result.exeName = "";
ffStrbufInit(&result.prettyName);
ffStrbufInit(&result.version);
result.pid = 0;
result.ppid = 0;
uint32_t ppid = ffDetectShell()->ppid;
if(ppid)
getTerminalInfo(&result, ppid);
if(result.processName.length == 0)
getTerminalFromEnv(&result);
setTerminalInfoDetails(&result);
fftsGetTerminalVersion(&result.processName, &result.exe, &result.version);
return &result;
}
+4 -10
View File
@@ -1,5 +1,4 @@
#include "fastfetch.h"
#include "common/thread.h"
#include "detection/gpu/gpu.h"
#include "detection/vulkan/vulkan.h"
@@ -8,7 +7,7 @@
#include "common/io/io.h"
#include "common/parsing.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <vulkan/vulkan.h>
@@ -211,14 +210,8 @@ static const char* detectVulkan(FFVulkanResult* result)
continue;
}
//If the highest device version is lower than the instance version, use it as our vulkan version
//otherwise the instance version is the vulkan version
if(ffVersionCompare(&instanceVersion, &maxDeviceApiVersion) > 0)
ffVersionToPretty(&maxDeviceApiVersion, &result->apiVersion);
else
ffVersionToPretty(&instanceVersion, &result->apiVersion);
//Use the highest device conformace version as our conformance version
ffVersionToPretty(&instanceVersion, &result->instanceVersion);
ffVersionToPretty(&maxDeviceApiVersion, &result->apiVersion);
ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion);
ffvkDestroyInstance(vkInstance, NULL);
@@ -236,6 +229,7 @@ FFVulkanResult* ffDetectVulkan(void)
ffStrbufInit(&result.driver);
ffStrbufInit(&result.apiVersion);
ffStrbufInit(&result.conformanceVersion);
ffStrbufInit(&result.instanceVersion);
ffListInit(&result.gpus, sizeof(FFGPUResult));
#ifdef FF_HAVE_VULKAN
+1
View File
@@ -7,6 +7,7 @@ typedef struct FFVulkanResult
FFstrbuf driver;
FFstrbuf apiVersion;
FFstrbuf conformanceVersion;
FFstrbuf instanceVersion;
FFlist gpus; //List of FFGPUResult, see detection/gpu/gpu.h
const char* error;
} FFVulkanResult;
-30
View File
@@ -1,30 +0,0 @@
#include "wallpaper.h"
#include "common/settings.h"
#include "util/apple/osascript.h"
const char* ffDetectWallpaper(FFstrbuf* result)
{
// https://stackoverflow.com/questions/301215/getting-desktop-background-on-mac
#ifdef FF_HAVE_SQLITE3
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateCopy(&instance.state.platform.homeDir);
ffStrbufAppendS(&path, "Library/Application Support/Dock/desktoppicture.db");
if (ffSettingsGetSQLite3String(path.chars,
"SELECT value\n"
"FROM preferences\n"
"JOIN data ON preferences.data_id=data.ROWID\n"
"JOIN pictures ON preferences.picture_id=pictures.ROWID\n"
"JOIN displays ON pictures.display_id=displays.ROWID\n"
"JOIN spaces ON pictures.space_id=spaces.ROWID\n"
"WHERE display_id=1 AND space_id=1 AND key=1", result)
)
return NULL;
#endif
if (!ffOsascript("tell application \"Finder\" to get POSIX path of (get desktop picture as alias)", result))
return "ffOsascript(get desktop picture) failed";
return NULL;
}
+72
View File
@@ -0,0 +1,72 @@
#include "wallpaper.h"
#include "common/settings.h"
#include "util/apple/osascript.h"
#import <Foundation/Foundation.h>
const char* ffDetectWallpaper(FFstrbuf* result)
{
{
// For Sonoma
// https://github.com/JohnCoates/Aerial/issues/1332
NSError* error;
NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Application Support/com.apple.wallpaper/Store/Index.plist", instance.state.platform.homeDir.chars];
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
error:&error];
if (!error)
{
NSArray* choices = [dict valueForKeyPath:@"SystemDefault.Desktop.Content.Choices"];
if (choices.count > 0)
{
NSDictionary* choice = [choices objectAtIndex:0];
NSArray* files = [choice valueForKey:@"Files"];
if (files.count > 0)
{
NSString* file = [[files objectAtIndex: 0] valueForKey: @"relative"];
ffStrbufAppendS(result, [NSURL URLWithString:file].path.UTF8String);
}
else
{
NSString* provider = [choice valueForKey:@"Provider"];
NSString* builtinPrefix = @"com.apple.wallpaper.choice.";
if ([provider hasPrefix:builtinPrefix])
provider = [provider substringFromIndex:builtinPrefix.length];
if ([provider isEqualToString:@"sonoma"])
ffStrbufSetStatic(result, "macOS Sonoma");
else if ([provider isEqualToString:@"aerials"]) // Most builtin aerial wallpapers are private
ffStrbufSetStatic(result, "Built-in aerial photography");
else
ffStrbufAppendF(result, "Built-in %s wallpaper", provider.UTF8String);
}
}
if (result->length > 0)
return NULL;
}
}
#ifdef FF_HAVE_SQLITE3
{
// For Ventura
// https://stackoverflow.com/questions/301215/getting-desktop-background-on-mac
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateCopy(&instance.state.platform.homeDir);
ffStrbufAppendS(&path, "Library/Application Support/Dock/desktoppicture.db");
if (ffSettingsGetSQLite3String(path.chars,
"SELECT value\n"
"FROM preferences\n"
"JOIN data ON preferences.data_id=data.ROWID\n"
"JOIN pictures ON preferences.picture_id=pictures.ROWID\n"
"JOIN displays ON pictures.display_id=displays.ROWID\n"
"JOIN spaces ON pictures.space_id=spaces.ROWID\n"
"WHERE display_id=1 AND space_id=1 AND key=1", result)
)
return NULL;
}
#endif
if (ffOsascript("tell application \"Finder\" to get POSIX path of (get desktop picture as alias)", result))
return NULL;
return "All detection methods failed";
}
+1 -1
View File
@@ -17,7 +17,7 @@ static NSDictionary* getWifiInfoByApple80211(NSString* ifName)
struct Apple80211* handle = NULL;
if (Apple80211Open(&handle) < 0) return NULL;
if (Apple80211BindToInterface(handle, (CFStringRef)ifName) < 0) return NULL;
if (Apple80211BindToInterface(handle, (__bridge CFStringRef)ifName) < 0) return NULL;
CFDictionaryRef result;
if (Apple80211GetInfoCopy(handle, &result) < 0) return NULL;
Apple80211Close(handle);
+19 -17
View File
@@ -87,43 +87,43 @@ static const char* detectWifiWithLibnm(FFlist* result)
switch(state)
{
case NM_DEVICE_STATE_UNKNOWN:
ffStrbufAppendS(&item->inf.status, "Unknown");
ffStrbufSetStatic(&item->inf.status, "Unknown");
break;
case NM_DEVICE_STATE_UNMANAGED:
ffStrbufAppendS(&item->inf.status, "Unmanaged");
ffStrbufSetStatic(&item->inf.status, "Unmanaged");
break;
case NM_DEVICE_STATE_UNAVAILABLE:
ffStrbufAppendS(&item->inf.status, "Unavailable");
ffStrbufSetStatic(&item->inf.status, "Unavailable");
break;
case NM_DEVICE_STATE_DISCONNECTED:
ffStrbufAppendS(&item->inf.status, "Disconnected");
ffStrbufSetStatic(&item->inf.status, "Disconnected");
break;
case NM_DEVICE_STATE_PREPARE:
ffStrbufAppendS(&item->inf.status, "Prepare");
ffStrbufSetStatic(&item->inf.status, "Prepare");
break;
case NM_DEVICE_STATE_CONFIG:
ffStrbufAppendS(&item->inf.status, "Config");
ffStrbufSetStatic(&item->inf.status, "Config");
break;
case NM_DEVICE_STATE_NEED_AUTH:
ffStrbufAppendS(&item->inf.status, "Need auth");
ffStrbufSetStatic(&item->inf.status, "Need auth");
break;
case NM_DEVICE_STATE_IP_CONFIG:
ffStrbufAppendS(&item->inf.status, "IP config");
ffStrbufSetStatic(&item->inf.status, "IP config");
break;
case NM_DEVICE_STATE_IP_CHECK:
ffStrbufAppendS(&item->inf.status, "IP check");
ffStrbufSetStatic(&item->inf.status, "IP check");
break;
case NM_DEVICE_STATE_SECONDARIES:
ffStrbufAppendS(&item->inf.status, "Secondaries");
ffStrbufSetStatic(&item->inf.status, "Secondaries");
break;
case NM_DEVICE_STATE_ACTIVATED:
ffStrbufAppendS(&item->inf.status, "Activated");
ffStrbufSetStatic(&item->inf.status, "Activated");
break;
case NM_DEVICE_STATE_DEACTIVATING:
ffStrbufAppendS(&item->inf.status, "Deactivating");
ffStrbufSetStatic(&item->inf.status, "Deactivating");
break;
case NM_DEVICE_STATE_FAILED:
ffStrbufAppendS(&item->inf.status, "Failed");
ffStrbufSetStatic(&item->inf.status, "Failed");
break;
}
if(state != NM_DEVICE_STATE_ACTIVATED)
@@ -133,6 +133,8 @@ static const char* detectWifiWithLibnm(FFlist* result)
if (!ap)
continue;
ffStrbufSetStatic(&item->conn.status, "Connected");
GBytes* activeSsid = ffnm_access_point_get_ssid(ap);
if (activeSsid)
{
@@ -161,13 +163,13 @@ static const char* detectWifiWithLibnm(FFlist* result)
if(ffParsePropLines(output.chars, "tx bitrate: ", &item->conn.protocol))
{
if(ffStrbufContainS(&item->conn.protocol, " HE-MCS "))
ffStrbufSetS(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else if(ffStrbufContainS(&item->conn.protocol, " VHT-MCS "))
ffStrbufSetS(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if(ffStrbufContainS(&item->conn.protocol, " MCS "))
ffStrbufSetS(&item->conn.protocol, "802.11n (Wi-Fi 4)");
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
else
ffStrbufSetS(&item->conn.protocol, "802.11a/b/g");
ffStrbufClear(&item->conn.protocol);
sscanf(item->conn.protocol.chars, "%lf", &item->conn.txRate);
}
+1 -1
View File
@@ -25,7 +25,7 @@ private:
extern "C"
const char* ffDetectWMPlugin(FFstrbuf* pluginName)
{
DWORD pid = ffDetectTerminalShell()->terminalPid; // Whatever GUI program
DWORD pid = ffDetectTerminal()->pid; // Whatever GUI program
if (pid == 0) return "Unable to find a GUI program";
FF_AUTO_CLOSE_FD HANDLE snapshot = NULL;
+5 -5
View File
@@ -498,14 +498,14 @@ void ffLogoPrint(void)
//Make sure the logo path is set correctly.
updateLogoPath();
const FFTerminalShellResult* terminalShell = ffDetectTerminalShell();
const FFTerminalResult* terminal = ffDetectTerminal();
//Terminal emulators that support kitty graphics protocol.
bool supportsKitty =
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "kitty") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wezterm") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "wayst") == 0;
ffStrbufIgnCaseEqualS(&terminal->processName, "kitty") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "konsole") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "wezterm") ||
ffStrbufIgnCaseEqualS(&terminal->processName, "wayst");
//Try to load the logo as an image. If it succeeds, print it and return.
if(logoPrintImageIfExists(supportsKitty ? FF_LOGO_TYPE_IMAGE_KITTY : FF_LOGO_TYPE_IMAGE_CHAFA, false))
+12 -29
View File
@@ -6,7 +6,7 @@
#include "modules/battery/battery.h"
#include "util/stringUtils.h"
#define FF_BATTERY_NUM_FORMAT_ARGS 7
#define FF_BATTERY_NUM_FORMAT_ARGS 8
static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index)
{
@@ -71,6 +71,8 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
{FF_FORMAT_ARG_TYPE_STRBUF, &result->status},
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature},
{FF_FORMAT_ARG_TYPE_UINT, &result->cycleCount},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->serial},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufactureDate},
});
}
}
@@ -96,6 +98,8 @@ void ffPrintBattery(FFBatteryOptions* options)
ffStrbufDestroy(&result->modelName);
ffStrbufDestroy(&result->technology);
ffStrbufDestroy(&result->status);
ffStrbufDestroy(&result->serial);
ffStrbufDestroy(&result->manufactureDate);
}
if(results.length == 0)
ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, "No batteries found");
@@ -115,14 +119,6 @@ bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, co
return true;
}
#ifdef __linux__
if (ffStrEqualsIgnCase(subKey, "dir"))
{
ffOptionParseString(key, value, &options->dir);
return true;
}
#endif
#ifdef _WIN32
if (ffStrEqualsIgnCase(subKey, "use-setup-api"))
{
@@ -147,14 +143,6 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module)
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
#ifdef __linux__
if (ffStrEqualsIgnCase(key, "dir"))
{
ffStrbufSetS(&options->dir, yyjson_get_str(val));
continue;
}
#endif
#ifdef _WIN32
if (ffStrEqualsIgnCase(key, "useSetupApi"))
{
@@ -180,11 +168,6 @@ void ffGenerateBatteryJsonConfig(FFBatteryOptions* options, yyjson_mut_doc* doc,
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
#ifdef __linux__
if (!ffStrbufEqual(&defaultOptions.dir, &options->dir))
yyjson_mut_obj_add_strbuf(doc, module, "dir", &options->dir);
#endif
#ifdef _WIN32
if (defaultOptions.useSetupApi != options->useSetupApi)
yyjson_mut_obj_add_bool(doc, module, "useSetupApi", options->useSetupApi);
@@ -212,9 +195,11 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc,
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_real(doc, obj, "capacity", battery->capacity);
yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &battery->manufacturer);
yyjson_mut_obj_add_strbuf(doc, obj, "manufactureDate", &battery->manufactureDate);
yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &battery->modelName);
yyjson_mut_obj_add_strbuf(doc, obj, "status", &battery->status);
yyjson_mut_obj_add_strbuf(doc, obj, "technology", &battery->technology);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &battery->serial);
yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature);
yyjson_mut_obj_add_uint(doc, obj, "cycleCount", battery->cycleCount);
}
@@ -222,9 +207,11 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc,
FF_LIST_FOR_EACH(FFBatteryResult, battery, results)
{
ffStrbufDestroy(&battery->manufacturer);
ffStrbufDestroy(&battery->manufactureDate);
ffStrbufDestroy(&battery->modelName);
ffStrbufDestroy(&battery->technology);
ffStrbufDestroy(&battery->status);
ffStrbufDestroy(&battery->serial);
}
}
@@ -238,6 +225,8 @@ void ffPrintBatteryHelpFormat(void)
"Battery status",
"Battery temperature",
"Battery cycle count",
"Battery serial number",
"Battery manufactor date",
});
}
@@ -257,9 +246,7 @@ void ffInitBatteryOptions(FFBatteryOptions* options)
ffOptionInitModuleArg(&options->moduleArgs);
options->temp = false;
#ifdef __linux__
ffStrbufInitStatic(&options->dir, "/sys/class/power_supply/");
#elif defined(_WIN32)
#ifdef _WIN32
options->useSetupApi = false;
#endif
}
@@ -267,8 +254,4 @@ void ffInitBatteryOptions(FFBatteryOptions* options)
void ffDestroyBatteryOptions(FFBatteryOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
#ifdef __linux__
ffStrbufDestroy(&options->dir);
#endif
}
+1 -3
View File
@@ -11,9 +11,7 @@ typedef struct FFBatteryOptions
bool temp;
#ifdef __linux__
FFstrbuf dir;
#elif defined(_WIN32)
#ifdef _WIN32
bool useSetupApi;
#endif
} FFBatteryOptions;
+9 -2
View File
@@ -12,8 +12,9 @@ void ffPrintBoard(FFBoardOptions* options)
ffStrbufInit(&result.name);
ffStrbufInit(&result.vendor);
ffStrbufInit(&result.version);
const char* error = ffDetectBoard(&result);
ffStrbufInit(&result.serial);
const char* error = ffDetectBoard(&result);
if(error)
{
ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, "%s", error);
@@ -40,6 +41,7 @@ void ffPrintBoard(FFBoardOptions* options)
{FF_FORMAT_ARG_TYPE_STRBUF, &result.name},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.version},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.serial},
});
}
@@ -47,6 +49,7 @@ exit:
ffStrbufDestroy(&result.name);
ffStrbufDestroy(&result.vendor);
ffStrbufDestroy(&result.version);
ffStrbufDestroy(&result.serial);
}
bool ffParseBoardCommandOptions(FFBoardOptions* options, const char* key, const char* value)
@@ -90,6 +93,7 @@ void ffGenerateBoardJsonResult(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_m
ffStrbufInit(&board.name);
ffStrbufInit(&board.vendor);
ffStrbufInit(&board.version);
ffStrbufInit(&board.serial);
const char* error = ffDetectBoard(&board);
@@ -109,11 +113,13 @@ void ffGenerateBoardJsonResult(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_m
yyjson_mut_obj_add_strbuf(doc, obj, "name", &board.name);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &board.vendor);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &board.version);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &board.serial);
exit:
ffStrbufDestroy(&board.name);
ffStrbufDestroy(&board.vendor);
ffStrbufDestroy(&board.version);
ffStrbufDestroy(&board.serial);
}
void ffPrintBoardHelpFormat(void)
@@ -121,7 +127,8 @@ void ffPrintBoardHelpFormat(void)
ffPrintModuleFormatHelp(FF_BOARD_MODULE_NAME, "{1} ({3})", FF_BOARD_NUM_FORMAT_ARGS, (const char* []) {
"board name",
"board vendor",
"board version"
"board version",
"board serial number",
});
}
+10 -28
View File
@@ -12,8 +12,9 @@ void ffPrintChassis(FFChassisOptions* options)
ffStrbufInit(&result.type);
ffStrbufInit(&result.vendor);
ffStrbufInit(&result.version);
ffStrbufInit(&result.serial);
const char* error = ffDetectChassis(&result, options);
const char* error = ffDetectChassis(&result);
if(error)
{
@@ -41,6 +42,7 @@ void ffPrintChassis(FFChassisOptions* options)
{FF_FORMAT_ARG_TYPE_STRBUF, &result.type},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.version},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.serial},
});
}
@@ -48,6 +50,7 @@ exit:
ffStrbufDestroy(&result.type);
ffStrbufDestroy(&result.vendor);
ffStrbufDestroy(&result.version);
ffStrbufDestroy(&result.serial);
}
bool ffParseChassisCommandOptions(FFChassisOptions* options, const char* key, const char* value)
@@ -57,14 +60,6 @@ bool ffParseChassisCommandOptions(FFChassisOptions* options, const char* key, co
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
#ifdef _WIN32
if (ffStrEqualsIgnCase(subKey, "use-wmi"))
{
options->useWmi = ffOptionParseBoolean(value);
return true;
}
#endif
return false;
}
@@ -81,14 +76,6 @@ void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module)
if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs))
continue;
#ifdef _WIN32
if (ffStrEqualsIgnCase(key, "useWmi"))
{
options->useWmi = yyjson_get_bool(val);
continue;
}
#endif
ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key);
}
}
@@ -99,11 +86,6 @@ void ffGenerateChassisJsonConfig(FFChassisOptions* options, yyjson_mut_doc* doc,
ffInitChassisOptions(&defaultOptions);
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
#ifdef _WIN32
if (options->useWmi != defaultOptions.useWmi)
yyjson_mut_obj_add_bool(doc, module, "useWmi", options->useWmi);
#endif
}
void ffGenerateChassisJsonResult(FF_MAYBE_UNUSED FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
@@ -112,8 +94,9 @@ void ffGenerateChassisJsonResult(FF_MAYBE_UNUSED FFChassisOptions* options, yyjs
ffStrbufInit(&result.type);
ffStrbufInit(&result.vendor);
ffStrbufInit(&result.version);
ffStrbufInit(&result.serial);
const char* error = ffDetectChassis(&result, options);
const char* error = ffDetectChassis(&result);
if (error)
{
@@ -131,11 +114,13 @@ void ffGenerateChassisJsonResult(FF_MAYBE_UNUSED FFChassisOptions* options, yyjs
yyjson_mut_obj_add_strbuf(doc, obj, "type", &result.type);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result.vendor);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &result.serial);
exit:
ffStrbufDestroy(&result.type);
ffStrbufDestroy(&result.vendor);
ffStrbufDestroy(&result.version);
ffStrbufDestroy(&result.serial);
}
void ffPrintChassisHelpFormat(void)
@@ -143,7 +128,8 @@ void ffPrintChassisHelpFormat(void)
ffPrintModuleFormatHelp(FF_CHASSIS_MODULE_NAME, "{1}", FF_CHASSIS_NUM_FORMAT_ARGS, (const char* []) {
"chassis type",
"chassis vendor",
"chassis version"
"chassis version",
"chassis serial number",
});
}
@@ -161,10 +147,6 @@ void ffInitChassisOptions(FFChassisOptions* options)
ffGenerateChassisJsonConfig
);
ffOptionInitModuleArg(&options->moduleArgs);
#ifdef _WIN32
options->useWmi = false;
#endif
}
void ffDestroyChassisOptions(FFChassisOptions* options)
-4
View File
@@ -8,8 +8,4 @@ typedef struct FFChassisOptions
{
FFModuleBaseInfo moduleInfo;
FFModuleArgs moduleArgs;
#ifdef _WIN32
bool useWmi;
#endif
} FFChassisOptions;
+15 -6
View File
@@ -1,3 +1,4 @@
#include "common/bar.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/gamepad/gamepad.h"
@@ -10,14 +11,21 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device
{
if(options->moduleArgs.outputFormat.length == 0)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name);
ffPrintLogoAndKey(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufPutTo(&device->name, stdout);
if (device->battery > 0 && device->battery <= 100)
{
ffStrbufAppendC(&buffer, ' ');
ffAppendPercentNum(&buffer, device->battery, 51, 21, true);
}
ffStrbufPutTo(&buffer, stdout);
}
else
{
ffPrintFormat(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->serial},
{FF_FORMAT_ARG_TYPE_UINT8, &device->battery},
});
}
}
@@ -44,7 +52,7 @@ void ffPrintGamepad(FFGamepadOptions* options)
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
{
printDevice(options, device, result.length > 1 ? ++index : 0);
ffStrbufDestroy(&device->identifier);
ffStrbufDestroy(&device->serial);
ffStrbufDestroy(&device->name);
}
}
@@ -106,13 +114,13 @@ void ffGenerateGamepadJsonResult(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjs
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &device->identifier);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name);
}
FF_LIST_FOR_EACH(FFGamepadDevice, device, result)
{
ffStrbufDestroy(&device->identifier);
ffStrbufDestroy(&device->serial);
ffStrbufDestroy(&device->name);
}
}
@@ -121,7 +129,8 @@ void ffPrintGamepadHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_GAMEPAD_MODULE_NAME, "{1}", FF_GAMEPAD_NUM_FORMAT_ARGS, (const char* []) {
"Name",
"Identifier"
"Serial number",
"Battery",
});
}
+55 -41
View File
@@ -4,25 +4,27 @@
#include "modules/host/host.h"
#include "util/stringUtils.h"
#define FF_HOST_NUM_FORMAT_ARGS 5
#define FF_HOST_NUM_FORMAT_ARGS 7
void ffPrintHost(FFHostOptions* options)
{
FFHostResult host;
ffStrbufInit(&host.productFamily);
ffStrbufInit(&host.productName);
ffStrbufInit(&host.productVersion);
ffStrbufInit(&host.productSku);
ffStrbufInit(&host.sysVendor);
const char* error = ffDetectHost(&host);
ffStrbufInit(&host.family);
ffStrbufInit(&host.name);
ffStrbufInit(&host.version);
ffStrbufInit(&host.sku);
ffStrbufInit(&host.serial);
ffStrbufInit(&host.uuid);
ffStrbufInit(&host.vendor);
const char* error = ffDetectHost(&host);
if(error)
{
ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, "%s", error);
goto exit;
}
if(host.productFamily.length == 0 && host.productName.length == 0)
if(host.family.length == 0 && host.name.length == 0)
{
ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, "neither product_family nor product_name is set by O.E.M.");
goto exit;
@@ -34,33 +36,37 @@ void ffPrintHost(FFHostOptions* options)
FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate();
if(host.productName.length > 0)
ffStrbufAppend(&output, &host.productName);
if(host.name.length > 0)
ffStrbufAppend(&output, &host.name);
else
ffStrbufAppend(&output, &host.productFamily);
ffStrbufAppend(&output, &host.family);
if(host.productVersion.length > 0)
ffStrbufAppendF(&output, " (%s)", host.productVersion.chars);
if(host.version.length > 0)
ffStrbufAppendF(&output, " (%s)", host.version.chars);
ffStrbufPutTo(&output, stdout);
}
else
{
ffPrintFormat(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &host.productFamily},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.productName},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.productVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.productSku},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.sysVendor}
{FF_FORMAT_ARG_TYPE_STRBUF, &host.family},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.name},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.version},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.sku},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.serial},
{FF_FORMAT_ARG_TYPE_STRBUF, &host.uuid},
});
}
exit:
ffStrbufDestroy(&host.productFamily);
ffStrbufDestroy(&host.productName);
ffStrbufDestroy(&host.productVersion);
ffStrbufDestroy(&host.productSku);
ffStrbufDestroy(&host.sysVendor);
ffStrbufDestroy(&host.family);
ffStrbufDestroy(&host.name);
ffStrbufDestroy(&host.version);
ffStrbufDestroy(&host.sku);
ffStrbufDestroy(&host.serial);
ffStrbufDestroy(&host.uuid);
ffStrbufDestroy(&host.vendor);
}
bool ffParseHostCommandOptions(FFHostOptions* options, const char* key, const char* value)
@@ -101,38 +107,44 @@ void ffGenerateHostJsonConfig(FFHostOptions* options, yyjson_mut_doc* doc, yyjso
void ffGenerateHostJsonResult(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
FFHostResult host;
ffStrbufInit(&host.productFamily);
ffStrbufInit(&host.productName);
ffStrbufInit(&host.productVersion);
ffStrbufInit(&host.productSku);
ffStrbufInit(&host.sysVendor);
const char* error = ffDetectHost(&host);
ffStrbufInit(&host.family);
ffStrbufInit(&host.name);
ffStrbufInit(&host.version);
ffStrbufInit(&host.sku);
ffStrbufInit(&host.serial);
ffStrbufInit(&host.uuid);
ffStrbufInit(&host.vendor);
const char* error = ffDetectHost(&host);
if (error)
{
yyjson_mut_obj_add_str(doc, module, "error", error);
goto exit;
}
if (host.productFamily.length == 0 && host.productName.length == 0)
if (host.family.length == 0 && host.name.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "neither product_family nor product_name is set by O.E.M.");
goto exit;
}
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "family", &host.productFamily);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &host.productName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &host.productVersion);
yyjson_mut_obj_add_strbuf(doc, obj, "sku", &host.productSku);
yyjson_mut_obj_add_strbuf(doc, obj, "sysVender", &host.sysVendor);
yyjson_mut_obj_add_strbuf(doc, obj, "family", &host.family);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &host.name);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &host.version);
yyjson_mut_obj_add_strbuf(doc, obj, "sku", &host.sku);
yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &host.vendor);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &host.serial);
yyjson_mut_obj_add_strbuf(doc, obj, "uuid", &host.uuid);
exit:
ffStrbufDestroy(&host.productFamily);
ffStrbufDestroy(&host.productName);
ffStrbufDestroy(&host.productVersion);
ffStrbufDestroy(&host.productSku);
ffStrbufDestroy(&host.sysVendor);
ffStrbufDestroy(&host.family);
ffStrbufDestroy(&host.name);
ffStrbufDestroy(&host.version);
ffStrbufDestroy(&host.sku);
ffStrbufDestroy(&host.serial);
ffStrbufDestroy(&host.uuid);
ffStrbufDestroy(&host.vendor);
}
void ffPrintHostHelpFormat(void)
@@ -142,7 +154,9 @@ void ffPrintHostHelpFormat(void)
"product name",
"product version",
"product sku",
"sys vendor"
"product vendor",
"product serial number",
"product uuid",
});
}
+39 -5
View File
@@ -59,6 +59,15 @@ void ffPrintMonitor(FFMonitorOptions* options)
}
else
{
char buf[32];
if (display->serial)
{
const uint8_t* nums = (uint8_t*) &display->serial;
snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]);
}
else
buf[0] = '\0';
ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_MONITOR_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &display->name},
{FF_FORMAT_ARG_TYPE_UINT, &display->width},
@@ -67,6 +76,9 @@ void ffPrintMonitor(FFMonitorOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &display->physicalHeight},
{FF_FORMAT_ARG_TYPE_DOUBLE, &inch},
{FF_FORMAT_ARG_TYPE_DOUBLE, &ppi},
{FF_FORMAT_ARG_TYPE_UINT16, &display->manufactureYear},
{FF_FORMAT_ARG_TYPE_UINT16, &display->manufactureWeek},
{FF_FORMAT_ARG_TYPE_STRING, buf},
});
}
@@ -131,11 +143,31 @@ void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjs
{
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
yyjson_mut_obj_add_bool(doc, obj, "hdrCompatible", item->hdrCompatible);
yyjson_mut_obj_add_uint(doc, obj, "width", item->width);
yyjson_mut_obj_add_uint(doc, obj, "height", item->height);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_uint(doc, obj, "physicalHeight", item->physicalHeight);
yyjson_mut_obj_add_uint(doc, obj, "physicalWidth", item->physicalWidth);
yyjson_mut_val* resolution = yyjson_mut_obj_add_obj(doc, obj, "resolution");
yyjson_mut_obj_add_uint(doc, resolution, "width", item->width);
yyjson_mut_obj_add_uint(doc, resolution, "height", item->height);
yyjson_mut_val* physical = yyjson_mut_obj_add_obj(doc, obj, "physical");
yyjson_mut_obj_add_uint(doc, physical, "height", item->physicalHeight);
yyjson_mut_obj_add_uint(doc, physical, "width", item->physicalWidth);
if (item->manufactureYear)
{
yyjson_mut_val* manufactureDate = yyjson_mut_obj_add_obj(doc, obj, "manufactureDate");
yyjson_mut_obj_add_uint(doc, manufactureDate, "year", item->manufactureYear);
yyjson_mut_obj_add_uint(doc, manufactureDate, "week", item->manufactureWeek);
}
else
{
yyjson_mut_obj_add_null(doc, obj, "manufactureDate");
}
if (item->serial)
yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial);
else
yyjson_mut_obj_add_null(doc, obj, "serial");
}
}
@@ -154,7 +186,9 @@ void ffPrintMonitorHelpFormat(void)
"Display physical width in millimeters",
"Display physical height in millimeters",
"Display physical diagonal length in inches",
"Display physical pixels per inch (PPI)"
"Year of manufacturing",
"Nth week of manufacturing in the year",
"Serial number",
});
}
+24 -23
View File
@@ -5,13 +5,13 @@
#include "util/stringUtils.h"
#define FF_POWERADAPTER_DISPLAY_NAME "Power Adapter"
#define FF_POWERADAPTER_NUM_FORMAT_ARGS 5
#define FF_POWERADAPTER_NUM_FORMAT_ARGS 6
void ffPrintPowerAdapter(FFPowerAdapterOptions* options)
{
FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFPowerAdapterResult));
const char* error = ffDetectPowerAdapterImpl(&results);
const char* error = ffDetectPowerAdapter(&results);
if (error)
{
@@ -27,35 +27,34 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options)
{
FFPowerAdapterResult* result = ffListGet(&results, i);
if(result->watts != FF_POWERADAPTER_UNSET)
if(options->moduleArgs.outputFormat.length == 0)
{
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffPrintLogoAndKey(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
if(result->name.length > 0)
puts(result->name.chars);
else if(result->watts == FF_POWERADAPTER_NOT_CONNECTED)
puts("not connected");
else
printf("%dW\n", result->watts);
}
if(result->name.length > 0)
puts(result->name.chars);
else if(result->watts == FF_POWERADAPTER_NOT_CONNECTED)
puts("not connected");
else
{
ffPrintFormat(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_POWERADAPTER_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_INT, &result->watts},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->description},
});
}
printf("%dW\n", result->watts);
}
else
{
ffPrintFormat(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_POWERADAPTER_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_INT, &result->watts},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->manufacturer},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->modelName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->description},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->serial},
});
}
ffStrbufDestroy(&result->manufacturer);
ffStrbufDestroy(&result->description);
ffStrbufDestroy(&result->modelName);
ffStrbufDestroy(&result->name);
ffStrbufDestroy(&result->serial);
}
}
}
@@ -99,7 +98,7 @@ void ffGeneratePowerAdapterJsonResult(FF_MAYBE_UNUSED FFPowerAdapterOptions* opt
{
FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFPowerAdapterResult));
const char* error = ffDetectPowerAdapterImpl(&results);
const char* error = ffDetectPowerAdapter(&results);
if (error)
{
@@ -119,6 +118,7 @@ void ffGeneratePowerAdapterJsonResult(FF_MAYBE_UNUSED FFPowerAdapterOptions* opt
yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &item->manufacturer);
yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &item->modelName);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name);
yyjson_mut_obj_add_strbuf(doc, obj, "serial", &item->serial);
yyjson_mut_obj_add_int(doc, obj, "watts", item->watts);
}
}
@@ -132,6 +132,7 @@ void ffPrintPowerAdapterHelpFormat(void)
"PowerAdapter manufacturer",
"PowerAdapter model",
"PowerAdapter description"
"PowerAdapter serial number"
});
}
+19 -18
View File
@@ -8,9 +8,9 @@
void ffPrintShell(FFShellOptions* options)
{
const FFTerminalShellResult* result = ffDetectTerminalShell();
const FFShellResult* result = ffDetectShell();
if(result->shellProcessName.length == 0)
if(result->processName.length == 0)
{
ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, "Couldn't detect shell");
return;
@@ -19,12 +19,12 @@ void ffPrintShell(FFShellOptions* options)
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufWriteTo(&result->shellPrettyName, stdout);
ffStrbufWriteTo(&result->prettyName, stdout);
if(result->shellVersion.length > 0)
if(result->version.length > 0)
{
putchar(' ');
ffStrbufWriteTo(&result->shellVersion, stdout);
ffStrbufWriteTo(&result->version, stdout);
}
putchar('\n');
@@ -32,12 +32,12 @@ void ffPrintShell(FFShellOptions* options)
else
{
ffPrintFormat(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_SHELL_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &result->shellProcessName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->shellExe},
{FF_FORMAT_ARG_TYPE_STRING, result->shellExeName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->shellVersion},
{FF_FORMAT_ARG_TYPE_UINT, &result->shellPid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->shellPrettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->processName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->exe},
{FF_FORMAT_ARG_TYPE_STRING, result->exeName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
{FF_FORMAT_ARG_TYPE_UINT, &result->pid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
});
}
}
@@ -79,20 +79,21 @@ void ffGenerateShellJsonConfig(FFShellOptions* options, yyjson_mut_doc* doc, yyj
void ffGenerateShellJsonResult(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
const FFTerminalShellResult* result = ffDetectTerminalShell();
const FFShellResult* result = ffDetectShell();
if(result->shellProcessName.length == 0)
if(result->processName.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect shell");
return;
}
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->shellExe);
yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->shellExeName);
yyjson_mut_obj_add_uint(doc, obj, "pid", result->shellPid);
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->shellVersion);
yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->exe);
yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->exeName);
yyjson_mut_obj_add_uint(doc, obj, "pid", result->pid);
yyjson_mut_obj_add_uint(doc, obj, "ppid", result->ppid);
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->processName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->version);
}
void ffPrintShellHelpFormat(void)
+20 -19
View File
@@ -10,9 +10,9 @@
void ffPrintTerminal(FFTerminalOptions* options)
{
const FFTerminalShellResult* result = ffDetectTerminalShell();
const FFTerminalResult* result = ffDetectTerminal();
if(result->terminalProcessName.length == 0)
if(result->processName.length == 0)
{
ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, "Couldn't detect terminal");
return;
@@ -22,20 +22,20 @@ void ffPrintTerminal(FFTerminalOptions* options)
{
ffPrintLogoAndKey(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
if(result->terminalVersion.length)
printf("%s %s\n", result->terminalPrettyName.chars, result->terminalVersion.chars);
if(result->version.length)
printf("%s %s\n", result->prettyName.chars, result->version.chars);
else
ffStrbufPutTo(&result->terminalPrettyName, stdout);
ffStrbufPutTo(&result->prettyName, stdout);
}
else
{
ffPrintFormat(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_TERMINAL_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalProcessName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalExe},
{FF_FORMAT_ARG_TYPE_STRING, result->terminalExeName},
{FF_FORMAT_ARG_TYPE_UINT, &result->terminalPid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalPrettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->processName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->exe},
{FF_FORMAT_ARG_TYPE_STRING, result->exeName},
{FF_FORMAT_ARG_TYPE_UINT, &result->pid},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->prettyName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->version},
});
}
}
@@ -77,21 +77,22 @@ void ffGenerateTerminalJsonConfig(FFTerminalOptions* options, yyjson_mut_doc* do
void ffGenerateTerminalJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
{
const FFTerminalShellResult* result = ffDetectTerminalShell();
const FFTerminalResult* result = ffDetectTerminal();
if(result->terminalProcessName.length == 0)
if(result->processName.length == 0)
{
yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect terminal");
return;
}
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->terminalProcessName);
yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->terminalExe);
yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->terminalExeName);
yyjson_mut_obj_add_uint(doc, obj, "pid", result->terminalPid);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->terminalPrettyName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->terminalVersion);
yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->processName);
yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->exe);
yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->exeName);
yyjson_mut_obj_add_uint(doc, obj, "pid", result->pid);
yyjson_mut_obj_add_uint(doc, obj, "ppid", result->ppid);
yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->prettyName);
yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->version);
}
void ffPrintTerminalHelpFormat(void)
+10 -1
View File
@@ -21,6 +21,13 @@ void ffPrintVulkan(FFVulkanOptions* options)
{
ffPrintLogoAndKey(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
if (vulkan->apiVersion.length == 0 && vulkan->driver.length == 0)
{
ffStrbufWriteTo(&vulkan->instanceVersion, stdout);
puts(" [Software only]");
return;
}
if(vulkan->apiVersion.length > 0)
{
ffStrbufWriteTo(&vulkan->apiVersion, stdout);
@@ -101,6 +108,7 @@ void ffGenerateVulkanJsonResult(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson
yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &vulkanGpu->vendor);
yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &vulkanGpu->name);
yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &vulkanGpu->driver);
yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &vulkanGpu->platformApi);
yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory");
@@ -139,7 +147,8 @@ void ffPrintVulkanHelpFormat(void)
ffPrintModuleFormatHelp(FF_VULKAN_MODULE_NAME, "{2} - {1}", FF_VULKAN_NUM_FORMAT_ARGS, (const char* []) {
"Driver name",
"API version",
"Conformance version"
"Conformance version",
"Instance version",
});
}
+23 -8
View File
@@ -249,13 +249,17 @@ void ffStrbufTrimLeft(FFstrbuf* strbuf, char c)
void ffStrbufTrimRight(FFstrbuf* strbuf, char c)
{
if(strbuf->length == 0)
if (strbuf->length == 0)
return;
while(ffStrbufEndsWithC(strbuf, c))
--strbuf->length;
if (!ffStrbufEndsWithC(strbuf, c))
return;
if(strbuf->allocated == 0)
do
--strbuf->length;
while (ffStrbufEndsWithC(strbuf, c));
if (strbuf->allocated == 0)
{
//static string
ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars);
@@ -267,13 +271,17 @@ void ffStrbufTrimRight(FFstrbuf* strbuf, char c)
void ffStrbufTrimRightSpace(FFstrbuf* strbuf)
{
if(strbuf->length == 0)
if (strbuf->length == 0)
return;
while(ffStrbufEndsWithFn(strbuf, isspace))
--strbuf->length;
if (!ffStrbufEndsWithFn(strbuf, isspace))
return;
if(strbuf->allocated == 0)
do
--strbuf->length;
while (ffStrbufEndsWithFn(strbuf, isspace));
if (strbuf->allocated == 0)
{
//static string
ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars);
@@ -470,6 +478,13 @@ uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue)
return str_end == strbuf->chars ? defaultValue : (uint64_t)result;
}
int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue)
{
char* str_end;
long long result = strtoll(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (int64_t)result;
}
void ffStrbufUpperCase(FFstrbuf* strbuf)
{
for (uint32_t i = 0; i < strbuf->length; ++i)
+3
View File
@@ -83,6 +83,7 @@ void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file);
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file);
FF_C_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf);
FF_C_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue);
FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue);
void ffStrbufUpperCase(FFstrbuf* strbuf);
@@ -222,6 +223,8 @@ FF_C_NODISCARD static inline FFstrbuf ffStrbufCreate()
static inline void ffStrbufInitStatic(FFstrbuf* strbuf, const char* str)
{
ffStrbufInit(strbuf);
if (!str) return;
strbuf->allocated = 0;
strbuf->length = (uint32_t) strlen(str);
strbuf->chars = (char*) str;

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