From 3c92e7013d1879ffb682888ae26017e32b656d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 26 Jul 2024 13:47:04 +0800 Subject: [PATCH 01/67] Doc: fix changelog [ci skip] --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e38e1245d6..b3a5239216 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Changes: * JSON option `display.keyWidth` has been renamed to `display.key.width` * Previously: `{ "display": { "keyWidth": 3 } }` * Now: `{ "display": { "key": { "width": 3 } } }` -* Windows Terminal font detection **in WSL** has been removed due to [issue #1113](https://github.com/fastfetch/fastfetch/issues/1113) +* Windows Terminal font detection **in WSL** has been removed due to [issue #1113](https://github.com/fastfetch-cli/fastfetch/issues/1113) Features: * Add option `display.key.type: ` to print icons in keys From ce43f06863d436c9927b295f8d5fbe4afc6a3449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 26 Jul 2024 23:08:24 +0800 Subject: [PATCH 02/67] DisplayServer (Linux): don't try to connect wayland and X11 in tty mode Fix #1110 --- .../displayserver/linux/displayserver_linux.c | 48 ++++- .../displayserver/linux/displayserver_linux.h | 3 +- .../displayserver/linux/wayland/wayland.c | 191 ++++++++---------- src/detection/displayserver/linux/wmde.c | 41 ---- 4 files changed, 129 insertions(+), 154 deletions(-) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index e864bdc07a..d8336f3a92 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -7,9 +7,48 @@ #include "common/settings.h" #endif +static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) +{ + const char* env = getenv("XDG_SESSION_TYPE"); + if(env) + { + if(ffStrEqualsIgnCase(env, "wayland")) + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); + else if(ffStrEqualsIgnCase(env, "x11") || ffStrEqualsIgnCase(env, "xorg")) + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); + else if(ffStrEqualsIgnCase(env, "tty")) + ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); + else + ffStrbufSetS(&result->wmProtocolName, env); + + return; + } + + if(getenv("WAYLAND_DISPLAY") != NULL || getenv("WAYLAND_SOCKET") != NULL) + { + ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); + return; + } + + if(getenv("DISPLAY") != NULL) // XWayland also set this + { + ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_X11); + return; + } + + env = getenv("TERM"); + if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux")) + { + ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); + return; + } +} + void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { - if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) + getWMProtocolNameFromEnv(ds); + + if (!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY) &&instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) { //We try wayland as our preferred display server, as it supports the most features. //This method can't detect the name of our WM / DE @@ -57,8 +96,11 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) } #endif - //This fills in missing information about WM / DE by using env vars and iterating processes - ffdsDetectWMDE(ds); + if(!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY)) + { + //This fills in missing information about WM / DE by using env vars and iterating processes + ffdsDetectWMDE(ds); + } } bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName) diff --git a/src/detection/displayserver/linux/displayserver_linux.h b/src/detection/displayserver/linux/displayserver_linux.h index c4937ee227..2a97e70080 100644 --- a/src/detection/displayserver/linux/displayserver_linux.h +++ b/src/detection/displayserver/linux/displayserver_linux.h @@ -7,8 +7,7 @@ bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName); -const char* ffdsConnectWlroots(FFDisplayServerResult* result); -void ffdsConnectWayland(FFDisplayServerResult* result); +const char* ffdsConnectWayland(FFDisplayServerResult* result); void ffdsConnectXcbRandr(FFDisplayServerResult* result); void ffdsConnectXcb(FFDisplayServerResult* result); diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 2bf03ebe7e..603d373aff 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -22,12 +22,14 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result) { struct ucred ucred; socklen_t len = sizeof(struct ucred); - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1 || ucred.pid <= 0) return false; FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate(); ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed. - ffReadFileBuffer(procPath.chars, &result->wmProcessName); + if (!ffReadFileBuffer(procPath.chars, &result->wmProcessName)) + return false; + ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path return true; @@ -69,27 +71,91 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u } } -bool detectWayland(FFDisplayServerResult* result) +void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name) +{ + WaylandDisplay* display = data; + if (display->id) return; + + display->type = ffdsGetDisplayType(name); + if (!display->edidName.length) + ffdsMatchDrmConnector(name, &display->edidName); + display->id = ffWaylandGenerateIdFromName(name); + ffStrbufAppendS(&display->name, name); +} + +void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description) +{ + WaylandDisplay* display = data; + if (display->description.length) return; + + while (*description == ' ') ++description; + if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)")) + ffStrbufAppendS(&display->description, description); +} + +uint32_t ffWaylandHandleRotation(WaylandDisplay* display) +{ + uint32_t rotation; + switch(display->transform) + { + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_90: + rotation = 90; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + case WL_OUTPUT_TRANSFORM_180: + rotation = 180; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + case WL_OUTPUT_TRANSFORM_270: + rotation = 270; + break; + default: + rotation = 0; + break; + } + + switch(rotation) + { + case 90: + case 270: { + int32_t temp = display->width; + display->width = display->height; + display->height = temp; + + temp = display->physicalWidth; + display->physicalWidth = display->physicalHeight; + display->physicalHeight = temp; + break; + } + default: + break; + } + return rotation; +} +#endif + +const char* ffdsConnectWayland(FFDisplayServerResult* result) { FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1) - FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false) - FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_get_fd, false) - FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false) - FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false) - FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_connect) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_get_fd) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_proxy_marshal_constructor) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_disconnect) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_registry_interface) WaylandData data = {}; - FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_marshal_constructor_versioned, false) - FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_add_listener, false) - FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_proxy_destroy, false) - FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_display_roundtrip, false) - FF_LIBRARY_LOAD_SYMBOL_VAR(wayland, data, wl_output_interface, false) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_marshal_constructor_versioned) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_add_listener) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_proxy_destroy) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_display_roundtrip) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_output_interface) data.display = ffwl_display_connect(NULL); if(data.display == NULL) - return false; + return "wl_display_connect returned NULL"; waylandDetectWM(ffwl_display_get_fd(data.display), result); @@ -97,7 +163,7 @@ bool detectWayland(FFDisplayServerResult* result) if(registry == NULL) { ffwl_display_disconnect(data.display); - return false; + return "wl_display_get_registry returned NULL"; } data.result = result; @@ -192,97 +258,6 @@ bool detectWayland(FFDisplayServerResult* result) //We successfully connected to wayland and detected the display. //So we can set set the session type to wayland. //This is used as an indicator that we are running wayland by the x11 backends. - ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); - return true; -} - -void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name) -{ - WaylandDisplay* display = data; - if (display->id) return; - - display->type = ffdsGetDisplayType(name); - if (!display->edidName.length) - ffdsMatchDrmConnector(name, &display->edidName); - display->id = ffWaylandGenerateIdFromName(name); - ffStrbufAppendS(&display->name, name); -} - -void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description) -{ - WaylandDisplay* display = data; - if (display->description.length) return; - - while (*description == ' ') ++description; - if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)")) - ffStrbufAppendS(&display->description, description); -} - -uint32_t ffWaylandHandleRotation(WaylandDisplay* display) -{ - uint32_t rotation; - switch(display->transform) - { - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - case WL_OUTPUT_TRANSFORM_90: - rotation = 90; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - case WL_OUTPUT_TRANSFORM_180: - rotation = 180; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - case WL_OUTPUT_TRANSFORM_270: - rotation = 270; - break; - default: - rotation = 0; - break; - } - - switch(rotation) - { - case 90: - case 270: { - int32_t temp = display->width; - display->width = display->height; - display->height = temp; - - temp = display->physicalWidth; - display->physicalWidth = display->physicalHeight; - display->physicalHeight = temp; - break; - } - default: - break; - } - return rotation; -} -#endif - -void ffdsConnectWayland(FFDisplayServerResult* result) -{ - //Wayland requires this to be set - if(getenv("XDG_RUNTIME_DIR") == NULL) - return; - - #ifdef FF_HAVE_WAYLAND - if(detectWayland(result)) - return; - #endif - - const char* xdgSessionType = getenv("XDG_SESSION_TYPE"); - - //If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session. - if(xdgSessionType != NULL && !ffStrEqualsIgnCase(xdgSessionType, "wayland")) - return; - - //If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY or WAYLAND_SOCKET is set. - //If not, there is no indicator for a wayland session - if(xdgSessionType == NULL && getenv("WAYLAND_DISPLAY") == NULL && getenv("WAYLAND_SOCKET") == NULL) - return; - - //We are probably running a wayland compositor at this point, - //but fastfetch was compiled without the required library, or loading the library failed. - ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); + ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); + return NULL; } diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 0319cdd454..8f50b69ab1 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -240,38 +240,6 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name) } } -static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) -{ - //This is only called if all connection attempts to a display server failed - //We don't need to check for wayland here, as the wayland code will always set the protocol name to wayland - - const char* env = getenv("XDG_SESSION_TYPE"); - if(ffStrSet(env)) - { - if(ffStrEqualsIgnCase(env, "x11")) - ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); - else if(ffStrEqualsIgnCase(env, "tty")) - ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); - else - ffStrbufSetS(&result->wmProtocolName, env); - - return; - } - - env = getenv("DISPLAY"); - if(ffStrSet(env)) - { - ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); - return; - } - - env = getenv("TERM"); - if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux")) - { - ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); - return; - } -} static const char* getFromProcesses(FFDisplayServerResult* result) { @@ -396,15 +364,6 @@ static const char* getFromProcesses(FFDisplayServerResult* result) void ffdsDetectWMDE(FFDisplayServerResult* result) { - //If all connections failed, use the environment variables to detect protocol name - if(result->wmProtocolName.length == 0) - getWMProtocolNameFromEnv(result); - - //We don't want to detect anything in TTY - //This can't happen if a connection succeeded, so we don't need to clear wmProcessName - if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY) == 0) - return; - const char* env = parseEnv(); if(result->wmProcessName.length > 0) From 873285b08348502f53e2b100cd9a901c8ce2b26a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 26 Jul 2024 23:52:39 +0800 Subject: [PATCH 03/67] TerminalShell: improve SSH detection --- src/detection/terminalshell/terminalshell_linux.c | 4 ++-- src/detection/terminalshell/terminalshell_windows.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 61c05a82bb..3a5449258e 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -42,7 +42,6 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) ffStrbufEqualS(&result->processName, "sudo") || ffStrbufEqualS(&result->processName, "su") || ffStrbufEqualS(&result->processName, "strace") || - ffStrbufEqualS(&result->processName, "sshd") || ffStrbufEqualS(&result->processName, "gdb") || ffStrbufEqualS(&result->processName, "lldb") || ffStrbufEqualS(&result->processName, "lldb-mi") || @@ -102,7 +101,6 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) ffStrbufEqualS(&result->processName, "oil.ovm") || ffStrbufEqualS(&result->processName, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case ffStrbufEqualS(&result->processName, "login") || - ffStrbufEqualS(&result->processName, "sshd") || ffStrbufEqualS(&result->processName, "clifm") || // https://github.com/leo-arch/clifm/issues/289 ffStrbufEqualS(&result->processName, "chezmoi") || // #762 #ifdef __linux__ @@ -314,6 +312,8 @@ static void setTerminalInfoDetails(FFTerminalResult* result) ffStrbufInitStatic(&result->prettyName, "tmux"); else if(ffStrbufStartsWithS(&result->processName, "screen-")) ffStrbufInitStatic(&result->prettyName, "screen"); + else if(ffStrbufEqualS(&result->processName, "sshd") || ffStrbufStartsWithS(&result->processName, "sshd-")) + ffStrbufInitCopy(&result->prettyName, &result->tty); #if defined(__ANDROID__) diff --git a/src/detection/terminalshell/terminalshell_windows.c b/src/detection/terminalshell/terminalshell_windows.c index 4f8e02f572..f429ae81da 100644 --- a/src/detection/terminalshell/terminalshell_windows.c +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -53,7 +53,6 @@ static uint32_t getShellInfo(FFShellResult* result, uint32_t pid) if( ffStrbufIgnCaseEqualS(&result->prettyName, "sudo") || ffStrbufIgnCaseEqualS(&result->prettyName, "su") || - ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || ffStrbufIgnCaseEqualS(&result->prettyName, "gdb") || ffStrbufIgnCaseEqualS(&result->prettyName, "lldb") || ffStrbufIgnCaseEqualS(&result->prettyName, "python") || // python on windows generates shim executables @@ -155,7 +154,7 @@ static bool getTerminalFromEnv(FFTerminalResult* result) } //SSH - if(getenv("SSH_CONNECTION") != NULL) + if(getenv("SSH_TTY") != NULL) term = getenv("SSH_TTY"); //Windows Terminal @@ -315,6 +314,11 @@ static void setTerminalInfoDetails(FFTerminalResult* result) ffStrbufSetStatic(&result->prettyName, "Windows Explorer"); else if(ffStrbufEqualS(&result->prettyName, "wezterm-gui")) ffStrbufSetStatic(&result->prettyName, "WezTerm"); + else if(ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || ffStrbufStartsWithIgnCaseS(&result->prettyName, "sshd-")) + { + const char* tty = getenv("SSH_TTY"); + if (tty) ffStrbufSetS(tty); + } } bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version); From 16dd9fb2137c01dcea614a3815110c6354dab09c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 27 Jul 2024 18:52:17 +0800 Subject: [PATCH 04/67] Terminal (Windows): fix build --- src/detection/terminalshell/terminalshell_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell_windows.c b/src/detection/terminalshell/terminalshell_windows.c index f429ae81da..f1e27d63e2 100644 --- a/src/detection/terminalshell/terminalshell_windows.c +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -317,7 +317,7 @@ static void setTerminalInfoDetails(FFTerminalResult* result) else if(ffStrbufIgnCaseEqualS(&result->prettyName, "sshd") || ffStrbufStartsWithIgnCaseS(&result->prettyName, "sshd-")) { const char* tty = getenv("SSH_TTY"); - if (tty) ffStrbufSetS(tty); + if (tty) ffStrbufSetS(&result->prettyName, tty); } } From 2cc94ee095134be7eeed5528a2e175f589371e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 27 Jul 2024 19:53:25 +0800 Subject: [PATCH 05/67] DisplayServer (Linux): fix build with no wayland support --- src/detection/displayserver/linux/wayland/wayland.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 603d373aff..3fc59362ae 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -133,7 +133,6 @@ uint32_t ffWaylandHandleRotation(WaylandDisplay* display) } return rotation; } -#endif const char* ffdsConnectWayland(FFDisplayServerResult* result) { @@ -261,3 +260,12 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND); return NULL; } + +#else + +const char* ffdsConnectWayland(FF_MAYBE_UNUSED FFDisplayServerResult* result) +{ + return "Fastfetch was compiled without Wayland support"; +} + +#endif From ce648e9e44ca82ceacd979e73a816b4ea64f8a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 27 Jul 2024 23:53:17 +0800 Subject: [PATCH 06/67] Bluetooth (Windows): tidy; update module description --- src/detection/bluetooth/bluetooth_windows.c | 29 +++++++++------------ src/modules/bluetooth/bluetooth.c | 6 ++--- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c index cf0c756b90..2ac377d01b 100644 --- a/src/detection/bluetooth/bluetooth_windows.c +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -15,18 +15,16 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextDevice) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindDeviceClose) - BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { + BLUETOOTH_DEVICE_INFO btdi = { + .dwSize = sizeof(btdi) + }; + HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) { .fReturnConnected = TRUE, .fReturnRemembered = TRUE, .fReturnAuthenticated = TRUE, .fReturnUnknown = TRUE, - .dwSize = sizeof(btsp) - }; - - BLUETOOTH_DEVICE_INFO btdi = { - .dwSize = sizeof(btdi) - }; - HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&btsp, &btdi); + .dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS) + }, &btdi); if(!hFind) { if (GetLastError() == ERROR_NO_MORE_ITEMS) @@ -37,21 +35,18 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) do { FFBluetoothResult* device = ffListAdd(devices); - ffStrbufInit(&device->name); - ffStrbufInit(&device->address); - ffStrbufInit(&device->type); - device->battery = 0; - device->connected = !!btdi.fConnected; - - ffStrbufSetWS(&device->name, btdi.szName); - - ffStrbufAppendF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x", + ffStrbufInitWS(&device->name, btdi.szName); + ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x", btdi.Address.rgBytes[0], btdi.Address.rgBytes[1], btdi.Address.rgBytes[2], btdi.Address.rgBytes[3], btdi.Address.rgBytes[4], btdi.Address.rgBytes[5]); + ffStrbufInit(&device->type); + device->battery = 0; + device->connected = !!btdi.fConnected; + //https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf if(BitTest(&btdi.ulClassofDevice, 13)) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index fa010ec9bb..037ca6335e 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -178,8 +178,8 @@ void ffGenerateBluetoothJsonResult(FF_MAYBE_UNUSED FFBluetoothOptions* options, void ffPrintBluetoothHelpFormat(void) { FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTH_MODULE_NAME, "{1} ({4})", FF_BLUETOOTH_NUM_FORMAT_ARGS, ((const char* []) { - "Name - name", - "Address - address", + "Name - device name", + "Address - remote device address", "Type - type", "Battery percentage number - battery-percentage", "Is connected - connected", @@ -192,7 +192,7 @@ void ffInitBluetoothOptions(FFBluetoothOptions* options) ffOptionInitModuleBaseInfo( &options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, - "List bluetooth devices", + "List (connected) bluetooth devices", ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, From 8a3af14d2220e65fdd6114fb04dbb78b7ae0b0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Jul 2024 00:05:07 +0800 Subject: [PATCH 07/67] BluetoothRadio (Windows): new module --- CMakeLists.txt | 7 + doc/json_schema.json | 32 ++- presets/all.jsonc | 1 + presets/ci.jsonc | 1 + src/common/modules.c | 1 + src/detection/bluetoothradio/bluetoothradio.h | 17 ++ .../bluetoothradio/bluetoothradio_nosupport.c | 6 + .../bluetoothradio/bluetoothradio_windows.c | 157 ++++++++++++++ src/modules/bluetoothradio/bluetoothradio.c | 198 ++++++++++++++++++ src/modules/bluetoothradio/bluetoothradio.h | 9 + src/modules/bluetoothradio/option.h | 12 ++ src/modules/modules.h | 1 + src/modules/options.h | 1 + src/options/modules.c | 2 + src/options/modules.h | 1 + 15 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 src/detection/bluetoothradio/bluetoothradio.h create mode 100644 src/detection/bluetoothradio/bluetoothradio_nosupport.c create mode 100644 src/detection/bluetoothradio/bluetoothradio_windows.c create mode 100644 src/modules/bluetoothradio/bluetoothradio.c create mode 100644 src/modules/bluetoothradio/bluetoothradio.h create mode 100644 src/modules/bluetoothradio/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ebd32ab292..8e9e91fce8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,7 @@ set(LIBFASTFETCH_SRC src/modules/battery/battery.c src/modules/bios/bios.c src/modules/bluetooth/bluetooth.c + src/modules/bluetoothradio/bluetoothradio.c src/modules/board/board.c src/modules/bootmgr/bootmgr.c src/modules/brightness/brightness.c @@ -421,6 +422,7 @@ if(LINUX) src/detection/cpuusage/cpuusage_linux.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_linux.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/disk/disk_linux.c src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_linux.c @@ -488,6 +490,7 @@ elseif(ANDROID) src/detection/battery/battery_android.c src/detection/bios/bios_android.c src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/board/board_android.c src/detection/bootmgr/bootmgr_nosupport.c src/detection/brightness/brightness_nosupport.c @@ -550,6 +553,7 @@ elseif(BSD) src/detection/battery/battery_bsd.c src/detection/bios/bios_bsd.c src/detection/bluetooth/bluetooth_linux.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/board/board_bsd.c src/detection/bootmgr/bootmgr_bsd.c src/detection/brightness/brightness_bsd.c @@ -626,6 +630,7 @@ elseif(APPLE) src/detection/battery/battery_apple.c src/detection/bios/bios_apple.c src/detection/bluetooth/bluetooth_apple.m + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/board/board_apple.c src/detection/bootmgr/bootmgr_apple.c src/detection/brightness/brightness_apple.c @@ -689,6 +694,7 @@ elseif(WIN32) src/detection/battery/battery_windows.c src/detection/bios/bios_windows.c src/detection/bluetooth/bluetooth_windows.c + src/detection/bluetoothradio/bluetoothradio_windows.c src/detection/board/board_windows.c src/detection/bootmgr/bootmgr_windows.c src/detection/brightness/brightness_windows.cpp @@ -763,6 +769,7 @@ elseif(SunOS) src/detection/cpuusage/cpuusage_sunos.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c src/detection/disk/disk_sunos.c src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_nosupport.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 0d8773b93d..4af7a84df5 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -745,6 +745,7 @@ "battery", "bios", "bluetooth", + "bluetoothradio", "board", "bootmgr", "break", @@ -1049,7 +1050,7 @@ "additionalProperties": false, "properties": { "type": { - "description": "List bluetooth devices", + "description": "List (connected) bluetooth devices", "const": "bluetooth" }, "showDisconnected": { @@ -1080,6 +1081,35 @@ } } }, + { + "title": "Bluetooth Radio", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "description": "List bluetooth radios width supported version and vendor", + "const": "bluetoothradio" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyIcon": { + "$ref": "#/$defs/keyIcon" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "format": { + "$ref": "#/$defs/format" + } + } + }, { "title": "Brightness", "type": "object", diff --git a/presets/all.jsonc b/presets/all.jsonc index 52d092d1c7..e19041c208 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -73,6 +73,7 @@ "opencl", "users", "bluetooth", + "bluetoothradio", "sound", "camera", "gamepad", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index ac34edab2b..2f3512ce24 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -75,6 +75,7 @@ "opencl", "users", "bluetooth", + "bluetoothradio", "sound", "camera", "gamepad", diff --git a/src/common/modules.c b/src/common/modules.c index d7607aa3a1..3cd1589849 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -8,6 +8,7 @@ static FFModuleBaseInfo* B[] = { (void*) &instance.config.modules.battery, (void*) &instance.config.modules.bios, (void*) &instance.config.modules.bluetooth, + (void*) &instance.config.modules.bluetoothRadio, (void*) &instance.config.modules.board, (void*) &instance.config.modules.bootmgr, (void*) &instance.config.modules.break_, diff --git a/src/detection/bluetoothradio/bluetoothradio.h b/src/detection/bluetoothradio/bluetoothradio.h new file mode 100644 index 0000000000..8aa911cb04 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio.h @@ -0,0 +1,17 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFBluetoothRadioResult +{ + FFstrbuf name; + FFstrbuf address; + uint8_t lmpVersion; + uint8_t hciVersion; + uint16_t lmpSubversion; + uint16_t hciRevision; + const char* vendor; + bool leSupported; +} FFBluetoothRadioResult; + +const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */); diff --git a/src/detection/bluetoothradio/bluetoothradio_nosupport.c b/src/detection/bluetoothradio/bluetoothradio_nosupport.c new file mode 100644 index 0000000000..1df1ce0e30 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_nosupport.c @@ -0,0 +1,6 @@ +#include "bluetoothradio.h" + +const char* ffDetectBluetoothRadio(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothRadioResult */) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c new file mode 100644 index 0000000000..330409608b --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -0,0 +1,157 @@ +#include "bluetoothradio.h" +#include "common/library.h" +#include "common/io/io.h" +#include "util/windows/unicode.h" + +#include +#include +#include + +// #include + +#define BTH_IOCTL_BASE 0 +#define BTH_CTL(id) CTL_CODE(FILE_DEVICE_BLUETOOTH, (id), METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_BTH_GET_LOCAL_INFO BTH_CTL(BTH_IOCTL_BASE+0x00) +#define LMP_LE_SUPPORTED(x) ((x >> 38) & 1) + +typedef struct _BTH_RADIO_INFO +{ + // Supported LMP features of the radio. Use LMP_XXX() to extract + // the desired bits. + ULONGLONG lmpSupportedFeatures; + + // Manufacturer ID (possibly BTH_MFG_XXX) + USHORT mfg; + + // LMP subversion + USHORT lmpSubversion; + + // LMP version + UCHAR lmpVersion; +} __attribute__((__packed__)) BTH_RADIO_INFO; + +typedef struct _BTH_LOCAL_RADIO_INFO +{ + // Local BTH_ADDR, class of defice, and radio name + BTH_DEVICE_INFO localInfo; + + // Combo of LOCAL_RADIO_XXX values + ULONG flags; + + // HCI revision, see core spec + USHORT hciRevision; + + // HCI version, see core spec + UCHAR hciVersion; + + // More information about the local radio (LMP, MFG) + BTH_RADIO_INFO radioInfo; +} __attribute__((__packed__)) BTH_LOCAL_RADIO_INFO; +static_assert(sizeof(BTH_LOCAL_RADIO_INFO) == 292, "BTH_LOCAL_RADIO_INFO should be 292 bytes"); + +#pragma GCC diagnostic ignored "-Wpointer-sign" + +const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) +{ + // Actually bluetoothapis.dll, but it's missing on Windows 7 + FF_LIBRARY_LOAD(bluetoothapis, NULL, "dlopen bthprops.cpl failed", "bthprops.cpl", 1) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose) + + HANDLE hRadio = NULL; + HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstRadio(&(BLUETOOTH_FIND_RADIO_PARAMS) { + .dwSize = sizeof(BLUETOOTH_FIND_RADIO_PARAMS) + }, &hRadio); + if(!hFind) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + return "No Bluetooth radios found"; + else + return "BluetoothFindFirstRadio() failed"; + } + + do { + BTH_LOCAL_RADIO_INFO blri; + DWORD returned; + if (!DeviceIoControl(hRadio, IOCTL_BTH_GET_LOCAL_INFO, NULL, 0, &blri, sizeof(blri), &returned, NULL)) + continue; + + FFBluetoothRadioResult* device = ffListAdd(devices); + ffStrbufInitS(&device->name, blri.localInfo.name); + + BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address }; + ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x", + addr.rgBytes[0], + addr.rgBytes[1], + addr.rgBytes[2], + addr.rgBytes[3], + addr.rgBytes[4], + addr.rgBytes[5]); + + device->lmpVersion = blri.radioInfo.lmpVersion; + device->lmpSubversion = blri.radioInfo.lmpSubversion; + device->hciVersion = blri.hciVersion; + device->hciRevision = blri.hciRevision; + device->leSupported = LMP_LE_SUPPORTED(blri.radioInfo.lmpSupportedFeatures); + + switch (blri.radioInfo.mfg) + { + case BTH_MFG_ERICSSON: device->vendor = "Ericsson"; break; + case BTH_MFG_NOKIA: device->vendor = "Nokia"; break; + case BTH_MFG_INTEL: device->vendor = "Intel"; break; + case BTH_MFG_IBM: device->vendor = "IBM"; break; + case BTH_MFG_TOSHIBA: device->vendor = "Toshiba"; break; + case BTH_MFG_3COM: device->vendor = "3Com"; break; + case BTH_MFG_MICROSOFT: device->vendor = "Microsoft"; break; + case BTH_MFG_LUCENT: device->vendor = "Lucent"; break; + case BTH_MFG_MOTOROLA: device->vendor = "Motorola"; break; + case BTH_MFG_INFINEON: device->vendor = "Infineon"; break; + case BTH_MFG_CSR: device->vendor = "CSR"; break; + case BTH_MFG_SILICONWAVE: device->vendor = "Silicon-Wave"; break; + case BTH_MFG_DIGIANSWER: device->vendor = "Digi-Answer"; break; + case BTH_MFG_TI: device->vendor = "Ti"; break; + case BTH_MFG_PARTHUS: device->vendor = "Parthus"; break; + case BTH_MFG_BROADCOM: device->vendor = "Broadcom"; break; + case BTH_MFG_MITEL: device->vendor = "Mitel"; break; + case BTH_MFG_WIDCOMM: device->vendor = "Widcomm"; break; + case BTH_MFG_ZEEVO: device->vendor = "Zeevo"; break; + case BTH_MFG_ATMEL: device->vendor = "Atmel"; break; + case BTH_MFG_MITSIBUSHI: device->vendor = "Mitsubishi"; break; + case BTH_MFG_RTX_TELECOM: device->vendor = "RTX Telecom"; break; + case BTH_MFG_KC_TECHNOLOGY: device->vendor = "KC Technology"; break; + case BTH_MFG_NEWLOGIC: device->vendor = "Newlogic"; break; + case BTH_MFG_TRANSILICA: device->vendor = "Transilica"; break; + case BTH_MFG_ROHDE_SCHWARZ: device->vendor = "Rohde-Schwarz"; break; + case BTH_MFG_TTPCOM: device->vendor = "TTPCom"; break; + case BTH_MFG_SIGNIA: device->vendor = "Signia"; break; + case BTH_MFG_CONEXANT: device->vendor = "Conexant"; break; + case BTH_MFG_QUALCOMM: device->vendor = "Qualcomm"; break; + case BTH_MFG_INVENTEL: device->vendor = "Inventel"; break; + case BTH_MFG_AVM_BERLIN: device->vendor = "AVM Berlin"; break; + case BTH_MFG_BANDSPEED: device->vendor = "Bandspeed"; break; + case BTH_MFG_MANSELLA: device->vendor = "Mansella"; break; + case BTH_MFG_NEC: device->vendor = "NEC"; break; + case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: device->vendor = "Waveplus"; break; + case BTH_MFG_ALCATEL: device->vendor = "Alcatel"; break; + case BTH_MFG_PHILIPS_SEMICONDUCTOR: device->vendor = "Philips Semiconductors"; break; + case BTH_MFG_C_TECHNOLOGIES: device->vendor = "C Technologies"; break; + case BTH_MFG_OPEN_INTERFACE: device->vendor = "Open Interface"; break; + case BTH_MFG_RF_MICRO_DEVICES: device->vendor = "RF Micro Devices"; break; + case BTH_MFG_HITACHI: device->vendor = "Hitachi"; break; + case BTH_MFG_SYMBOL_TECHNOLOGIES: device->vendor = "Symbol Technologies"; break; + case BTH_MFG_TENOVIS: device->vendor = "Tenovis"; break; + case BTH_MFG_MACRONIX_INTERNATIONAL: device->vendor = "Macronix International"; break; + case BTH_MFG_MARVELL: device->vendor = "Marvell"; break; + case BTH_MFG_APPLE: device->vendor = "Apple"; break; + case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: device->vendor = "Nordic Semiconductor ASA"; break; + case BTH_MFG_ARUBA_NETWORKS: device->vendor = "Aruba Networks"; break; + case BTH_MFG_INTERNAL_USE: device->vendor = "Internal Use"; break; + default: device->vendor = "Unknown"; break; + } + } while (ffBluetoothFindNextRadio(hFind, &hRadio)); + + ffBluetoothFindRadioClose(hFind); + + return NULL; +} diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c new file mode 100644 index 0000000000..f85832b099 --- /dev/null +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -0,0 +1,198 @@ +#include "common/percent.h" +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/bluetoothradio/bluetoothradio.h" +#include "modules/bluetoothradio/bluetoothradio.h" +#include "util/stringUtils.h" + +#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 7 +#define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio" + +static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) +{ + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + if (options->moduleArgs.key.length == 0) + { + ffStrbufAppendF(&key, "%s (%s)", FF_BLUETOOTHRADIO_DISPLAY_NAME, radio->name.chars); + } + else + { + FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index, "index"}, + {FF_FORMAT_ARG_TYPE_STRING, radio->name.chars, "name"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &options->moduleArgs.keyIcon, "icon"}, + })); + } + + const char* version = NULL; + + switch (radio->lmpVersion) + { + case 0: version = "1.0b"; break; + case 1: version = "1.1"; break; + case 2: version = "1.2"; break; + case 3: version = "2.0 + EDR"; break; + case 4: version = "2.1 + EDR"; break; + case 5: version = "3.0 + HS"; break; + case 6: version = "4.0"; break; + case 7: version = "4.1"; break; + case 8: version = "4.2"; break; + case 9: version = "5.0"; break; + case 10: version = "5.1"; break; + case 11: version = "5.2"; break; + case 12: version = "5.3"; break; + case 13: version = "5.4"; break; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + + if (version) + printf("Bluetooth %s (%s)\n", version, radio->vendor); + else + fputs(radio->vendor, stdout); + } + else + { + FF_STRBUF_AUTO_DESTROY lmpVersion = ffStrbufCreateF("%u.%u", radio->lmpVersion, radio->lmpSubversion); + FF_STRBUF_AUTO_DESTROY hciVersion = ffStrbufCreateF("%u.%u", radio->hciVersion, radio->hciRevision); + + FF_PRINT_FORMAT_CHECKED(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &radio->name, "name"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &radio->address, "address"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &lmpVersion, "lmp-version"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &hciVersion, "hci-version"}, + {FF_FORMAT_ARG_TYPE_STRING, version, "version"}, + {FF_FORMAT_ARG_TYPE_STRING, radio->vendor, "vendor"}, + {FF_FORMAT_ARG_TYPE_BOOL, &radio->leSupported, "le-supported"}, + })); + } +} + +void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) +{ + FF_LIST_AUTO_DESTROY radios = ffListCreate(sizeof (FFBluetoothRadioResult)); + const char* error = ffDetectBluetoothRadio(&radios); + + if(error) + { + ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + } + else + { + for(uint32_t i = 0; i < radios.length; i++) + { + uint8_t index = (uint8_t) (radios.length == 1 ? 0 : i + 1); + printDevice(options, FF_LIST_GET(FFBluetoothRadioResult, radios, i), index); + } + } + + FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, radios) + { + ffStrbufDestroy(&radio->name); + ffStrbufDestroy(&radio->address); + } +} + +bool ffParseBluetoothRadioCommandOptions(FFBluetoothRadioOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_BLUETOOTHRADIO_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateBluetoothRadioJsonConfig(FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyBluetoothRadioOptions))) FFBluetoothRadioOptions defaultOptions; + ffInitBluetoothRadioOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothRadioResult)); + + const char* error = ffDetectBluetoothRadio(&results); + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + + FF_LIST_FOR_EACH(FFBluetoothRadioResult, item, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address); + yyjson_mut_obj_add_uint(doc, obj, "lmpVersion", item->lmpVersion); + yyjson_mut_obj_add_uint(doc, obj, "lmpSubversion", item->lmpSubversion); + yyjson_mut_obj_add_uint(doc, obj, "hciVersion", item->hciVersion); + yyjson_mut_obj_add_uint(doc, obj, "hciRevision", item->hciRevision); + yyjson_mut_obj_add_str(doc, obj, "vendor", item->vendor); + yyjson_mut_obj_add_bool(doc, obj, "leSupported", item->leSupported); + } + + FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, results) + { + ffStrbufDestroy(&radio->name); + ffStrbufDestroy(&radio->address); + } +} + +void ffPrintBluetoothRadioHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTHRADIO_MODULE_NAME, "{1} ({4})", FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((const char* []) { + "Radio name for discovering - name", + "Address - local radio address", + "LMP version - lmp-version", + "HCI version - hci-version", + "Bluetooth version - version", + "Vendor - vendor", + "Is Bluetooth Low Energy (LE) supported - le-supported" + })); +} + +void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_BLUETOOTHRADIO_MODULE_NAME, + "List bluetooth radios width supported version and vendor", + ffParseBluetoothRadioCommandOptions, + ffParseBluetoothRadioJsonObject, + ffPrintBluetoothRadio, + ffGenerateBluetoothRadioJsonResult, + ffPrintBluetoothRadioHelpFormat, + ffGenerateBluetoothRadioJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰐻"); +} + +void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/bluetoothradio/bluetoothradio.h b/src/modules/bluetoothradio/bluetoothradio.h new file mode 100644 index 0000000000..ee9ef11959 --- /dev/null +++ b/src/modules/bluetoothradio/bluetoothradio.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio" + +void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options); +void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options); +void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options); diff --git a/src/modules/bluetoothradio/option.h b/src/modules/bluetoothradio/option.h new file mode 100644 index 0000000000..714200d3e8 --- /dev/null +++ b/src/modules/bluetoothradio/option.h @@ -0,0 +1,12 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" +#include "common/percent.h" + +typedef struct FFBluetoothRadioOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFBluetoothRadioOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 58ce1b98d4..dbfebcf319 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -5,6 +5,7 @@ #include "modules/battery/battery.h" #include "modules/bios/bios.h" #include "modules/bluetooth/bluetooth.h" +#include "modules/bluetoothradio/bluetoothradio.h" #include "modules/brightness/brightness.h" #include "modules/board/board.h" #include "modules/bootmgr/bootmgr.h" diff --git a/src/modules/options.h b/src/modules/options.h index 49bd8fe6b5..c705c75005 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -5,6 +5,7 @@ #include "modules/battery/option.h" #include "modules/bios/option.h" #include "modules/bluetooth/option.h" +#include "modules/bluetoothradio/option.h" #include "modules/board/option.h" #include "modules/bootmgr/option.h" #include "modules/break/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index 7d80b2d868..0bc117e3eb 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -6,6 +6,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitBatteryOptions(&options->battery); ffInitBiosOptions(&options->bios); ffInitBluetoothOptions(&options->bluetooth); + ffInitBluetoothRadioOptions(&options->bluetoothRadio); ffInitBoardOptions(&options->board); ffInitBootmgrOptions(&options->bootmgr); ffInitBreakOptions(&options->break_); @@ -77,6 +78,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyBatteryOptions(&options->battery); ffDestroyBiosOptions(&options->bios); ffDestroyBluetoothOptions(&options->bluetooth); + ffDestroyBluetoothRadioOptions(&options->bluetoothRadio); ffDestroyBoardOptions(&options->board); ffDestroyBootmgrOptions(&options->bootmgr); ffDestroyBreakOptions(&options->break_); diff --git a/src/options/modules.h b/src/options/modules.h index fdfae5e47a..1768c8c181 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -7,6 +7,7 @@ typedef struct FFOptionsModules FFBatteryOptions battery; FFBiosOptions bios; FFBluetoothOptions bluetooth; + FFBluetoothRadioOptions bluetoothRadio; FFBoardOptions board; FFBootmgrOptions bootmgr; FFBreakOptions break_; From a102f0505c6ccf5522da03af0ce389b3eb6a91f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Jul 2024 00:16:30 +0800 Subject: [PATCH 08/67] CI: silence spell checks --- .codespellrc | 2 +- src/detection/bluetoothradio/bluetoothradio_windows.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.codespellrc b/.codespellrc index 0dce5c4692..7de7af981c 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,Conexant diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c index 330409608b..eeca45c80e 100644 --- a/src/detection/bluetoothradio/bluetoothradio_windows.c +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -32,7 +32,7 @@ typedef struct _BTH_RADIO_INFO typedef struct _BTH_LOCAL_RADIO_INFO { - // Local BTH_ADDR, class of defice, and radio name + // Local BTH_ADDR, class of device, and radio name BTH_DEVICE_INFO localInfo; // Combo of LOCAL_RADIO_XXX values From db1fbe0a300e018b37f9142f448f088aeec6a7cd Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 28 Jul 2024 10:54:26 +0800 Subject: [PATCH 09/67] DBus: rename ffDBusGetValue to ffDBusGetString; add ffDBusGetUint16 --- src/common/dbus.c | 26 +++++++++++++++++++---- src/common/dbus.h | 3 ++- src/detection/bluetooth/bluetooth_linux.c | 6 +++--- src/detection/media/media_linux.c | 8 +++---- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/common/dbus.c b/src/common/dbus.c index f5b40aee2a..1715a50887 100644 --- a/src/common/dbus.c +++ b/src/common/dbus.c @@ -56,7 +56,7 @@ const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data) return NULL; } -bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) +bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) { int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); @@ -79,7 +79,7 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); if(argType == DBUS_TYPE_VARIANT) - return ffDBusGetValue(dbus, &subIter, result); + return ffDBusGetString(dbus, &subIter, result); //At this point we have an array @@ -87,7 +87,7 @@ bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) while(true) { - if(ffDBusGetValue(dbus, &subIter, result)) + if(ffDBusGetString(dbus, &subIter, result)) { foundAValue = true; ffStrbufAppendS(result, ", "); @@ -140,6 +140,24 @@ bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result) return ffDBusGetByte(dbus, &subIter, result); } +bool ffDBusGetUint16(FFDBusData* dbus, DBusMessageIter* iter, uint16_t* result) +{ + int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); + + if(argType == DBUS_TYPE_UINT16) + { + dbus->lib->ffdbus_message_iter_get_basic(iter, result); + return true; + } + + if(argType != DBUS_TYPE_VARIANT) + return false; + + DBusMessageIter subIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); + return ffDBusGetUint16(dbus, &subIter, result); +} + DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method) { DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method); @@ -194,7 +212,7 @@ bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* return false; } - bool ret = ffDBusGetValue(dbus, &rootIterator, result); + bool ret = ffDBusGetString(dbus, &rootIterator, result); dbus->lib->ffdbus_message_unref(reply); diff --git a/src/common/dbus.h b/src/common/dbus.h index a327884d44..bf6a5cc980 100644 --- a/src/common/dbus.h +++ b/src/common/dbus.h @@ -43,9 +43,10 @@ typedef struct FFDBusData } FFDBusData; const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success -bool ffDBusGetValue(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result); +bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result); bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result); bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result); +bool ffDBusGetUint16(FFDBusData* dbus, DBusMessageIter* iter, uint16_t* result); DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method); DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property); bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result); diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index 1ed712c90a..0ac664d7a3 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -61,11 +61,11 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue dbus->lib->ffdbus_message_iter_next(&dictIter); if(ffStrEquals(deviceProperty, "Address")) - ffDBusGetValue(dbus, &dictIter, &device->address); + ffDBusGetString(dbus, &dictIter, &device->address); else if(ffStrEquals(deviceProperty, "Name")) - ffDBusGetValue(dbus, &dictIter, &device->name); + ffDBusGetString(dbus, &dictIter, &device->name); else if(ffStrEquals(deviceProperty, "Icon")) - ffDBusGetValue(dbus, &dictIter, &device->type); + ffDBusGetString(dbus, &dictIter, &device->type); else if(ffStrEquals(deviceProperty, "Percentage")) ffDBusGetByte(dbus, &dictIter, &device->battery); else if(ffStrEquals(deviceProperty, "Connected")) diff --git a/src/detection/media/media_linux.c b/src/detection/media/media_linux.c index 5dd673338d..7d40927d7c 100644 --- a/src/detection/media/media_linux.c +++ b/src/detection/media/media_linux.c @@ -61,13 +61,13 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul data->lib->ffdbus_message_iter_next(&dictIterator); if(ffStrEquals(key, "xesam:title")) - ffDBusGetValue(data, &dictIterator, &result->song); + ffDBusGetString(data, &dictIterator, &result->song); else if(ffStrEquals(key, "xesam:album")) - ffDBusGetValue(data, &dictIterator, &result->album); + ffDBusGetString(data, &dictIterator, &result->album); else if(ffStrEquals(key, "xesam:artist")) - ffDBusGetValue(data, &dictIterator, &result->artist); + ffDBusGetString(data, &dictIterator, &result->artist); else if(ffStrEquals(key, "xesam:url")) - ffDBusGetValue(data, &dictIterator, &result->url); + ffDBusGetString(data, &dictIterator, &result->url); if(result->song.length > 0 && result->artist.length > 0 && result->album.length > 0 && result->url.length > 0) break; From 2c7cd6df986707b933bd02e705208797275abaa5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 28 Jul 2024 10:54:49 +0800 Subject: [PATCH 10/67] Bluetooth (Linux): more strict checks --- src/detection/bluetooth/bluetooth_linux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index 0ac664d7a3..ef66cfcc3a 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -86,8 +86,8 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB const char* propertyType; dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType); - if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL) - return; //We don't care about other properties + if(!ffStrContains(propertyType, ".Device") && !ffStrContains(propertyType, ".Battery")) + return; // We don't care about other properties dbus->lib->ffdbus_message_iter_next(&dictIter); @@ -118,8 +118,8 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage const char* objectPath; dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath); - //We don't want adapter objects - if(strstr(objectPath, "dev_") == NULL) + // We don't want adapter objects + if(!ffStrContains(objectPath, "/dev_")) return; dbus->lib->ffdbus_message_iter_next(&dictIter); From 96c58148f62470f176847892a021762b4ad757a4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 28 Jul 2024 10:55:07 +0800 Subject: [PATCH 11/67] BluetoothRadio (Linux): add support --- .codespellrc | 2 +- CMakeLists.txt | 5 +- src/detection/bluetoothradio/bluetoothradio.c | 112 ++++++++++ src/detection/bluetoothradio/bluetoothradio.h | 2 +- .../bluetoothradio/bluetoothradio_linux.c | 205 ++++++++++++++++++ .../bluetoothradio/bluetoothradio_windows.c | 57 +---- src/modules/bluetoothradio/bluetoothradio.c | 7 +- 7 files changed, 325 insertions(+), 65 deletions(-) create mode 100644 src/detection/bluetoothradio/bluetoothradio.c create mode 100644 src/detection/bluetoothradio/bluetoothradio_linux.c diff --git a/.codespellrc b/.codespellrc index 7de7af981c..087150a6d5 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,Conexant +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,conexant diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e9e91fce8..86e8f6f867 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,6 +294,7 @@ set(LIBFASTFETCH_SRC src/common/properties.c src/common/settings.c src/common/temps.c + src/detection/bluetoothradio/bluetoothradio.c src/detection/bootmgr/bootmgr.c src/detection/chassis/chassis.c src/detection/cpu/cpu.c @@ -422,7 +423,7 @@ if(LINUX) src/detection/cpuusage/cpuusage_linux.c src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_linux.c - src/detection/bluetoothradio/bluetoothradio_nosupport.c + src/detection/bluetoothradio/bluetoothradio_linux.c src/detection/disk/disk_linux.c src/detection/dns/dns_linux.c src/detection/physicaldisk/physicaldisk_linux.c @@ -553,7 +554,7 @@ elseif(BSD) src/detection/battery/battery_bsd.c src/detection/bios/bios_bsd.c src/detection/bluetooth/bluetooth_linux.c - src/detection/bluetoothradio/bluetoothradio_nosupport.c + src/detection/bluetoothradio/bluetoothradio_linux.c src/detection/board/board_bsd.c src/detection/bootmgr/bootmgr_bsd.c src/detection/brightness/brightness_bsd.c diff --git a/src/detection/bluetoothradio/bluetoothradio.c b/src/detection/bluetoothradio/bluetoothradio.c new file mode 100644 index 0000000000..90a5b54539 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio.c @@ -0,0 +1,112 @@ +#include "bluetoothradio.h" + +// https://github.com/ziglang/zig/blob/a84951465b409495095a9598db0cae745f34fa7b/lib/libc/include/any-windows-any/bthdef.h#L187-L236 + +#define BTH_MFG_ERICSSON 0 +#define BTH_MFG_NOKIA 1 +#define BTH_MFG_INTEL 2 +#define BTH_MFG_IBM 3 +#define BTH_MFG_TOSHIBA 4 +#define BTH_MFG_3COM 5 +#define BTH_MFG_MICROSOFT 6 +#define BTH_MFG_LUCENT 7 +#define BTH_MFG_MOTOROLA 8 +#define BTH_MFG_INFINEON 9 +#define BTH_MFG_CSR 10 +#define BTH_MFG_SILICONWAVE 11 +#define BTH_MFG_DIGIANSWER 12 +#define BTH_MFG_TI 13 +#define BTH_MFG_PARTHUS 14 +#define BTH_MFG_BROADCOM 15 +#define BTH_MFG_MITEL 16 +#define BTH_MFG_WIDCOMM 17 +#define BTH_MFG_ZEEVO 18 +#define BTH_MFG_ATMEL 19 +#define BTH_MFG_MITSIBUSHI 20 +#define BTH_MFG_RTX_TELECOM 21 +#define BTH_MFG_KC_TECHNOLOGY 22 +#define BTH_MFG_NEWLOGIC 23 +#define BTH_MFG_TRANSILICA 24 +#define BTH_MFG_ROHDE_SCHWARZ 25 +#define BTH_MFG_TTPCOM 26 +#define BTH_MFG_SIGNIA 27 +#define BTH_MFG_CONEXANT 28 +#define BTH_MFG_QUALCOMM 29 +#define BTH_MFG_INVENTEL 30 +#define BTH_MFG_AVM_BERLIN 31 +#define BTH_MFG_BANDSPEED 32 +#define BTH_MFG_MANSELLA 33 +#define BTH_MFG_NEC 34 +#define BTH_MFG_WAVEPLUS_TECHNOLOGY_CO 35 +#define BTH_MFG_ALCATEL 36 +#define BTH_MFG_PHILIPS_SEMICONDUCTOR 37 +#define BTH_MFG_C_TECHNOLOGIES 38 +#define BTH_MFG_OPEN_INTERFACE 39 +#define BTH_MFG_RF_MICRO_DEVICES 40 +#define BTH_MFG_HITACHI 41 +#define BTH_MFG_SYMBOL_TECHNOLOGIES 42 +#define BTH_MFG_TENOVIS 43 +#define BTH_MFG_MACRONIX_INTERNATIONAL 44 +#define BTH_MFG_MARVELL 72 +#define BTH_MFG_APPLE 76 +#define BTH_MFG_NORDIC_SEMICONDUCTORS_ASA 89 +#define BTH_MFG_ARUBA_NETWORKS 283 +#define BTH_MFG_INTERNAL_USE 65535 + +const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId) +{ + switch (manufacturerId) + { + case BTH_MFG_ERICSSON: return "Ericsson"; + case BTH_MFG_NOKIA: return "Nokia"; + case BTH_MFG_INTEL: return "Intel"; + case BTH_MFG_IBM: return "IBM"; + case BTH_MFG_TOSHIBA: return "Toshiba"; + case BTH_MFG_3COM: return "3Com"; + case BTH_MFG_MICROSOFT: return "Microsoft"; + case BTH_MFG_LUCENT: return "Lucent"; + case BTH_MFG_MOTOROLA: return "Motorola"; + case BTH_MFG_INFINEON: return "Infineon"; + case BTH_MFG_CSR: return "CSR"; + case BTH_MFG_SILICONWAVE: return "Silicon-Wave"; + case BTH_MFG_DIGIANSWER: return "Digi-Answer"; + case BTH_MFG_TI: return "Ti"; + case BTH_MFG_PARTHUS: return "Parthus"; + case BTH_MFG_BROADCOM: return "Broadcom"; + case BTH_MFG_MITEL: return "Mitel"; + case BTH_MFG_WIDCOMM: return "Widcomm"; + case BTH_MFG_ZEEVO: return "Zeevo"; + case BTH_MFG_ATMEL: return "Atmel"; + case BTH_MFG_MITSIBUSHI: return "Mitsubishi"; + case BTH_MFG_RTX_TELECOM: return "RTX Telecom"; + case BTH_MFG_KC_TECHNOLOGY: return "KC Technology"; + case BTH_MFG_NEWLOGIC: return "Newlogic"; + case BTH_MFG_TRANSILICA: return "Transilica"; + case BTH_MFG_ROHDE_SCHWARZ: return "Rohde-Schwarz"; + case BTH_MFG_TTPCOM: return "TTPCom"; + case BTH_MFG_SIGNIA: return "Signia"; + case BTH_MFG_CONEXANT: return "Conexant"; + case BTH_MFG_QUALCOMM: return "Qualcomm"; + case BTH_MFG_INVENTEL: return "Inventel"; + case BTH_MFG_AVM_BERLIN: return "AVM Berlin"; + case BTH_MFG_BANDSPEED: return "Bandspeed"; + case BTH_MFG_MANSELLA: return "Mansella"; + case BTH_MFG_NEC: return "NEC"; + case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: return "Waveplus"; + case BTH_MFG_ALCATEL: return "Alcatel"; + case BTH_MFG_PHILIPS_SEMICONDUCTOR: return "Philips Semiconductors"; + case BTH_MFG_C_TECHNOLOGIES: return "C Technologies"; + case BTH_MFG_OPEN_INTERFACE: return "Open Interface"; + case BTH_MFG_RF_MICRO_DEVICES: return "RF Micro Devices"; + case BTH_MFG_HITACHI: return "Hitachi"; + case BTH_MFG_SYMBOL_TECHNOLOGIES: return "Symbol Technologies"; + case BTH_MFG_TENOVIS: return "Tenovis"; + case BTH_MFG_MACRONIX_INTERNATIONAL: return "Macronix International"; + case BTH_MFG_MARVELL: return "Marvell"; + case BTH_MFG_APPLE: return "Apple"; + case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: return "Nordic Semiconductor ASA"; + case BTH_MFG_ARUBA_NETWORKS: return "Aruba Networks"; + case BTH_MFG_INTERNAL_USE: return "Internal Use"; + default: return "Unknown"; + } +} diff --git a/src/detection/bluetoothradio/bluetoothradio.h b/src/detection/bluetoothradio/bluetoothradio.h index 8aa911cb04..669f8bc5c3 100644 --- a/src/detection/bluetoothradio/bluetoothradio.h +++ b/src/detection/bluetoothradio/bluetoothradio.h @@ -11,7 +11,7 @@ typedef struct FFBluetoothRadioResult uint16_t lmpSubversion; uint16_t hciRevision; const char* vendor; - bool leSupported; } FFBluetoothRadioResult; const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */); +const char* ffBluetoothRadioGetVendor(uint32_t manufacturerId); diff --git a/src/detection/bluetoothradio/bluetoothradio_linux.c b/src/detection/bluetoothradio/bluetoothradio_linux.c new file mode 100644 index 0000000000..a0f44dda05 --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_linux.c @@ -0,0 +1,205 @@ +#include "bluetoothradio.h" +#include "util/stringUtils.h" + +#ifdef FF_HAVE_DBUS +#include "common/dbus.h" + +/* Example dbus reply, striped to only the relevant parts: +array [ //root + dict entry( + object path "/org/bluez/hci0" + array [ + dict entry( + string "org.bluez.Adapter1" + array [ + dict entry( + string "Address" + variant string "XX:XX:XX:XX:XX:XX" + ) + dict entry( + string "Name" + variant string "xxxxxxxx" + ) + dict entry( + string "Powered" + variant boolean true + ) + dict entry( + string "PowerState" + variant string "on" + ) + dict entry( + string "Manufacturer" + variant uint16 2 + ) + dict entry( + string "Version" + variant byte 12 + ) + ] + ) + ] + ) +] +*/ + +static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) + return; + + DBusMessageIter dictIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); + + // if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) + // return; + + const char* deviceProperty; + dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty); + + dbus->lib->ffdbus_message_iter_next(&dictIter); + + if(ffStrEquals(deviceProperty, "Address")) + ffDBusGetString(dbus, &dictIter, &device->address); + else if(ffStrEquals(deviceProperty, "Name")) + ffDBusGetString(dbus, &dictIter, &device->name); + else if(ffStrEquals(deviceProperty, "Manufacturer")) + { + uint16_t detection; + if (ffDBusGetUint16(dbus, &dictIter, &detection)) + device->vendor = ffBluetoothRadioGetVendor(detection); + } + else if(ffStrEquals(deviceProperty, "Version")) + ffDBusGetByte(dbus, &dictIter, &device->lmpVersion); +} + +static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) + return; + + DBusMessageIter dictIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) + return; + + const char* propertyType; + dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType); + + if(!ffStrContains(propertyType, ".Adapter")) + return; //We don't care about other properties + + dbus->lib->ffdbus_message_iter_next(&dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) + return; + + DBusMessageIter arrayIter; + dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); + + while(true) + { + detectBluetoothValue(dbus, &arrayIter, device); + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); + } +} + +static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) + return; + + DBusMessageIter dictIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH) + return; + + const char* objectPath; + dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath); + + //We want adapter objects + if(!ffStrStartsWith(objectPath, "/org/bluez/hci") || ffStrContains(objectPath, "/dev_")) + return; + + dbus->lib->ffdbus_message_iter_next(&dictIter); + + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY) + return; + + DBusMessageIter arrayIter; + dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); + + FFBluetoothRadioResult* device = ffListAdd(devices); + ffStrbufInit(&device->name); + ffStrbufInit(&device->address); + device->lmpVersion = 0; + device->hciVersion = 0; + device->lmpSubversion = 0; + device->hciRevision = 0; + device->vendor = "Unknown"; + + while(true) + { + detectBluetoothProperty(dbus, &arrayIter, device); + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); + } + + if(device->name.length == 0) + { + ffStrbufDestroy(&device->name); + ffStrbufDestroy(&device->address); + --devices->length; + } +} + +static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter) +{ + if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + DBusMessageIter arrayIter; + dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter); + + while(true) + { + detectBluetoothObject(devices, dbus, &arrayIter); + FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); + } +} + +static const char* detectBluetooth(FFlist* devices) +{ + FFDBusData dbus; + const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus); + if(error) + return error; + + DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + if(!managedObjects) + return "Failed to call GetManagedObjects"; + + DBusMessageIter rootIter; + if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter)) + { + dbus.lib->ffdbus_message_unref(managedObjects); + return "Failed to get root iterator of GetManagedObjects"; + } + + detectBluetoothRoot(devices, &dbus, &rootIter); + + dbus.lib->ffdbus_message_unref(managedObjects); + return NULL; +} + +#endif + +const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) +{ + #ifdef FF_HAVE_DBUS + return detectBluetooth(devices); + #else + return "Fastfetch was compiled without DBus support"; + #endif +} diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c index eeca45c80e..db1d86234f 100644 --- a/src/detection/bluetoothradio/bluetoothradio_windows.c +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -93,62 +93,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) device->lmpSubversion = blri.radioInfo.lmpSubversion; device->hciVersion = blri.hciVersion; device->hciRevision = blri.hciRevision; - device->leSupported = LMP_LE_SUPPORTED(blri.radioInfo.lmpSupportedFeatures); - - switch (blri.radioInfo.mfg) - { - case BTH_MFG_ERICSSON: device->vendor = "Ericsson"; break; - case BTH_MFG_NOKIA: device->vendor = "Nokia"; break; - case BTH_MFG_INTEL: device->vendor = "Intel"; break; - case BTH_MFG_IBM: device->vendor = "IBM"; break; - case BTH_MFG_TOSHIBA: device->vendor = "Toshiba"; break; - case BTH_MFG_3COM: device->vendor = "3Com"; break; - case BTH_MFG_MICROSOFT: device->vendor = "Microsoft"; break; - case BTH_MFG_LUCENT: device->vendor = "Lucent"; break; - case BTH_MFG_MOTOROLA: device->vendor = "Motorola"; break; - case BTH_MFG_INFINEON: device->vendor = "Infineon"; break; - case BTH_MFG_CSR: device->vendor = "CSR"; break; - case BTH_MFG_SILICONWAVE: device->vendor = "Silicon-Wave"; break; - case BTH_MFG_DIGIANSWER: device->vendor = "Digi-Answer"; break; - case BTH_MFG_TI: device->vendor = "Ti"; break; - case BTH_MFG_PARTHUS: device->vendor = "Parthus"; break; - case BTH_MFG_BROADCOM: device->vendor = "Broadcom"; break; - case BTH_MFG_MITEL: device->vendor = "Mitel"; break; - case BTH_MFG_WIDCOMM: device->vendor = "Widcomm"; break; - case BTH_MFG_ZEEVO: device->vendor = "Zeevo"; break; - case BTH_MFG_ATMEL: device->vendor = "Atmel"; break; - case BTH_MFG_MITSIBUSHI: device->vendor = "Mitsubishi"; break; - case BTH_MFG_RTX_TELECOM: device->vendor = "RTX Telecom"; break; - case BTH_MFG_KC_TECHNOLOGY: device->vendor = "KC Technology"; break; - case BTH_MFG_NEWLOGIC: device->vendor = "Newlogic"; break; - case BTH_MFG_TRANSILICA: device->vendor = "Transilica"; break; - case BTH_MFG_ROHDE_SCHWARZ: device->vendor = "Rohde-Schwarz"; break; - case BTH_MFG_TTPCOM: device->vendor = "TTPCom"; break; - case BTH_MFG_SIGNIA: device->vendor = "Signia"; break; - case BTH_MFG_CONEXANT: device->vendor = "Conexant"; break; - case BTH_MFG_QUALCOMM: device->vendor = "Qualcomm"; break; - case BTH_MFG_INVENTEL: device->vendor = "Inventel"; break; - case BTH_MFG_AVM_BERLIN: device->vendor = "AVM Berlin"; break; - case BTH_MFG_BANDSPEED: device->vendor = "Bandspeed"; break; - case BTH_MFG_MANSELLA: device->vendor = "Mansella"; break; - case BTH_MFG_NEC: device->vendor = "NEC"; break; - case BTH_MFG_WAVEPLUS_TECHNOLOGY_CO: device->vendor = "Waveplus"; break; - case BTH_MFG_ALCATEL: device->vendor = "Alcatel"; break; - case BTH_MFG_PHILIPS_SEMICONDUCTOR: device->vendor = "Philips Semiconductors"; break; - case BTH_MFG_C_TECHNOLOGIES: device->vendor = "C Technologies"; break; - case BTH_MFG_OPEN_INTERFACE: device->vendor = "Open Interface"; break; - case BTH_MFG_RF_MICRO_DEVICES: device->vendor = "RF Micro Devices"; break; - case BTH_MFG_HITACHI: device->vendor = "Hitachi"; break; - case BTH_MFG_SYMBOL_TECHNOLOGIES: device->vendor = "Symbol Technologies"; break; - case BTH_MFG_TENOVIS: device->vendor = "Tenovis"; break; - case BTH_MFG_MACRONIX_INTERNATIONAL: device->vendor = "Macronix International"; break; - case BTH_MFG_MARVELL: device->vendor = "Marvell"; break; - case BTH_MFG_APPLE: device->vendor = "Apple"; break; - case BTH_MFG_NORDIC_SEMICONDUCTORS_ASA: device->vendor = "Nordic Semiconductor ASA"; break; - case BTH_MFG_ARUBA_NETWORKS: device->vendor = "Aruba Networks"; break; - case BTH_MFG_INTERNAL_USE: device->vendor = "Internal Use"; break; - default: device->vendor = "Unknown"; break; - } + device->vendor = ffBluetoothRadioGetVendor(blri.radioInfo.mfg); } while (ffBluetoothFindNextRadio(hFind, &hRadio)); ffBluetoothFindRadioClose(hFind); diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index f85832b099..0d966647e7 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -5,7 +5,7 @@ #include "modules/bluetoothradio/bluetoothradio.h" #include "util/stringUtils.h" -#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 7 +#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 6 #define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio" static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) @@ -65,7 +65,6 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio {FF_FORMAT_ARG_TYPE_STRBUF, &hciVersion, "hci-version"}, {FF_FORMAT_ARG_TYPE_STRING, version, "version"}, {FF_FORMAT_ARG_TYPE_STRING, radio->vendor, "vendor"}, - {FF_FORMAT_ARG_TYPE_BOOL, &radio->leSupported, "le-supported"}, })); } } @@ -153,7 +152,6 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* yyjson_mut_obj_add_uint(doc, obj, "hciVersion", item->hciVersion); yyjson_mut_obj_add_uint(doc, obj, "hciRevision", item->hciRevision); yyjson_mut_obj_add_str(doc, obj, "vendor", item->vendor); - yyjson_mut_obj_add_bool(doc, obj, "leSupported", item->leSupported); } FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, results) @@ -165,14 +163,13 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* void ffPrintBluetoothRadioHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTHRADIO_MODULE_NAME, "{1} ({4})", FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BLUETOOTHRADIO_MODULE_NAME, "Bluetooth {5} ({6})", FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((const char* []) { "Radio name for discovering - name", "Address - local radio address", "LMP version - lmp-version", "HCI version - hci-version", "Bluetooth version - version", "Vendor - vendor", - "Is Bluetooth Low Energy (LE) supported - le-supported" })); } From 7a75615d9e0f790c5076bf6baf9067122c20ca3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 28 Jul 2024 13:06:29 +0800 Subject: [PATCH 12/67] BluetoothRadio (macOS): add dirty support --- CMakeLists.txt | 2 +- .../bluetoothradio/bluetoothradio_apple.m | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/detection/bluetoothradio/bluetoothradio_apple.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 86e8f6f867..3e6e859630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,7 +631,7 @@ elseif(APPLE) src/detection/battery/battery_apple.c src/detection/bios/bios_apple.c src/detection/bluetooth/bluetooth_apple.m - src/detection/bluetoothradio/bluetoothradio_nosupport.c + src/detection/bluetoothradio/bluetoothradio_apple.m src/detection/board/board_apple.c src/detection/bootmgr/bootmgr_apple.c src/detection/brightness/brightness_apple.c diff --git a/src/detection/bluetoothradio/bluetoothradio_apple.m b/src/detection/bluetoothradio/bluetoothradio_apple.m new file mode 100644 index 0000000000..c68e9eee1c --- /dev/null +++ b/src/detection/bluetoothradio/bluetoothradio_apple.m @@ -0,0 +1,26 @@ +#include "bluetoothradio.h" + +#import + +const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */) +{ + IOBluetoothHostController* ctrl = IOBluetoothHostController.defaultController; + if(!ctrl) + return "IOBluetoothHostController.defaultController failed"; + + FFBluetoothRadioResult* device = ffListAdd(devices); + ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String); + ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String); + device->lmpVersion = 0; + device->hciVersion = 0; + device->lmpSubversion = 0; + device->hciRevision = 0; + + #ifdef __aarch64__ + device->vendor = "Apple"; + #else + device->vendor = "Unknown"; // Hackintosh? + #endif + + return NULL; +} From c14ba32b82e39e5ea0db7c8c23dda87791d23ea4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 28 Jul 2024 15:26:37 +0800 Subject: [PATCH 13/67] BluetoothRadio: add more props; remove hciVersion; code cleanup --- src/detection/bluetooth/bluetooth_windows.c | 5 +- src/detection/bluetoothradio/bluetoothradio.h | 9 ++-- .../bluetoothradio/bluetoothradio_apple.m | 9 ++-- .../bluetoothradio/bluetoothradio_linux.c | 25 ++++++---- .../bluetoothradio/bluetoothradio_windows.c | 9 ++-- src/modules/bluetoothradio/bluetoothradio.c | 48 +++++++++++++------ 6 files changed, 68 insertions(+), 37 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c index 2ac377d01b..58322be190 100644 --- a/src/detection/bluetooth/bluetooth_windows.c +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -27,10 +27,7 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) }, &btdi); if(!hFind) { - if (GetLastError() == ERROR_NO_MORE_ITEMS) - return "No Bluetooth devices found"; - else - return "BluetoothFindFirstDevice() failed"; + return "BluetoothFindFirstDevice() failed"; } do { diff --git a/src/detection/bluetoothradio/bluetoothradio.h b/src/detection/bluetoothradio/bluetoothradio.h index 669f8bc5c3..ad68ca2fde 100644 --- a/src/detection/bluetoothradio/bluetoothradio.h +++ b/src/detection/bluetoothradio/bluetoothradio.h @@ -6,11 +6,12 @@ typedef struct FFBluetoothRadioResult { FFstrbuf name; FFstrbuf address; - uint8_t lmpVersion; - uint8_t hciVersion; - uint16_t lmpSubversion; - uint16_t hciRevision; + int32_t lmpVersion; + int32_t lmpSubversion; const char* vendor; + bool enabled; + bool discoverable; + bool connectable; } FFBluetoothRadioResult; const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */); diff --git a/src/detection/bluetoothradio/bluetoothradio_apple.m b/src/detection/bluetoothradio/bluetoothradio_apple.m index c68e9eee1c..77414a5f64 100644 --- a/src/detection/bluetoothradio/bluetoothradio_apple.m +++ b/src/detection/bluetoothradio/bluetoothradio_apple.m @@ -11,10 +11,11 @@ FFBluetoothRadioResult* device = ffListAdd(devices); ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String); ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String); - device->lmpVersion = 0; - device->hciVersion = 0; - device->lmpSubversion = 0; - device->hciRevision = 0; + device->lmpVersion = -1; + device->lmpSubversion = -1; + device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON; + device->discoverable = false; + device->connectable = true; #ifdef __aarch64__ device->vendor = "Apple"; diff --git a/src/detection/bluetoothradio/bluetoothradio_linux.c b/src/detection/bluetoothradio/bluetoothradio_linux.c index a0f44dda05..8a1ac01084 100644 --- a/src/detection/bluetoothradio/bluetoothradio_linux.c +++ b/src/detection/bluetoothradio/bluetoothradio_linux.c @@ -51,8 +51,8 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue DBusMessageIter dictIter; dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter); - // if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) - // return; + if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING) + return; const char* deviceProperty; dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty); @@ -61,7 +61,7 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue if(ffStrEquals(deviceProperty, "Address")) ffDBusGetString(dbus, &dictIter, &device->address); - else if(ffStrEquals(deviceProperty, "Name")) + else if(ffStrEquals(deviceProperty, "Alias")) ffDBusGetString(dbus, &dictIter, &device->name); else if(ffStrEquals(deviceProperty, "Manufacturer")) { @@ -70,7 +70,17 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue device->vendor = ffBluetoothRadioGetVendor(detection); } else if(ffStrEquals(deviceProperty, "Version")) - ffDBusGetByte(dbus, &dictIter, &device->lmpVersion); + { + uint8_t byte; + if (ffDBusGetByte(dbus, &dictIter, &byte)) + device->lmpVersion = byte; + } + else if(ffStrEquals(deviceProperty, "Powered")) + ffDBusGetBool(dbus, &dictIter, &device->enabled); + else if(ffStrEquals(deviceProperty, "Discoverable")) + ffDBusGetBool(dbus, &dictIter, &device->discoverable); + else if(ffStrEquals(deviceProperty, "Pairable")) + ffDBusGetBool(dbus, &dictIter, &device->connectable); } static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device) @@ -134,11 +144,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage FFBluetoothRadioResult* device = ffListAdd(devices); ffStrbufInit(&device->name); ffStrbufInit(&device->address); - device->lmpVersion = 0; - device->hciVersion = 0; - device->lmpSubversion = 0; - device->hciRevision = 0; + device->lmpVersion = -1; + device->lmpSubversion = -1; device->vendor = "Unknown"; + device->enabled = false; while(true) { diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c index db1d86234f..20693c04a2 100644 --- a/src/detection/bluetoothradio/bluetoothradio_windows.c +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -58,6 +58,8 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsConnectable) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothIsDiscoverable) HANDLE hRadio = NULL; HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstRadio(&(BLUETOOTH_FIND_RADIO_PARAMS) { @@ -66,7 +68,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) if(!hFind) { if (GetLastError() == ERROR_NO_MORE_ITEMS) - return "No Bluetooth radios found"; + return "No Bluetooth radios found or service disabled"; else return "BluetoothFindFirstRadio() failed"; } @@ -91,9 +93,10 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) device->lmpVersion = blri.radioInfo.lmpVersion; device->lmpSubversion = blri.radioInfo.lmpSubversion; - device->hciVersion = blri.hciVersion; - device->hciRevision = blri.hciRevision; device->vendor = ffBluetoothRadioGetVendor(blri.radioInfo.mfg); + device->enabled = true; + device->connectable = ffBluetoothIsConnectable(hRadio); + device->discoverable = ffBluetoothIsDiscoverable(hRadio); } while (ffBluetoothFindNextRadio(hFind, &hRadio)); ffBluetoothFindRadioClose(hFind); diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 0d966647e7..8adf49e9ca 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -5,7 +5,7 @@ #include "modules/bluetoothradio/bluetoothradio.h" #include "util/stringUtils.h" -#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 6 +#define FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS 8 #define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio" static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) @@ -55,16 +55,15 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio } else { - FF_STRBUF_AUTO_DESTROY lmpVersion = ffStrbufCreateF("%u.%u", radio->lmpVersion, radio->lmpSubversion); - FF_STRBUF_AUTO_DESTROY hciVersion = ffStrbufCreateF("%u.%u", radio->hciVersion, radio->hciRevision); - FF_PRINT_FORMAT_CHECKED(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &radio->name, "name"}, {FF_FORMAT_ARG_TYPE_STRBUF, &radio->address, "address"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &lmpVersion, "lmp-version"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &hciVersion, "hci-version"}, + {FF_FORMAT_ARG_TYPE_INT, &radio->lmpVersion, "lmp-version"}, + {FF_FORMAT_ARG_TYPE_INT, &radio->lmpSubversion, "lmp-subversion"}, {FF_FORMAT_ARG_TYPE_STRING, version, "version"}, {FF_FORMAT_ARG_TYPE_STRING, radio->vendor, "vendor"}, + {FF_FORMAT_ARG_TYPE_BOOL, &radio->discoverable, "discoverable"}, + {FF_FORMAT_ARG_TYPE_BOOL, &radio->connectable, "connectable"}, })); } } @@ -80,10 +79,22 @@ void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) } else { - for(uint32_t i = 0; i < radios.length; i++) + uint8_t index = 0; + FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, radios) { - uint8_t index = (uint8_t) (radios.length == 1 ? 0 : i + 1); - printDevice(options, FF_LIST_GET(FFBluetoothRadioResult, radios, i), index); + if (!radio->enabled) + continue; + + index++; + printDevice(options, radio, index); + } + + if (index == 0) + { + if (radios.length > 0) + ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled"); + else + ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); } } @@ -147,11 +158,18 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address); - yyjson_mut_obj_add_uint(doc, obj, "lmpVersion", item->lmpVersion); - yyjson_mut_obj_add_uint(doc, obj, "lmpSubversion", item->lmpSubversion); - yyjson_mut_obj_add_uint(doc, obj, "hciVersion", item->hciVersion); - yyjson_mut_obj_add_uint(doc, obj, "hciRevision", item->hciRevision); + if (item->lmpVersion < 0) + yyjson_mut_obj_add_null(doc, obj, "lmpVersion"); + else + yyjson_mut_obj_add_int(doc, obj, "lmpVersion", item->lmpVersion); + if (item->lmpSubversion < 0) + yyjson_mut_obj_add_null(doc, obj, "lmpSubversion"); + else + yyjson_mut_obj_add_int(doc, obj, "lmpSubversion", item->lmpSubversion); yyjson_mut_obj_add_str(doc, obj, "vendor", item->vendor); + yyjson_mut_obj_add_bool(doc, obj, "enabled", item->enabled); + yyjson_mut_obj_add_bool(doc, obj, "discoverable", item->discoverable); + yyjson_mut_obj_add_bool(doc, obj, "connectable", item->connectable); } FF_LIST_FOR_EACH(FFBluetoothRadioResult, radio, results) @@ -167,9 +185,11 @@ void ffPrintBluetoothRadioHelpFormat(void) "Radio name for discovering - name", "Address - local radio address", "LMP version - lmp-version", - "HCI version - hci-version", + "LMP subversion - lmp-subversion", "Bluetooth version - version", "Vendor - vendor", + "Discoverable - discoverable", + "Connectable / Pairable - connectable", })); } From 0929b940c877c6a313e579bc5448ccef9b7aa212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Jul 2024 16:32:36 +0800 Subject: [PATCH 14/67] BluetoothRadio (macOS): detect more info --- src/detection/bluetoothradio/bluetoothradio.h | 2 +- .../bluetoothradio/bluetoothradio_apple.m | 78 ++++++++++++++----- .../bluetoothradio/bluetoothradio_linux.c | 12 +-- .../bluetoothradio/bluetoothradio_windows.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 22 +++--- 5 files changed, 80 insertions(+), 36 deletions(-) diff --git a/src/detection/bluetoothradio/bluetoothradio.h b/src/detection/bluetoothradio/bluetoothradio.h index ad68ca2fde..46ea60f580 100644 --- a/src/detection/bluetoothradio/bluetoothradio.h +++ b/src/detection/bluetoothradio/bluetoothradio.h @@ -6,9 +6,9 @@ typedef struct FFBluetoothRadioResult { FFstrbuf name; FFstrbuf address; + FFstrbuf vendor; int32_t lmpVersion; int32_t lmpSubversion; - const char* vendor; bool enabled; bool discoverable; bool connectable; diff --git a/src/detection/bluetoothradio/bluetoothradio_apple.m b/src/detection/bluetoothradio/bluetoothradio_apple.m index 77414a5f64..9c0426c71a 100644 --- a/src/detection/bluetoothradio/bluetoothradio_apple.m +++ b/src/detection/bluetoothradio/bluetoothradio_apple.m @@ -1,27 +1,69 @@ #include "bluetoothradio.h" +#include "common/processing.h" #import +// For some reason the official declaration of IOBluetoothHostController don't include property `controllers` +@interface IOBluetoothHostController() ++ (id)controllers; +@end + const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */) { - IOBluetoothHostController* ctrl = IOBluetoothHostController.defaultController; - if(!ctrl) - return "IOBluetoothHostController.defaultController failed"; - - FFBluetoothRadioResult* device = ffListAdd(devices); - ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String); - ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String); - device->lmpVersion = -1; - device->lmpSubversion = -1; - device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON; - device->discoverable = false; - device->connectable = true; - - #ifdef __aarch64__ - device->vendor = "Apple"; - #else - device->vendor = "Unknown"; // Hackintosh? - #endif + NSArray* ctrls = IOBluetoothHostController.controllers; + if(!ctrls) + return "IOBluetoothHostController.controllers returns nil"; + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffProcessAppendStdOut(&buffer, (char* const[]) { + "system_profiler", + "SPBluetoothDataType", + "-xml", + "-detailLevel", + "basic", + NULL + }) != NULL) + return "Starting `system_profiler SPBluetoothDataType -xml -detailLevel basic` failed"; + + NSArray* arr = [NSPropertyListSerialization propertyListWithData:[NSData dataWithBytes:buffer.chars length:buffer.length] + options:NSPropertyListImmutable + format:nil + error:nil]; + if (!arr || !arr.count) + return "system_profiler SPBluetoothDataType returned an empty array"; + + for (IOBluetoothHostController* ctrl in ctrls) + { + FFBluetoothRadioResult* device = ffListAdd(devices); + ffStrbufInitS(&device->name, ctrl.nameAsString.UTF8String); + ffStrbufInitS(&device->address, ctrl.addressAsString.UTF8String); + ffStrbufInitStatic(&device->vendor, "Apple"); + device->lmpVersion = INT_MIN; + device->lmpSubversion = INT_MIN; + device->enabled = ctrl.powerState == kBluetoothHCIPowerStateON; + device->discoverable = false; + device->connectable = true; + + for (NSDictionary* itemDict in arr[0][@"_items"]) + { + NSDictionary* props = itemDict[@"controller_properties"]; + if (!props) continue; + + if (![ctrl.addressAsString isEqualToString:props[@"controller_address"]]) continue; + + NSString* services = props[@"controller_supportedServices"]; + if ([services containsString:@" LEA "]) + device->lmpVersion = -11; + else if ([services containsString:@" GATT "]) + device->lmpVersion = -6; + + device->discoverable = ![props[@"controller_discoverable"] isEqualToString:@"attrib_off"]; + ffStrbufSetS(&device->vendor, ((NSString*) props[@"controller_vendorID"]).UTF8String); + ffStrbufSubstrAfterFirstC(&device->vendor, '('); + ffStrbufTrimRight(&device->vendor, ')'); + break; + } + } return NULL; } diff --git a/src/detection/bluetoothradio/bluetoothradio_linux.c b/src/detection/bluetoothradio/bluetoothradio_linux.c index 8a1ac01084..dca38cf036 100644 --- a/src/detection/bluetoothradio/bluetoothradio_linux.c +++ b/src/detection/bluetoothradio/bluetoothradio_linux.c @@ -65,9 +65,9 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue ffDBusGetString(dbus, &dictIter, &device->name); else if(ffStrEquals(deviceProperty, "Manufacturer")) { - uint16_t detection; - if (ffDBusGetUint16(dbus, &dictIter, &detection)) - device->vendor = ffBluetoothRadioGetVendor(detection); + uint16_t vendorId; + if (ffDBusGetUint16(dbus, &dictIter, &vendorId)) + ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(vendorId)); } else if(ffStrEquals(deviceProperty, "Version")) { @@ -144,9 +144,9 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage FFBluetoothRadioResult* device = ffListAdd(devices); ffStrbufInit(&device->name); ffStrbufInit(&device->address); - device->lmpVersion = -1; - device->lmpSubversion = -1; - device->vendor = "Unknown"; + ffStrbufInitStatic(&device->vendor, "Unknown"); + device->lmpVersion = INT_MIN; + device->lmpSubversion = INT_MIN; device->enabled = false; while(true) diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c index 20693c04a2..772b3b1b57 100644 --- a/src/detection/bluetoothradio/bluetoothradio_windows.c +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -93,7 +93,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) device->lmpVersion = blri.radioInfo.lmpVersion; device->lmpSubversion = blri.radioInfo.lmpSubversion; - device->vendor = ffBluetoothRadioGetVendor(blri.radioInfo.mfg); + ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg)); device->enabled = true; device->connectable = ffBluetoothIsConnectable(hRadio); device->discoverable = ffBluetoothIsDiscoverable(hRadio); diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 8adf49e9ca..956da3ea16 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -26,14 +26,14 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio const char* version = NULL; - switch (radio->lmpVersion) + switch (radio->lmpVersion < 0 ? -radio->lmpVersion : radio->lmpVersion) { case 0: version = "1.0b"; break; case 1: version = "1.1"; break; case 2: version = "1.2"; break; - case 3: version = "2.0 + EDR"; break; - case 4: version = "2.1 + EDR"; break; - case 5: version = "3.0 + HS"; break; + case 3: version = "2.0"; break; + case 4: version = "2.1"; break; + case 5: version = "3.0"; break; case 6: version = "4.0"; break; case 7: version = "4.1"; break; case 8: version = "4.2"; break; @@ -49,9 +49,9 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); if (version) - printf("Bluetooth %s (%s)\n", version, radio->vendor); + printf("Bluetooth %s%s (%s)\n", version, (radio->lmpVersion < 0 ? "+" : ""), radio->vendor.chars); else - fputs(radio->vendor, stdout); + ffStrbufPutTo(&radio->vendor, stdout); } else { @@ -61,7 +61,7 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio {FF_FORMAT_ARG_TYPE_INT, &radio->lmpVersion, "lmp-version"}, {FF_FORMAT_ARG_TYPE_INT, &radio->lmpSubversion, "lmp-subversion"}, {FF_FORMAT_ARG_TYPE_STRING, version, "version"}, - {FF_FORMAT_ARG_TYPE_STRING, radio->vendor, "vendor"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &radio->vendor, "vendor"}, {FF_FORMAT_ARG_TYPE_BOOL, &radio->discoverable, "discoverable"}, {FF_FORMAT_ARG_TYPE_BOOL, &radio->connectable, "connectable"}, })); @@ -102,6 +102,7 @@ void ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) { ffStrbufDestroy(&radio->name); ffStrbufDestroy(&radio->address); + ffStrbufDestroy(&radio->vendor); } } @@ -158,15 +159,15 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address); - if (item->lmpVersion < 0) + if (item->lmpVersion == INT_MIN) yyjson_mut_obj_add_null(doc, obj, "lmpVersion"); else yyjson_mut_obj_add_int(doc, obj, "lmpVersion", item->lmpVersion); - if (item->lmpSubversion < 0) + if (item->lmpSubversion == INT_MIN) yyjson_mut_obj_add_null(doc, obj, "lmpSubversion"); else yyjson_mut_obj_add_int(doc, obj, "lmpSubversion", item->lmpSubversion); - yyjson_mut_obj_add_str(doc, obj, "vendor", item->vendor); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &item->vendor); yyjson_mut_obj_add_bool(doc, obj, "enabled", item->enabled); yyjson_mut_obj_add_bool(doc, obj, "discoverable", item->discoverable); yyjson_mut_obj_add_bool(doc, obj, "connectable", item->connectable); @@ -176,6 +177,7 @@ void ffGenerateBluetoothRadioJsonResult(FF_MAYBE_UNUSED FFBluetoothRadioOptions* { ffStrbufDestroy(&radio->name); ffStrbufDestroy(&radio->address); + ffStrbufDestroy(&radio->vendor); } } From 2bb988a7f8fc2b49376690ad3e96ac7951739abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Jul 2024 16:44:54 +0800 Subject: [PATCH 15/67] CPU: fix freq max formatting --- presets/examples/20.jsonc | 2 +- src/modules/cpu/cpu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/presets/examples/20.jsonc b/presets/examples/20.jsonc index e64c0b0867..162e813f31 100644 --- a/presets/examples/20.jsonc +++ b/presets/examples/20.jsonc @@ -106,7 +106,7 @@ { "type": "cpu", "key": "│ CPU FREQ │{$1}", - "format": "{freq-max}{/freq-max}{freq-base}{/} GHz" + "format": "{freq-max}{/freq-max}{freq-base}{/}" }, { "type": "loadavg", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 72391793b4..65503eb9a7 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -95,7 +95,7 @@ void ffPrintCPU(FFCPUOptions* options) FF_STRBUF_AUTO_DESTROY freqBase = ffStrbufCreate(); ffParseFrequency(cpu.frequencyBase, &freqBase); FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBase, &freqMax); + ffParseFrequency(cpu.frequencyMax, &freqMax); FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate(); ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit); From 6cb565e3797f0a9e9311f6ffbe9ee2f4de7dbfe8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 29 Jul 2024 18:42:24 +0800 Subject: [PATCH 16/67] BluetoothRadio: don't print unnecessary index --- src/modules/bluetoothradio/bluetoothradio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 956da3ea16..455c06df2d 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -46,7 +46,7 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); if (version) printf("Bluetooth %s%s (%s)\n", version, (radio->lmpVersion < 0 ? "+" : ""), radio->vendor.chars); @@ -55,7 +55,7 @@ static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadio } else { - FF_PRINT_FORMAT_CHECKED(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BLUETOOTHRADIO_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &radio->name, "name"}, {FF_FORMAT_ARG_TYPE_STRBUF, &radio->address, "address"}, {FF_FORMAT_ARG_TYPE_INT, &radio->lmpVersion, "lmp-version"}, From bbbb493cdf8514423e9b1331a34f88ccb2a429ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Jul 2024 18:55:43 +0800 Subject: [PATCH 17/67] BluetoothRadio (Windows): fix segfault --- src/detection/bluetoothradio/bluetoothradio_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/bluetoothradio/bluetoothradio_windows.c b/src/detection/bluetoothradio/bluetoothradio_windows.c index 772b3b1b57..6e6f9461b0 100644 --- a/src/detection/bluetoothradio/bluetoothradio_windows.c +++ b/src/detection/bluetoothradio/bluetoothradio_windows.c @@ -93,7 +93,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) device->lmpVersion = blri.radioInfo.lmpVersion; device->lmpSubversion = blri.radioInfo.lmpSubversion; - ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg)); + ffStrbufInitStatic(&device->vendor, ffBluetoothRadioGetVendor(blri.radioInfo.mfg)); device->enabled = true; device->connectable = ffBluetoothIsConnectable(hRadio); device->discoverable = ffBluetoothIsDiscoverable(hRadio); From 4371e719ae6e2686dd28956525a795e9b96ed63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 29 Jul 2024 21:47:32 +0800 Subject: [PATCH 18/67] CI (Linux): build aarch64 version with ubuntu 20.04 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e8e234140..379f819e9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,11 +138,11 @@ jobs: id: runcmd with: arch: aarch64 - distro: ubuntu22.04 + distro: ubuntu20.04 githubToken: ${{ github.token }} run: | uname -a - apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm + apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features From ec8391f6c698fbc20080c8de1d836b8adbb462fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 30 Jul 2024 11:06:27 +0800 Subject: [PATCH 19/67] Global: don't use __has_include It reports false results in ubuntu 20.04. Details unknown. --- CMakeLists.txt | 30 ++++++++++++++- src/common/init.c | 60 ++++++++++++++--------------- src/common/io/io_unix.c | 8 ++-- src/common/thread.h | 4 +- src/detection/camera/camera_linux.c | 4 +- src/detection/gpu/gpu_linux.c | 28 ++++++-------- src/detection/users/users_linux.c | 2 +- src/detection/wifi/wifi_linux.c | 2 +- 8 files changed, 81 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e6e859630..319bc18e77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1186,7 +1186,35 @@ if(WIN32) PRIVATE "-static" # stdc++, winpthread, gcc_s, etc. ) endif() - set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD 17) +endif() +if(LINUX) + CHECK_INCLUDE_FILE("linux/videodev2.h" HAVE_LINUX_VIDEODEV2) + if(HAVE_LINUX_VIDEODEV2) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LINUX_VIDEODEV2=1) + endif() + CHECK_INCLUDE_FILE("linux/wireless.h" HAVE_LINUX_WIRELESS) + if(HAVE_LINUX_WIRELESS) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LINUX_WIRELESS=1) + endif() +endif() +if(NOT WIN32) + CHECK_INCLUDE_FILE("utmpx.h" HAVE_UTMPX) + if(HAVE_UTMPX) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_UTMPX=1) + endif() + CHECK_INCLUDE_FILE("wordexp.h" HAVE_WORDEXP) + if(HAVE_WORDEXP) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1) + endif() + CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP) + if(HAVE_PTHREAD_NP) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_PTHREAD_NP=1) + endif() + check_function_exists("pthread_timedjoin_np" HAVE_TIMEDJOIN_NP) + if(HAVE_TIMEDJOIN_NP) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_TIMEDJOIN_NP=1) + endif() endif() ###################### diff --git a/src/common/init.c b/src/common/init.c index 13d6f44682..c9c80ed97c 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -173,94 +173,94 @@ void ffDestroyInstance(void) void ffListFeatures(void) { fputs( - #ifdef FF_HAVE_THREADS + #if FF_HAVE_THREADS "threads\n" #endif - #ifdef FF_HAVE_VULKAN + #if FF_HAVE_VULKAN "vulkan\n" #endif - #ifdef FF_HAVE_WAYLAND + #if FF_HAVE_WAYLAND "wayland\n" #endif - #ifdef FF_HAVE_XCB_RANDR + #if FF_HAVE_XCB_RANDR "xcb-randr\n" #endif - #ifdef FF_HAVE_XCB + #if FF_HAVE_XCB "xcb\n" #endif - #ifdef FF_HAVE_XRANDR + #if FF_HAVE_XRANDR "xrandr\n" #endif - #ifdef FF_HAVE_X11 + #if FF_HAVE_X11 "x11\n" #endif - #ifdef FF_HAVE_DRM + #if FF_HAVE_DRM "drm\n" #endif - #ifdef FF_HAVE_GIO + #if FF_HAVE_GIO "gio\n" #endif - #ifdef FF_HAVE_DCONF + #if FF_HAVE_DCONF "dconf\n" #endif - #ifdef FF_HAVE_DBUS + #if FF_HAVE_DBUS "dbus\n" #endif - #ifdef FF_HAVE_IMAGEMAGICK7 + #if FF_HAVE_IMAGEMAGICK7 "imagemagick7\n" #endif - #ifdef FF_HAVE_IMAGEMAGICK6 + #if FF_HAVE_IMAGEMAGICK6 "imagemagick6\n" #endif - #ifdef FF_HAVE_CHAFA + #if FF_HAVE_CHAFA "chafa\n" #endif - #ifdef FF_HAVE_ZLIB + #if FF_HAVE_ZLIB "zlib\n" #endif - #ifdef FF_HAVE_XFCONF + #if FF_HAVE_XFCONF "xfconf\n" #endif - #ifdef FF_HAVE_SQLITE3 + #if FF_HAVE_SQLITE3 "sqlite3\n" #endif - #ifdef FF_HAVE_RPM + #if FF_HAVE_RPM "rpm\n" #endif - #ifdef FF_HAVE_EGL + #if FF_HAVE_EGL "egl\n" #endif - #ifdef FF_HAVE_GLX + #if FF_HAVE_GLX "glx\n" #endif - #ifdef FF_HAVE_OSMESA + #if FF_HAVE_OSMESA "osmesa\n" #endif - #ifdef FF_HAVE_OPENCL + #if FF_HAVE_OPENCL "opencl\n" #endif - #ifdef FF_HAVE_FREETYPE + #if FF_HAVE_FREETYPE "freetype\n" #endif - #ifdef FF_HAVE_PULSE + #if FF_HAVE_PULSE "libpulse\n" #endif - #ifdef FF_HAVE_LIBNM + #if FF_HAVE_LIBNM "libnm\n" #endif - #ifdef FF_HAVE_DDCUTIL + #if FF_HAVE_DDCUTIL "libddcutil\n" #endif - #ifdef FF_HAVE_DIRECTX_HEADERS + #if FF_HAVE_DIRECTX_HEADERS "Directx Headers\n" #endif - #ifdef FF_USE_SYSTEM_YYJSON + #if FF_USE_SYSTEM_YYJSON "System yyjson\n" #endif - #if __has_include() + #if FF_HAVE_LINUX_VIDEODEV2 "linux/videodev2\n" #endif - #if __has_include() + #if FF_HAVE_LINUX_WIRELESS "linux/wireless\n" #endif "" diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 788d47a3fc..870b773fab 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -8,8 +8,10 @@ #include #include -#if __has_include() -#include +#if FF_HAVE_WORDEXP + #include +#else + #warning " not available" #endif static void createSubfolders(const char* fileName) @@ -112,7 +114,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o { bool result = false; - #if __has_include() // https://github.com/termux/termux-packages/pull/7056 + #if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056 wordexp_t exp; if(wordexp(in, &exp, 0) != 0) diff --git a/src/common/thread.h b/src/common/thread.h index 2fd328cf42..62c8cc0567 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -33,7 +33,7 @@ #else #include #include - #if __has_include() + #if FF_HAVE_PTHREAD_NP #include #endif #define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER @@ -51,7 +51,7 @@ static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); } static inline bool ffThreadJoin(FFThreadType thread, FF_MAYBE_UNUSED uint32_t timeout) { - #if (defined(__linux__) && !defined(__ANDROID__)) || __has_include() + #if HAVE_TIMEDJOIN_NP if (timeout > 0) { struct timespec ts; diff --git a/src/detection/camera/camera_linux.c b/src/detection/camera/camera_linux.c index 080a322a99..d7e2988e43 100644 --- a/src/detection/camera/camera_linux.c +++ b/src/detection/camera/camera_linux.c @@ -5,13 +5,13 @@ #include #include -#if __has_include() +#if FF_HAVE_LINUX_VIDEODEV2 #include #endif const char* ffDetectCamera(FFlist* result) { -#if __has_include() +#if FF_HAVE_LINUX_VIDEODEV2 char path[] = "/dev/videoN"; for (uint32_t i = 0; i <= 9; ++i) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 7b0fb54624..9281b13cb9 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -7,29 +7,23 @@ #include "common/properties.h" #include "util/stringUtils.h" -#define FF_STR_INDIR(x) #x -#define FF_STR(x) FF_STR_INDIR(x) - #include -#if __has_include() - #include - #define FF_HAVE_DRM_H 1 -#elif __has_include() - #include - #define FF_HAVE_DRM_H 1 -#endif - -#if FF_HAVE_DRM_H - #include - #include - - #if __aarch64__ && __has_include() - #include +#if __aarch64__ + #if __has_include() + #include + #include + #include + #include #define FF_HAVE_ASAHI_DRM_H 1 + #else + #warning " not available" #endif #endif +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) { uint32_t pciDirLength = pciDir->length; diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index 86e69dbe42..30c38c2af1 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -1,7 +1,7 @@ #include "fastfetch.h" #include "users.h" -#if __has_include() +#if FF_HAVE_UTMPX #include #else //for Android compatibility diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 0392fb706f..60e5107919 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -212,7 +212,7 @@ static const char* detectWifiWithLibnm(FFlist* result) #endif -#if __has_include() +#if FF_HAVE_LINUX_WIRELESS #define FF_DETECT_WIFI_WITH_IOCTLS #include "common/io/io.h" From 88a7468489f78f24bc061ccda5204caddfa31165 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 30 Jul 2024 16:43:56 +0800 Subject: [PATCH 20/67] GPU (Linux): fix apple gpu support --- src/detection/gpu/gpu_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 9281b13cb9..ed71f85967 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -10,8 +10,8 @@ #include #if __aarch64__ - #if __has_include() - #include + #if __has_include() && FF_HAVE_DRM + #include #include #include #include From ced67e81a5d39f964220e551a1f1a91b05e3d0b5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 30 Jul 2024 23:50:19 +0800 Subject: [PATCH 21/67] DisplayServer (Linux): ensure $XDG_RUNTIME_DIR is set before connecting wayland --- src/detection/displayserver/linux/wayland/wayland.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 3fc59362ae..2b64bbce34 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -136,6 +136,9 @@ uint32_t ffWaylandHandleRotation(WaylandDisplay* display) const char* ffdsConnectWayland(FFDisplayServerResult* result) { + if (getenv("XDG_RUNTIME_DIR") == NULL) + return "Wayland requires $XDG_RUNTIME_DIR being set"; + FF_LIBRARY_LOAD(wayland, &instance.config.library.libWayland, false, "libwayland-client" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wayland, wl_display_connect) From fa0007ac6f0967df0ff83fd677f7f8ad9203d632 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 31 Jul 2024 08:57:53 +0800 Subject: [PATCH 22/67] CPU (Android): add SD 4s Gen 2 --- src/detection/cpu/cpu_linux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 851c881dbf..422f7f51d6 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -46,6 +46,8 @@ static void detectQualcomm(FFCPUResult* cpu) else if (ffStrbufEqualS(&cpu->name, "SM6450")) ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 6 Gen 1 [SM6450]"); + else if (ffStrbufEqualS(&cpu->name, "SM4635")) + ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4s Gen 2 [SM4635]"); else if (ffStrbufEqualS(&cpu->name, "SM4450")) ffStrbufSetStatic(&cpu->name, "Qualcomm Snapdragon 4 Gen 2 [SM4450]"); else if (ffStrbufEqualS(&cpu->name, "SM4375")) From a070519721abbae5928c3bedb35668511a258b4d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 31 Jul 2024 09:40:00 +0800 Subject: [PATCH 23/67] IO: disallow input echo --- src/common/io/io_unix.c | 49 ++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 870b773fab..d459c3d924 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -133,46 +133,39 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o return result; } -const char* ffGetTerminalResponse(const char* request, const char* format, ...) +static int ftty = -1; +static struct termios oldTerm; +void restoreTerm(void) { - int fin = STDIN_FILENO, fout = STDOUT_FILENO; - FF_AUTO_CLOSE_FD int ftty = -1; + tcsetattr(ftty, TCSAFLUSH, &oldTerm); +} - if (!isatty(STDIN_FILENO)) - { - if (ftty < 0) - ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); - fin = ftty; - } - if (!isatty(STDOUT_FILENO)) +const char* ffGetTerminalResponse(const char* request, const char* format, ...) +{ + if (ftty < 0) { + ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); if (ftty < 0) - ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); - fout = ftty; - } + return "open(\"/dev/tty\", O_RDWR | O_NOCTTY | O_CLOEXEC) failed"; - struct termios oldTerm; - if(tcgetattr(fin, &oldTerm) == -1) - return "tcgetattr(STDIN_FILENO, &oldTerm) failed"; + if(tcgetattr(ftty, &oldTerm) == -1) + return "tcgetattr(STDIN_FILENO, &oldTerm) failed"; - struct termios newTerm = oldTerm; - newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO); - if(tcsetattr(fin, TCSAFLUSH, &newTerm) == -1) - return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)"; + struct termios newTerm = oldTerm; + newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO); + if(tcsetattr(ftty, TCSAFLUSH, &newTerm) == -1) + return "tcsetattr(STDIN_FILENO, TCSAFLUSH, &newTerm)"; + atexit(restoreTerm); + } - ffWriteFDData(fout, strlen(request), request); + ffWriteFDData(ftty, strlen(request), request); //Give the terminal some time to respond - if(poll(&(struct pollfd) { .fd = fin, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0) - { - tcsetattr(fin, TCSANOW, &oldTerm); + if(poll(&(struct pollfd) { .fd = ftty, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0) return "poll() timeout or failed"; - } char buffer[512]; - ssize_t bytesRead = read(fin, buffer, sizeof(buffer) - 1); - - tcsetattr(fin, TCSANOW, &oldTerm); + ssize_t bytesRead = read(ftty, buffer, sizeof(buffer) - 1); if(bytesRead <= 0) return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed"; From cf0d1cf2946d5c1c7759ec6b8d0adf8c9ab2de8c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 31 Jul 2024 10:13:29 +0800 Subject: [PATCH 24/67] DisplayServer (Linux): don't print unknown as display name --- src/detection/displayserver/linux/wayland/global-output.c | 2 +- src/detection/displayserver/linux/wayland/zwlr-output.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index 7f815f42f0..a8299d16d7 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -122,7 +122,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist display.edidName.length ? &display.edidName // Try ignoring `eDP-1-unknown`, where `unknown` is localized - : display.description.length && !(ffStrbufStartsWithS(&display.description, display.name.chars) && display.description.chars[display.name.length] == '-') + : display.description.length && !ffStrbufContain(&display.description, &display.name) ? &display.description : &display.name, display.type, diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index 76aee392a7..dd31b91b0a 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -131,7 +131,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output rotation, display.edidName.length ? &display.edidName - : display.description.length + : display.description.length && !ffStrbufContain(&display.description, &display.name) ? &display.description : &display.name, display.type, From bd5012edc89f96450d3444abd9b390c9f858719b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 31 Jul 2024 11:13:04 +0800 Subject: [PATCH 25/67] PhysicalMemory: make sure to detect all memory devices --- src/detection/physicalmemory/physicalmemory.c | 6 ++++++ src/detection/physicalmemory/physicalmemory_linux.c | 6 +++--- src/modules/physicalmemory/physicalmemory.c | 6 ++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/detection/physicalmemory/physicalmemory.c b/src/detection/physicalmemory/physicalmemory.c index 6591c32453..c5df181f38 100644 --- a/src/detection/physicalmemory/physicalmemory.c +++ b/src/detection/physicalmemory/physicalmemory.c @@ -23,6 +23,12 @@ static inline const char* getVendorString(unsigned vendorId) void FFPhysicalMemoryUpdateVendorString(FFPhysicalMemoryResult* device) { + if (ffStrbufEqualS(&device->vendor, "Unknown")) + { + ffStrbufClear(&device->vendor); + return; + } + char vendorIdStr[5]; if (ffStrbufStartsWithS(&device->vendor, "0x")) { diff --git a/src/detection/physicalmemory/physicalmemory_linux.c b/src/detection/physicalmemory/physicalmemory_linux.c index 1eb971e8ba..fc83f92a31 100644 --- a/src/detection/physicalmemory/physicalmemory_linux.c +++ b/src/detection/physicalmemory/physicalmemory_linux.c @@ -75,10 +75,10 @@ const char* ffDetectPhysicalMemory(FFlist* result) if (!data) return "Memory device is not found in SMBIOS data"; - for (; data->Header.Type == FF_SMBIOS_TYPE_MEMORY_DEVICE; - data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header)) + for (; data->Header.Type < FF_SMBIOS_TYPE_END_OF_TABLE; + data = (const FFSmbiosMemoryDevice*) ffSmbiosNextEntry(&data->Header)) { - if (data->Size == 0) continue; + if (data->Header.Type != FF_SMBIOS_TYPE_MEMORY_DEVICE || data->Size == 0) continue; const char* strings = (const char*) data + data->Header.Length; diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 84e62eb904..6949b045d8 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -20,6 +20,12 @@ void ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) return; } + if (result.length == 0) + { + ffPrintError(FF_PHYSICALMEMORY_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory detected"); + return; + } + FF_STRBUF_AUTO_DESTROY prettySize = ffStrbufCreate(); uint32_t i = 0; From 7eaaed60245b8c08d0c5f826e7f618ccc7759fd4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 31 Jul 2024 14:19:42 +0800 Subject: [PATCH 26/67] WM (Linux): don't use `wl-restart` as WM name Fix #1135 --- src/detection/displayserver/linux/wayland/wayland.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 2b64bbce34..71671a74d5 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -30,8 +30,19 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result) if (!ffReadFileBuffer(procPath.chars, &result->wmProcessName)) return false; + // #1135: wl-restart is a special case + const char* filename = strrchr(result->wmProcessName.chars, '/'); + if (filename) + filename++; + else + filename = result->wmProcessName.chars; + + if (ffStrEquals(filename, "wl-restart")) + ffStrbufSubstrAfterFirstC(&result->wmProcessName, '\0'); + ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path + return true; } #else From 2ce7c8c60d47475fd88a704841f2e8964aa0499a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 31 Jul 2024 22:23:19 +0800 Subject: [PATCH 27/67] GPU (Windows): use pci bus id to match Nvidia cards Fix multi-gpu device --- src/detection/gpu/gpu_windows.c | 44 +++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 34ecaa5379..83c3281da1 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -53,6 +53,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* wchar_t regControlVideoKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{"; const uint32_t regControlVideoKeyPrefixLength = (uint32_t) wcslen(regControlVideoKey); const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regControlVideoKeyPrefixLength; + wchar_t regPciKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Enum\\"; + const uint32_t regPciKeyPrefixLength = (uint32_t) wcslen(regPciKey); for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i) { @@ -144,17 +146,55 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { - if (vendorId && deviceId && subSystemId) + if (vendorId && deviceId) { + int bus = -1, dev = -1, func = -1; + if (detectFn == ffDetectNvidiaGpuInfo) + { + // Find PCI id from video id + // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\DEVICE_ID\INSTANCE_ID\Device Parameters\VideoID + wcscpy(regPciKey + regPciKeyPrefixLength, displayDevice.DeviceID); + FF_HKEY_AUTO_DESTROY hKey = NULL; + if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regPciKey, &hKey, NULL)) continue; + for (uint32_t idx = 0; ; ++idx) + { + wchar_t instanceKey[256]; + DWORD bufSizeInstanceKey = sizeof(instanceKey) / sizeof(*instanceKey); + if (RegEnumKeyExW(hKey, idx, instanceKey, &bufSizeInstanceKey, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) break; + wcscpy(instanceKey + bufSizeInstanceKey, L"\\Device Parameters"); + + wchar_t videoId[256]; + DWORD bufSizeVideoId = sizeof(videoId) / sizeof(*videoId); + if (RegGetValueW(hKey, instanceKey, L"VideoID", RRF_RT_REG_SZ, NULL, videoId, &bufSizeVideoId) != ERROR_SUCCESS) continue; + if (videoId[0] != L'{') continue; + if (wmemcmp(videoId + 1 /* Ignore {} */, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000")) != 0) continue; + + // We finally find it + instanceKey[bufSizeInstanceKey] = L'\0'; + bufSizeVideoId = sizeof(videoId) / sizeof(*videoId); + if (RegGetValueW(hKey, instanceKey, L"LocationInformation", RRF_RT_REG_SZ, NULL, videoId, &bufSizeVideoId) != ERROR_SUCCESS) break; + swscanf(videoId, L"%*[^(](%d,%d,%d)", &bus, &dev, &func); + break; + } + } + detectFn( &(FFGpuDriverCondition) { - .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | FF_GPU_DRIVER_CONDITION_TYPE_LUID, + .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID + | FF_GPU_DRIVER_CONDITION_TYPE_LUID + | (bus > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), .pciDeviceId = { .deviceId = deviceId, .vendorId = vendorId, .subSystemId = subSystemId, .revId = revId, }, + .pciBusId = { + .domain = 0, + .bus = (uint32_t) bus, + .device = (uint32_t) dev, + .func = (uint32_t) func, + }, .luid = gpu->deviceId, }, (FFGpuDriverResult) { From 5d32eba1a628bf7497f07db2b65bb8723128da85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 31 Jul 2024 23:40:25 +0800 Subject: [PATCH 28/67] GPU (Nvidia): detect GPU core usage --- src/detection/gpu/gpu_driver_specific.h | 1 + src/detection/gpu/gpu_nvidia.c | 9 +++++++++ src/detection/gpu/nvml.h | 12 ++++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 8c935ff8c5..c22ce18eb3 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -42,6 +42,7 @@ typedef struct FFGpuDriverResult uint32_t* coreCount; FFGPUType* type; uint32_t* frequency; + uint8_t* usage; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 683e681ef2..5d158833a2 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -12,6 +12,7 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2) FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores) FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo) + FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates) FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand) bool inited; @@ -35,6 +36,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, nvmlDeviceGetMaxClockInfo) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand) if (ffnvmlInit_v2() != NVML_SUCCESS) @@ -124,6 +126,13 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR if (result.frequency) nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency); + if (result.usage) + { + nvmlUtilization_t rates; + if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &rates) == NVML_SUCCESS) + *result.usage = (uint8_t) rates.gpu; + } + return NULL; #else diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index ea776a4bee..d3f1904b09 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -94,6 +94,16 @@ typedef enum { NVML_BRAND_COUNT, } nvmlBrandType_t; +// https://docs.nvidia.com/deploy/nvml-api/structnvmlUtilization__t.html#structnvmlUtilization__t +// Utilization information for a device. +typedef struct +{ + // Percent of time over the past second during which one or more kernels was executing on the GPU + unsigned int gpu; + // Percent of time over the past second during which global (device) memory was being read or written + unsigned int memory; +} nvmlUtilization_t; + // https://docs.nvidia.com/deploy/nvml-api/group__nvmlInitializationAndCleanup.html#group__nvmlInitializationAndCleanup // Initialize NVML, but don't initialize any GPUs yet nvmlReturn_t nvmlInit_v2(void); @@ -119,3 +129,5 @@ extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType_t type, unsigned int* clock); // Retrieves the brand of this device extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type); +// Retrieves the current utilization rates for the device +extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization); From 1e8b9aa461ad79fcca97dfa876774d37f5fce898 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 1 Aug 2024 00:06:22 +0800 Subject: [PATCH 29/67] GPU (Linux): detect if nvidia driver is open source or proprietary --- src/detection/gpu/gpu_linux.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index ed71f85967..181ddc6a67 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -39,6 +39,17 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash); } + if (ffStrbufEqualS(&gpu->driver, "nvidia")) + { + if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer)) + { + if (ffStrbufContainS(buffer, " Open ")) + ffStrbufAppendS(&gpu->driver, " (open source)"); + else + ffStrbufAppendS(&gpu->driver, " (proprietary)"); + } + } + if (instance.config.general.detectVersion) { ffStrbufAppendS(pciDir, "/module/version"); From cbf8fdf3fc38c2368558ee1c39836a0d9d88f081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 08:54:12 +0800 Subject: [PATCH 30/67] GPU (macOS): ensure we only detects GPU May fix #1066 --- src/detection/gpu/gpu_apple.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index be74022c0e..329febf42b 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -76,8 +76,12 @@ static const char* detectFrequency(FFGPUResult* gpu) const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL; - if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess) - return "IOServiceGetMatchingServices() failed"; + { + CFMutableDictionaryRef matches = IOServiceMatching(kIOAcceleratorClassName); + CFDictionaryAddValue(matches, CFSTR("IOMatchCategory"), CFSTR(kIOAcceleratorClassName)); + if (IOServiceGetMatchingServices(MACH_PORT_NULL, matches, &iterator) != kIOReturnSuccess) + return "IOServiceGetMatchingServices() failed"; + } io_registry_entry_t registryEntry; while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL) From c549a5cab8b362219fbbcb6048346f74d0a23567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 13:54:03 +0800 Subject: [PATCH 31/67] GPU (macOS): report core usage --- src/detection/gpu/gpu.c | 1 + src/detection/gpu/gpu.h | 2 ++ src/detection/gpu/gpu_apple.c | 38 ++++++++++++++++++++++++- src/detection/gpu/gpu_apple.m | 11 ------- src/detection/gpu/gpu_bsd.c | 2 ++ src/detection/gpu/gpu_driver_specific.h | 2 +- src/detection/gpu/gpu_linux.c | 1 + src/detection/gpu/gpu_nvidia.c | 8 +++--- src/detection/gpu/gpu_sunos.c | 1 + src/detection/gpu/gpu_windows.c | 2 ++ src/detection/gpu/gpu_wsl.cpp | 3 ++ src/detection/opencl/opencl.c | 1 + src/detection/vulkan/vulkan.c | 1 + src/modules/gpu/gpu.c | 4 ++- src/modules/opencl/opencl.c | 2 +- 15 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index d9b30cd2e1..fee845022c 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -56,6 +56,7 @@ const char* detectByOpenGL(FFlist* gpus) gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0}; gpu->deviceId = 0; diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index e3e50dacd5..ffa82d0cac 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -6,6 +6,7 @@ #define FF_GPU_CORE_COUNT_UNSET -1 #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) #define FF_GPU_FREQUENCY_UNSET 0 +#define FF_GPU_CORE_USAGE_UNSET (0/0.0) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -35,6 +36,7 @@ typedef struct FFGPUResult uint32_t frequency; // Maximum time clock frequency in MHz FFGPUMemory dedicated; FFGPUMemory shared; + double coreUsage; uint64_t deviceId; // Used internally, may be uninitialized } FFGPUResult; diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 329febf42b..1190a63676 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -107,6 +107,31 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = 0.0/0.0; + CFDictionaryRef perfStatistics = NULL; + uint64_t vramUsed = 0, vramTotal = 0; + if (ffCfDictGetDict(properties, CFSTR("PerformanceStatistics"), &perfStatistics) == NULL) + { + int64_t utilization; + if (ffCfDictGetInt64(perfStatistics, CFSTR("Device Utilization %"), &utilization) == NULL) + gpu->coreUsage = (double) utilization; + else if (ffCfDictGetInt64(perfStatistics, CFSTR("GPU Core Utilization"), &utilization) == NULL) + gpu->coreUsage = (double) utilization / 10000000.; // Nvidia? + + if (ffCfDictGetInt64(perfStatistics, CFSTR("Alloc system memory"), (int64_t*) &vramTotal) == NULL) + { + if (ffCfDictGetInt64(perfStatistics, CFSTR("In use system memory"), (int64_t*) &vramUsed) != NULL) + vramTotal = 0; + } + else if (ffCfDictGetInt64(perfStatistics, CFSTR("vramUsedBytes"), (int64_t*) &vramTotal) == NULL) + { + if (ffCfDictGetInt64(perfStatistics, CFSTR("vramFreeBytes"), (int64_t*) &vramUsed) == NULL) + vramTotal += vramUsed; + else + vramTotal = 0; + } + } + ffStrbufInit(&gpu->name); //IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs. //Still needs testing for AMD's @@ -127,7 +152,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) ffStrbufInit(&gpu->vendor); int vendorId; - if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId)) + if(ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId) == NULL) { const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId); ffStrbufAppendS(&gpu->vendor, vendorStr); @@ -140,6 +165,17 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (vendorStr == FF_GPU_VENDOR_NAME_APPLE) detectFrequency(gpu); #endif + + if (gpu->type == FF_GPU_TYPE_INTEGRATED) + { + gpu->shared.total = vramTotal; + gpu->shared.used = vramUsed; + } + else + { + gpu->dedicated.total = vramTotal; + gpu->dedicated.used = vramUsed; + } } gpu->temperature = options->temp ? detectGpuTemp(&gpu->name) : FF_GPU_TEMP_UNSET; diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index c63abaf5f5..e5b6bebf60 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -44,17 +44,6 @@ gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; #endif - - if (gpu->type == FF_GPU_TYPE_INTEGRATED) - { - gpu->shared.total = device.recommendedMaxWorkingSetSize; - gpu->shared.used = device.currentAllocatedSize; - } - else - { - gpu->dedicated.total = device.recommendedMaxWorkingSetSize; - gpu->dedicated.used = device.currentAllocatedSize; - } } return NULL; } diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 7bc22b485c..87abb0630d 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -57,6 +57,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) ffStrbufInit(&gpu->platformApi); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func; @@ -92,6 +93,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, .type = &gpu->type, .frequency = &gpu->frequency, + .coreUsage = &gpu->coreUsage, }, "libnvidia-ml.so"); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index c22ce18eb3..01f3b67a93 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -42,7 +42,7 @@ typedef struct FFGpuDriverResult uint32_t* coreCount; FFGPUType* type; uint32_t* frequency; - uint8_t* usage; + double* coreUsage; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 181ddc6a67..71b614c638 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -331,6 +331,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->type = FF_GPU_TYPE_INTEGRATED; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 5d158833a2..164e824d89 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -126,11 +126,11 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR if (result.frequency) nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency); - if (result.usage) + if (result.coreUsage) { - nvmlUtilization_t rates; - if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &rates) == NVML_SUCCESS) - *result.usage = (uint8_t) rates.gpu; + nvmlUtilization_t utilization; + if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &utilization) == NVML_SUCCESS) + *result.coreUsage = utilization.gpu; } return NULL; diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index a040adf1f2..168cfaac15 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -59,6 +59,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInit(&gpu->platformApi); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = 0; diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 83c3281da1..9df0ba3a71 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -84,6 +84,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInitStatic(&gpu->platformApi, "Direct3D"); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = 0; @@ -201,6 +202,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, }, diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index 0b9c440d06..6459b281ca 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -71,8 +71,10 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus); ffStrbufInitS(&gpu->name, desc); gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + gpu->deviceId = 0; ffStrbufInitStatic(&gpu->platformApi, "DXCore"); ffStrbufInit(&gpu->driver); @@ -119,6 +121,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 462f3aff20..7da61a23ad 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -81,6 +81,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->deviceId = (size_t) deviceID; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) { diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index e71cfe18f1..dc3b42089e 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -237,6 +237,7 @@ static const char* detectVulkan(FFVulkanResult* result) gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; next: continue; diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 6c89d806a1..0765c8af1c 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -327,6 +327,8 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ else yyjson_mut_obj_add_null(doc, obj, "coreCount"); + yyjson_mut_obj_add_real(doc, obj, "coreUsage", gpu->coreUsage); + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, obj, "memory"); yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); @@ -371,7 +373,7 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi); - yyjson_mut_obj_add_real(doc, obj, "frequency", gpu->frequency); // NaN will be output as "null" + yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency); yyjson_mut_obj_add_uint(doc, obj, "deviceId", gpu->deviceId); } diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 2f69be3bf0..cb29a155e0 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -96,7 +96,7 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson else yyjson_mut_obj_add_null(doc, gpuObj, "coreCount"); - yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency); + yyjson_mut_obj_add_uint(doc, gpuObj, "frequency", gpu->frequency); yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); From d68c4cef13248d337d9f60bde995345e29374649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 14:10:07 +0800 Subject: [PATCH 32/67] GPU (WSL): fix building --- src/detection/gpu/gpu_driver_specific.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 01f3b67a93..5bcf4d2db2 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -40,9 +40,9 @@ typedef struct FFGpuDriverResult double* temp; FFGPUMemory* memory; uint32_t* coreCount; + double* coreUsage; FFGPUType* type; uint32_t* frequency; - double* coreUsage; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); From 114cc753d9e6bdc4b2d3fbf6e0b5b948015d5784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 14:19:24 +0800 Subject: [PATCH 33/67] Option: print error when finding invalid color code Fix #1138 --- src/common/option.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/option.c b/src/common/option.c index a7453cd512..d2f2cd78d1 100644 --- a/src/common/option.c +++ b/src/common/option.c @@ -206,6 +206,11 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer) else FF_APPEND_COLOR_PROP_COND(title, colorTitle) else FF_APPEND_COLOR_PROP_COND(output, colorOutput) else FF_APPEND_COLOR_PROP_COND(separator, colorSeparator) + else + { + fprintf(stderr, "Error: invalid color code found: %s\n", value); + exit(479); + } } ffStrbufAppendC(buffer, *value); ++value; From 104cb43158a339e71c1af1acdf6f577d797c50b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 15:45:53 +0800 Subject: [PATCH 34/67] Wifi: rename `macAddress` to `bssid` --- src/detection/wifi/wifi.h | 2 +- src/detection/wifi/wifi_android.c | 8 ++++---- src/detection/wifi/wifi_apple.m | 6 +++--- src/detection/wifi/wifi_bsd.c | 4 ++-- src/detection/wifi/wifi_linux.c | 10 +++++----- src/detection/wifi/wifi_windows.c | 6 +++--- src/modules/wifi/wifi.c | 8 ++++---- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index 2e292439d4..10b4ffdbc9 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -12,7 +12,7 @@ struct FFWifiConnection { FFstrbuf status; FFstrbuf ssid; - FFstrbuf macAddress; + FFstrbuf bssid; FFstrbuf protocol; FFstrbuf security; double signalQuality; // Percentage diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index e34f45365b..a149892422 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -37,7 +37,7 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; @@ -53,12 +53,12 @@ const char* ffDetectWifi(FFlist* result) if(!ffStrbufEqualS(&item->inf.status, "COMPLETED")) return NULL; - + double rssi = yyjson_get_num(yyjson_obj_get(root, "rssi")); item->conn.signalQuality = rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2; - + ffStrbufAppendS(&item->inf.description, yyjson_get_str(yyjson_obj_get(root, "ip"))); - ffStrbufAppendS(&item->conn.macAddress, yyjson_get_str(yyjson_obj_get(root, "bssid"))); + ffStrbufAppendS(&item->conn.bssid, yyjson_get_str(yyjson_obj_get(root, "bssid"))); ffStrbufAppendS(&item->conn.ssid, yyjson_get_str(yyjson_obj_get(root, "ssid"))); return NULL; diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 8fdb406370..28edee5eb5 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -37,7 +37,7 @@ ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; @@ -63,9 +63,9 @@ ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 if (inf.bssid) - ffStrbufAppendS(&item->conn.macAddress, inf.bssid.UTF8String); + ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String); else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName))) - ffStrbufAppendS(&item->conn.macAddress, [[apple valueForKey:@"BSSID"] UTF8String]); + ffStrbufAppendS(&item->conn.bssid, [[apple valueForKey:@"BSSID"] UTF8String]); switch(inf.activePHYMode) { diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index 66edc10c6f..1f47cf9ef3 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -28,7 +28,7 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; @@ -42,7 +42,7 @@ const char* ffDetectWifi(FFlist* result) if (ibssid < item->conn.ssid.length) { ibssid += (uint32_t) strlen(" bssid "); - ffStrbufSetS(&item->conn.macAddress, item->conn.ssid.chars + ibssid); + ffStrbufSetS(&item->conn.bssid, item->conn.ssid.chars + ibssid); } ffStrbufSubstrBeforeFirstC(&item->conn.ssid, ' '); diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 60e5107919..f85bb264a1 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -75,7 +75,7 @@ static const char* detectWifiWithLibnm(FFlist* result) ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; @@ -143,7 +143,7 @@ static const char* detectWifiWithLibnm(FFlist* result) ffg_free(ssid); } - ffStrbufAppendS(&item->conn.macAddress, ffnm_access_point_get_bssid(ap)); + ffStrbufAppendS(&item->conn.bssid, ffnm_access_point_get_bssid(ap)); item->conn.signalQuality = ffnm_access_point_get_strength(ap); item->conn.rxRate = ffnm_access_point_get_max_bitrate(ap); @@ -242,7 +242,7 @@ static const char* detectWifiWithIoctls(FFlist* result) ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; @@ -281,8 +281,8 @@ static const char* detectWifiWithIoctls(FFlist* result) if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) { for(int i = 0; i < 6; ++i) - ffStrbufAppendF(&item->conn.macAddress, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); - ffStrbufTrimRight(&item->conn.macAddress, '-'); + ffStrbufAppendF(&item->conn.bssid, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); + ffStrbufTrimRight(&item->conn.bssid, '-'); } struct iw_statistics stats; diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 18638c046d..0508a72d44 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -76,7 +76,7 @@ const char* ffDetectWifi(FFlist* result) ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.macAddress); + ffStrbufInit(&item->conn.bssid); ffStrbufInit(&item->conn.protocol); ffStrbufInit(&item->conn.security); item->conn.signalQuality = 0.0/0.0; @@ -107,8 +107,8 @@ const char* ffDetectWifi(FFlist* result) (const char *)connInfo->wlanAssociationAttributes.dot11Ssid.ucSSID); for (size_t i = 0; i < sizeof(connInfo->wlanAssociationAttributes.dot11Bssid); i++) - ffStrbufAppendF(&item->conn.macAddress, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]); - ffStrbufTrimRight(&item->conn.macAddress, '-'); + ffStrbufAppendF(&item->conn.bssid, "%.2X-", connInfo->wlanAssociationAttributes.dot11Bssid[i]); + ffStrbufTrimRight(&item->conn.bssid, '-'); switch (connInfo->wlanAssociationAttributes.dot11PhyType) { diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 18208d3a84..fa2ddb05d9 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -85,7 +85,7 @@ void ffPrintWifi(FFWifiOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &item->inf.status, "inf-status"}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.status, "status"}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.ssid, "ssid"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.macAddress, "mac-address"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.bssid, "bssid"}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->conn.protocol, "protocol"}, {FF_FORMAT_ARG_TYPE_DOUBLE, &percentNum, "signal-quality"}, {FF_FORMAT_ARG_TYPE_DOUBLE, &item->conn.rxRate, "rx-rate"}, @@ -99,7 +99,7 @@ void ffPrintWifi(FFWifiOptions* options) ffStrbufDestroy(&item->inf.status); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); - ffStrbufDestroy(&item->conn.macAddress); + ffStrbufDestroy(&item->conn.bssid); ffStrbufDestroy(&item->conn.protocol); ffStrbufDestroy(&item->conn.security); } @@ -170,7 +170,7 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn"); yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status); yyjson_mut_obj_add_strbuf(doc, conn, "ssid", &wifi->conn.ssid); - yyjson_mut_obj_add_strbuf(doc, conn, "bssid", &wifi->conn.macAddress); + yyjson_mut_obj_add_strbuf(doc, conn, "bssid", &wifi->conn.bssid); yyjson_mut_obj_add_strbuf(doc, conn, "protocol", &wifi->conn.protocol); yyjson_mut_obj_add_strbuf(doc, conn, "security", &wifi->conn.security); yyjson_mut_obj_add_real(doc, conn, "signalQuality", wifi->conn.signalQuality); @@ -184,7 +184,7 @@ void ffGenerateWifiJsonResult(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut ffStrbufDestroy(&item->inf.status); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); - ffStrbufDestroy(&item->conn.macAddress); + ffStrbufDestroy(&item->conn.bssid); ffStrbufDestroy(&item->conn.protocol); ffStrbufDestroy(&item->conn.security); } From 65883766a0d875fa77380f82520a97601fd3c36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 16:02:41 +0800 Subject: [PATCH 35/67] Display (macOS): don't parse string --- .../displayserver/displayserver_apple.c | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 15bba56b5d..53baf70928 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -86,21 +86,15 @@ static void detectDisplays(FFDisplayServerResult* ds) ); if (display) { - // Shitty code - uint8_t bitDepth = 0; - FF_CFTYPE_AUTO_RELEASE CFStringRef desc = CFCopyDescription(mode); - CFRange start = CFStringFind(desc, CFSTR("BitsPerSample = "), 0); - if (start.location != kCFNotFound) + // https://stackoverflow.com/a/33519316/9976392 + // Also shitty, but better than parsing `CFCopyDescription(mode)` + CFDictionaryRef dict = (CFDictionaryRef) *((int64_t *)mode + 2); + if (CFGetTypeID(dict) == CFDictionaryGetTypeID()) { - for (CFIndex idx = start.location + start.length; idx < CFStringGetLength(desc); ++idx) - { - UniChar ch = CFStringGetCharacterAtIndex(desc, idx); - if (!ffCharIsDigit((char) ch)) - break; - bitDepth = (uint8_t) (bitDepth * 10 + (ch - '0')); - } + int32_t bitDepth; + ffCfDictGetInt(dict, kCGDisplayBitsPerSample, &bitDepth); + display->bitDepth = (uint8_t) bitDepth; } - display->bitDepth = bitDepth; } CGDisplayModeRelease(mode); } From dcbfae7f726ba1079fb299aa3541b242d5cd012a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 16:04:37 +0800 Subject: [PATCH 36/67] Wifi (macOS): use private property to fetch ssid --- src/detection/wifi/wifi_apple.m | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 28edee5eb5..55085fda18 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -6,21 +6,17 @@ struct Apple80211; // https://code.google.com/archive/p/iphone-wireless/wikis/Apple80211.wiki // 0 is successful; < 0 is failure -int Apple80211Open(struct Apple80211 **handle) __attribute__((weak_import)); -int Apple80211BindToInterface(struct Apple80211 *handle, CFStringRef interface) __attribute__((weak_import)); int Apple80211GetInfoCopy(struct Apple80211 *handle, CFDictionaryRef *info) __attribute__((weak_import)); -int Apple80211Close(struct Apple80211 *handle) __attribute__((weak_import)); -static NSDictionary* getWifiInfoByApple80211(NSString* ifName) -{ - if (!Apple80211Open || !Apple80211BindToInterface || !Apple80211GetInfoCopy || !Apple80211Close) return NULL; +@interface CWInterface() +@property (readonly) struct Apple80211* device; +@end - struct Apple80211* handle = NULL; - if (Apple80211Open(&handle) < 0) return NULL; - if (Apple80211BindToInterface(handle, (__bridge CFStringRef)ifName) < 0) return NULL; - CFDictionaryRef result; - if (Apple80211GetInfoCopy(handle, &result) < 0) return NULL; - Apple80211Close(handle); +static NSDictionary* getWifiInfoByApple80211(CWInterface* inf) +{ + if (!Apple80211GetInfoCopy) return NULL; + CFDictionaryRef result = NULL; + if (Apple80211GetInfoCopy(inf.device, &result) < 0) return NULL; return CFBridgingRelease(result); } @@ -57,14 +53,14 @@ if (inf.ssid) // https://developer.apple.com/forums/thread/732431 ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); - else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName))) + else if (apple || (apple = getWifiInfoByApple80211(inf))) ffStrbufAppendS(&item->conn.ssid, [[apple valueForKey:@"SSID_STR"] UTF8String]); else ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 if (inf.bssid) ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String); - else if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName))) + else if (apple || (apple = getWifiInfoByApple80211(inf))) ffStrbufAppendS(&item->conn.bssid, [[apple valueForKey:@"BSSID"] UTF8String]); switch(inf.activePHYMode) @@ -152,7 +148,7 @@ break; case kCWSecurityUnknown: // Sonoma... - if (apple || (apple = getWifiInfoByApple80211(inf.interfaceName))) + if (apple || (apple = getWifiInfoByApple80211(inf))) { NSDictionary* authType = [apple valueForKey:@"AUTH_TYPE"]; if (authType) From 812a13c871249dff42c7cd2bc9ea6eb1ad6caa2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 1 Aug 2024 16:41:02 +0800 Subject: [PATCH 37/67] Display (macOS): fix invalid refresh rate in old mac --- src/detection/displayserver/displayserver_apple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 53baf70928..d2e87ecf2a 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -37,7 +37,7 @@ static void detectDisplays(FFDisplayServerResult* ds) { const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); if (!(time.flags & kCVTimeIsIndefinite)) - refreshRate = time.timeScale / (double) time.timeValue + 0.5; //59.97... + refreshRate = time.timeScale / (double) time.timeValue; //59.97... CVDisplayLinkRelease(link); } } From b9fe2fb4dda39f8d5c122e6013187066e28770c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 2 Aug 2024 10:09:19 +0800 Subject: [PATCH 38/67] Logo (Builtin): update endeavour_small --- src/logo/ascii/endeavour_small.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/logo/ascii/endeavour_small.txt b/src/logo/ascii/endeavour_small.txt index 7265f4dead..2bc9e93b0c 100644 --- a/src/logo/ascii/endeavour_small.txt +++ b/src/logo/ascii/endeavour_small.txt @@ -1,7 +1,7 @@ - /${c2}o${c3}. -${c1} :${c2}sssso${c3}- -${c1} :${c2}ossssssso${c3}: -${c1} /${c2}ssssssssssso${c3}+ -${c1} -+${c2}ssssssssssssssso${c3}+ -${c1} //${c2}osssssssssssssso${c3}+- - `+++++++++++++++-` + /${c2}o${c3}. +${c1} /${c2}sssso${c3}- +${c1} /${c2}ossssssso${c3}: +${c1} /${c2}ssssssssssso${c3}+ +${c1} /${c2}ssssssssssssssso${c3}+ +${c1}//${c2}osssssssssssssso${c3}+- + `+++++++++++++++-` From 121e9b911e85afc7c3aee4082155944ead0a68d9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 13:48:02 +0800 Subject: [PATCH 39/67] GPU (Windows): fix bug that assuming pci bus id > 0 --- src/detection/gpu/gpu_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 9df0ba3a71..111aced8eb 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -183,7 +183,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* &(FFGpuDriverCondition) { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | FF_GPU_DRIVER_CONDITION_TYPE_LUID - | (bus > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), + | (bus >= 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), .pciDeviceId = { .deviceId = deviceId, .vendorId = vendorId, From 98fc793386560e6258383ff6f5bffcb04a8d273b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 14:07:04 +0800 Subject: [PATCH 40/67] GPU (Linux): embed part of `asahi_drm.h` code --- src/detection/gpu/gpu_linux.c | 81 ++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 71b614c638..dee3ff961a 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -10,14 +10,83 @@ #include #if __aarch64__ - #if __has_include() && FF_HAVE_DRM - #include + #if FF_HAVE_DRM #include #include #include - #define FF_HAVE_ASAHI_DRM_H 1 - #else - #warning " not available" + + #if !__has_include() + #include + #else + /* SPDX-License-Identifier: MIT */ + /* Copyright (C) The Asahi Linux Contributors */ + #define DRM_ASAHI_GET_PARAMS 0x00 + #define DRM_ASAHI_MAX_CLUSTERS 32 + struct drm_asahi_params_global + { + __u32 unstable_uabi_version; + __u32 pad0; + + __u64 feat_compat; + __u64 feat_incompat; + + __u32 gpu_generation; + __u32 gpu_variant; + __u32 gpu_revision; + __u32 chip_id; + + __u32 num_dies; + __u32 num_clusters_total; + __u32 num_cores_per_cluster; + __u32 num_frags_per_cluster; + __u32 num_gps_per_cluster; + __u32 num_cores_total_active; + __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; + + __u32 vm_page_size; + __u32 pad1; + __u64 vm_user_start; + __u64 vm_user_end; + __u64 vm_shader_start; + __u64 vm_shader_end; + + __u32 max_syncs_per_submission; + __u32 max_commands_per_submission; + __u32 max_commands_in_flight; + __u32 max_attachments; + + __u32 timer_frequency_hz; + __u32 min_frequency_khz; + __u32 max_frequency_khz; + __u32 max_power_mw; + + __u32 result_render_size; + __u32 result_compute_size; + }; + + struct drm_asahi_get_params + { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @param: Parameter group to fetch (MBZ) */ + __u32 param_group; + + /** @pad: MBZ */ + __u32 pad; + + /** @value: User pointer to write parameter struct */ + __u64 pointer; + + /** @value: Size of user buffer, max size supported on return */ + __u64 size; + }; + + enum + { + DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), + }; + #endif #endif #endif @@ -338,7 +407,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F pciDetectDriver(gpu, drmDir, buffer, drmKey); - #if FF_HAVE_ASAHI_DRM_H + #if FF_HAVE_DRM ffStrbufSetS(buffer, "/dev/dri/"); ffStrbufAppendS(buffer, drmKey); FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY); From 08dea9fe21656d33cc1af8611f223149726fa741 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 14:10:07 +0800 Subject: [PATCH 41/67] GPU (Linux): fix compiling oops... --- src/detection/gpu/gpu_linux.c | 144 +++++++++++++++++----------------- 1 file changed, 71 insertions(+), 73 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index dee3ff961a..91ac598eb8 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -9,84 +9,82 @@ #include -#if __aarch64__ - #if FF_HAVE_DRM - #include - #include - #include - - #if !__has_include() - #include - #else - /* SPDX-License-Identifier: MIT */ - /* Copyright (C) The Asahi Linux Contributors */ - #define DRM_ASAHI_GET_PARAMS 0x00 - #define DRM_ASAHI_MAX_CLUSTERS 32 - struct drm_asahi_params_global - { - __u32 unstable_uabi_version; - __u32 pad0; - - __u64 feat_compat; - __u64 feat_incompat; - - __u32 gpu_generation; - __u32 gpu_variant; - __u32 gpu_revision; - __u32 chip_id; - - __u32 num_dies; - __u32 num_clusters_total; - __u32 num_cores_per_cluster; - __u32 num_frags_per_cluster; - __u32 num_gps_per_cluster; - __u32 num_cores_total_active; - __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; - - __u32 vm_page_size; - __u32 pad1; - __u64 vm_user_start; - __u64 vm_user_end; - __u64 vm_shader_start; - __u64 vm_shader_end; - - __u32 max_syncs_per_submission; - __u32 max_commands_per_submission; - __u32 max_commands_in_flight; - __u32 max_attachments; - - __u32 timer_frequency_hz; - __u32 min_frequency_khz; - __u32 max_frequency_khz; - __u32 max_power_mw; - - __u32 result_render_size; - __u32 result_compute_size; - }; - - struct drm_asahi_get_params - { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; +#if __aarch64__ && FF_HAVE_DRM + #include + #include + #include + + #if __has_include() + #include + #else + /* SPDX-License-Identifier: MIT */ + /* Copyright (C) The Asahi Linux Contributors */ + #define DRM_ASAHI_GET_PARAMS 0x00 + #define DRM_ASAHI_MAX_CLUSTERS 32 + struct drm_asahi_params_global + { + __u32 unstable_uabi_version; + __u32 pad0; + + __u64 feat_compat; + __u64 feat_incompat; + + __u32 gpu_generation; + __u32 gpu_variant; + __u32 gpu_revision; + __u32 chip_id; + + __u32 num_dies; + __u32 num_clusters_total; + __u32 num_cores_per_cluster; + __u32 num_frags_per_cluster; + __u32 num_gps_per_cluster; + __u32 num_cores_total_active; + __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; + + __u32 vm_page_size; + __u32 pad1; + __u64 vm_user_start; + __u64 vm_user_end; + __u64 vm_shader_start; + __u64 vm_shader_end; + + __u32 max_syncs_per_submission; + __u32 max_commands_per_submission; + __u32 max_commands_in_flight; + __u32 max_attachments; + + __u32 timer_frequency_hz; + __u32 min_frequency_khz; + __u32 max_frequency_khz; + __u32 max_power_mw; + + __u32 result_render_size; + __u32 result_compute_size; + }; + + struct drm_asahi_get_params + { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; - /** @param: Parameter group to fetch (MBZ) */ - __u32 param_group; + /** @param: Parameter group to fetch (MBZ) */ + __u32 param_group; - /** @pad: MBZ */ - __u32 pad; + /** @pad: MBZ */ + __u32 pad; - /** @value: User pointer to write parameter struct */ - __u64 pointer; + /** @value: User pointer to write parameter struct */ + __u64 pointer; - /** @value: Size of user buffer, max size supported on return */ - __u64 size; - }; + /** @value: Size of user buffer, max size supported on return */ + __u64 size; + }; - enum - { - DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), - }; - #endif + enum + { + DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), + }; #endif #endif From 884fd097c61933bd441ed3ea65c8d3f4797c3bf8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 14:13:33 +0800 Subject: [PATCH 42/67] GPU (Linux): fix compiling (2) --- src/detection/gpu/gpu_linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 91ac598eb8..b132d282ad 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -384,6 +384,8 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf return NULL; } +#if __aarch64__ + FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) { uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t"); @@ -427,6 +429,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F return NULL; } +#endif static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) { From dccbdba24212dc53e36bf401b49a18b4a3063fd4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 15:10:04 +0800 Subject: [PATCH 43/67] Wifi (Linux): remove libnm dependency --- src/detection/wifi/wifi_linux.c | 423 +++++++++++--------------------- 1 file changed, 137 insertions(+), 286 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index f85bb264a1..137b818165 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,217 +1,67 @@ #include "wifi.h" +#include "common/processing.h" +#include "common/properties.h" #include "util/stringUtils.h" #include #include -#ifdef FF_HAVE_LIBNM - -#include "common/processing.h" -#include "common/properties.h" -#include "common/library.h" - -#include -#define NM_NO_INCLUDE_EXTRA_HEADERS 1 -#include - -//https://developer-old.gnome.org/libnm/stable/libnm-nm-dbus-interface.html -#ifndef NM_VERSION_1_26 - #define NM_802_11_AP_SEC_KEY_MGMT_OWE 0x00000800 - #define NM_802_11_AP_SEC_KEY_MGMT_OWE_TM 0x00001000 -#endif - -static const char* detectWifiWithLibnm(FFlist* result) +static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) { - FF_LIBRARY_LOAD(nm, &instance.config.library.libnm, "dlopen libnm failed", "libnm" FF_LIBRARY_EXTENSION, 0); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_new); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_client_get_devices); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_iface); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_get_state); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_type); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_device_wifi_get_active_access_point); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_ssid); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_utils_ssid_to_utf8); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_bssid); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_strength); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_max_bitrate); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_flags); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_wpa_flags); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, nm_access_point_get_rsn_flags); - - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_type_check_instance_is_a); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_size); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_bytes_get_data); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_free); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(nm, g_object_unref); - - NMClient* client = ffnm_client_new(NULL, NULL); - if(!client) - return "Could not create NMClient"; - - /* Get all devices managed by NetworkManager */ - const GPtrArray* devices = ffnm_client_get_devices(client); - - /* Go through the array and process Wi-Fi devices */ - for (guint i = 0; i < devices->len; i++) + const char* error = NULL; + FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); + if((error = ffProcessAppendStdOut(&output, (char* const[]){ + "iw", + "dev", + item->inf.description.chars, + "link", + NULL + }))) + return error; + + if(output.length == 0) + return "iw command execution failed"; + + if(!ffParsePropLines(output.chars, "Connected to ", &item->conn.bssid)) { - NMDevice *device = g_ptr_array_index(devices, i); - if (!({ - GTypeInstance *inst = (GTypeInstance*) device; - GType type = ffnm_device_wifi_get_type(); - gboolean return_value; - if (!inst) - return_value = FALSE; - else if (inst->g_class && inst->g_class->g_type == type) - return_value = TRUE; - else - return_value = ffg_type_check_instance_is_a (inst, type); - return_value; - }) //NM_IS_DEVICE_WIFI(device) - ) - continue; - - FFWifiResult* item = (FFWifiResult*) ffListAdd(result); - ffStrbufInit(&item->inf.description); - ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->conn.status); - ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.bssid); - ffStrbufInit(&item->conn.protocol); - ffStrbufInit(&item->conn.security); - item->conn.signalQuality = 0.0/0.0; - item->conn.rxRate = 0.0/0.0; - item->conn.txRate = 0.0/0.0; + ffStrbufAppendS(&item->conn.status, "disconnected"); + return NULL; + } - ffStrbufAppendS(&item->inf.description, ffnm_device_get_iface(device)); - NMDeviceState state = ffnm_device_get_state(device); - switch(state) - { - case NM_DEVICE_STATE_UNKNOWN: - ffStrbufSetStatic(&item->inf.status, "Unknown"); - break; - case NM_DEVICE_STATE_UNMANAGED: - ffStrbufSetStatic(&item->inf.status, "Unmanaged"); - break; - case NM_DEVICE_STATE_UNAVAILABLE: - ffStrbufSetStatic(&item->inf.status, "Unavailable"); - break; - case NM_DEVICE_STATE_DISCONNECTED: - ffStrbufSetStatic(&item->inf.status, "Disconnected"); - break; - case NM_DEVICE_STATE_PREPARE: - ffStrbufSetStatic(&item->inf.status, "Prepare"); - break; - case NM_DEVICE_STATE_CONFIG: - ffStrbufSetStatic(&item->inf.status, "Config"); - break; - case NM_DEVICE_STATE_NEED_AUTH: - ffStrbufSetStatic(&item->inf.status, "Need auth"); - break; - case NM_DEVICE_STATE_IP_CONFIG: - ffStrbufSetStatic(&item->inf.status, "IP config"); - break; - case NM_DEVICE_STATE_IP_CHECK: - ffStrbufSetStatic(&item->inf.status, "IP check"); - break; - case NM_DEVICE_STATE_SECONDARIES: - ffStrbufSetStatic(&item->inf.status, "Secondaries"); - break; - case NM_DEVICE_STATE_ACTIVATED: - ffStrbufSetStatic(&item->inf.status, "Activated"); - break; - case NM_DEVICE_STATE_DEACTIVATING: - ffStrbufSetStatic(&item->inf.status, "Deactivating"); - break; - case NM_DEVICE_STATE_FAILED: - ffStrbufSetStatic(&item->inf.status, "Failed"); - break; - } - if(state != NM_DEVICE_STATE_ACTIVATED) - continue; - NMAccessPoint* ap = ffnm_device_wifi_get_active_access_point((NMDeviceWifi *) device); - if (!ap) - continue; + ffStrbufAppendS(&item->conn.status, "connected"); + ffStrbufSubstrBeforeFirstC(&item->conn.bssid, ' '); - ffStrbufSetStatic(&item->conn.status, "Connected"); + ffParsePropLines(output.chars, "SSID: ", &item->conn.ssid); - GBytes* activeSsid = ffnm_access_point_get_ssid(ap); - if (activeSsid) - { - char* ssid = ffnm_utils_ssid_to_utf8(ffg_bytes_get_data(activeSsid, NULL), ffg_bytes_get_size(activeSsid)); - ffStrbufAppendS(&item->conn.ssid, ssid); - ffg_free(ssid); - } + ffStrbufClear(buffer); + if(ffParsePropLines(output.chars, "signal: ", buffer)) + { + int level = (int) ffStrbufToSInt(buffer, INT_MAX); + if (level != INT_MAX) + item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2; + } - ffStrbufAppendS(&item->conn.bssid, ffnm_access_point_get_bssid(ap)); - item->conn.signalQuality = ffnm_access_point_get_strength(ap); - item->conn.rxRate = ffnm_access_point_get_max_bitrate(ap); - - FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); - if(!ffProcessAppendStdOut(&output, (char* const[]){ - "iw", - "dev", - item->inf.description.chars, - "link", - NULL - })) - { - if(ffParsePropLines(output.chars, "rx bitrate: ", &item->conn.protocol)) - { - sscanf(item->conn.protocol.chars, "%lf", &item->conn.rxRate); - } - if(ffParsePropLines(output.chars, "tx bitrate: ", &item->conn.protocol)) - { - if(ffStrbufContainS(&item->conn.protocol, " HE-MCS ")) - ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); - else if(ffStrbufContainS(&item->conn.protocol, " VHT-MCS ")) - ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); - else if(ffStrbufContainS(&item->conn.protocol, " MCS ")) - ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); - else - ffStrbufClear(&item->conn.protocol); - - sscanf(item->conn.protocol.chars, "%lf", &item->conn.txRate); - } - } + ffStrbufClear(buffer); + if(ffParsePropLines(output.chars, "rx bitrate: ", buffer)) + item->conn.rxRate = ffStrbufToDouble(buffer); - NM80211ApFlags flags = ffnm_access_point_get_flags(ap); - NM80211ApSecurityFlags wpaFlags = ffnm_access_point_get_wpa_flags(ap); - NM80211ApSecurityFlags rsnFlags = ffnm_access_point_get_rsn_flags(ap); - - if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) - && (rsnFlags == NM_802_11_AP_SEC_NONE)) - ffStrbufAppendS(&item->conn.security, "WEP/"); - if (wpaFlags != NM_802_11_AP_SEC_NONE) - ffStrbufAppendS(&item->conn.security, "WPA/"); - if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) - || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { - ffStrbufAppendS(&item->conn.security, "WPA2/"); - } - if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) { - ffStrbufAppendS(&item->conn.security, "WPA3/"); - } - if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) - || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { - ffStrbufAppendS(&item->conn.security, "OWE/"); - } - if ((wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) - || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { - ffStrbufAppendS(&item->conn.security, "802.1X/"); - } - if (!item->conn.security.length) - ffStrbufAppendS(&item->conn.security, "Insecure"); - else - ffStrbufTrimRight(&item->conn.security, '/'); + ffStrbufClear(buffer); + if(ffParsePropLines(output.chars, "tx bitrate: ", buffer)) + { + item->conn.txRate = ffStrbufToDouble(buffer); + + if(ffStrbufContainS(buffer, " HE-MCS ")) + ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); + else if(ffStrbufContainS(buffer, " VHT-MCS ")) + ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); + else if(ffStrbufContainS(buffer, " MCS ")) + ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); } - ffg_object_unref(client); - return NULL; } -#endif - #if FF_HAVE_LINUX_WIRELESS #define FF_DETECT_WIFI_WITH_IOCTLS @@ -221,20 +71,97 @@ static const char* detectWifiWithLibnm(FFlist* result) #include #include #include -#include //TODO: Don't depend on kernel headers +#include + +static const char* detectWifiWithIoctls(FFWifiResult* item) +{ + FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if(sock < 0) + return "socket() failed"; + + struct iwreq iwr; + strncpy(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ); + ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE); + iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars; + iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; + iwr.u.essid.flags = 0; + if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0) + ffStrbufRecalculateLength(&item->conn.ssid); + + if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11")) + { + if(ffStrStartsWithIgnCase(iwr.u.name, "IEEE ")) + ffStrbufSetS(&item->conn.protocol, iwr.u.name + strlen("IEEE ")); + else + ffStrbufSetS(&item->conn.protocol, iwr.u.name); + } + + if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) + { + for(int i = 0; i < 6; ++i) + ffStrbufAppendF(&item->conn.bssid, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); + ffStrbufTrimRight(&item->conn.bssid, '-'); + } + + struct iw_statistics stats; + iwr.u.data.pointer = &stats; + iwr.u.data.length = sizeof(stats); + iwr.u.data.flags = 0; + + if(ioctl(sock, SIOCGIWSTATS, &iwr) >= 0) + { + int8_t level = (int8_t) stats.qual.level; // https://stackoverflow.com/questions/18079771/wireless-h-how-do-i-print-out-the-signal-level + item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2; + } + + //FIXME: doesn't work + struct iw_encode_ext iwe; + iwr.u.data.pointer = &iwe; + iwr.u.data.length = sizeof(iwe); + iwr.u.data.flags = 0; + if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0) + { + switch(iwe.alg) + { + case IW_ENCODE_ALG_WEP: + ffStrbufAppendS(&item->conn.security, "WEP"); + break; + case IW_ENCODE_ALG_TKIP: + ffStrbufAppendS(&item->conn.security, "TKIP"); + break; + case IW_ENCODE_ALG_CCMP: + ffStrbufAppendS(&item->conn.security, "CCMP"); + break; + case IW_ENCODE_ALG_PMK: + ffStrbufAppendS(&item->conn.security, "PMK"); + break; + case IW_ENCODE_ALG_AES_CMAC: + ffStrbufAppendS(&item->conn.security, "CMAC"); + break; + default: + ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe.alg); + break; + } + } + + return NULL; +} -static const char* detectWifiWithIoctls(FFlist* result) +#endif + +const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) { struct if_nameindex* infs = if_nameindex(); if(!infs) return "if_nameindex() failed"; - FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + const char* error = NULL; for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i) { - ffStrbufSetF(&path, "/sys/class/net/%s/phy80211", i->if_name); - if(!ffPathExists(path.chars, FF_PATHTYPE_DIRECTORY)) + ffStrbufSetF(&buffer, "/sys/class/net/%s/phy80211", i->if_name); + if(!ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY)) continue; FFWifiResult* item = (FFWifiResult*)ffListAdd(result); @@ -249,102 +176,26 @@ static const char* detectWifiWithIoctls(FFlist* result) item->conn.rxRate = 0.0/0.0; item->conn.txRate = 0.0/0.0; - ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name); - if (!ffAppendFileBuffer(path.chars, &item->inf.status)) + ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name); + if (!ffAppendFileBuffer(buffer.chars, &item->inf.status)) continue; ffStrbufTrimRightSpace(&item->inf.status); if (!ffStrbufEqualS(&item->inf.status, "up")) continue; - FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if(sock < 0) + if (detectWifiWithIw(item, &buffer) == NULL) continue; - struct iwreq iwr; - strncpy(iwr.ifr_name, i->if_name, IFNAMSIZ); - ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE); - iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars; - iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; - iwr.u.essid.flags = 0; - if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0) - ffStrbufRecalculateLength(&item->conn.ssid); - - if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11")) - { - if(ffStrStartsWithIgnCase(iwr.u.name, "IEEE ")) - ffStrbufSetS(&item->conn.protocol, iwr.u.name + strlen("IEEE ")); - else - ffStrbufSetS(&item->conn.protocol, iwr.u.name); - } - - if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) - { - for(int i = 0; i < 6; ++i) - ffStrbufAppendF(&item->conn.bssid, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); - ffStrbufTrimRight(&item->conn.bssid, '-'); - } - - struct iw_statistics stats; - iwr.u.data.pointer = &stats; - iwr.u.data.length = sizeof(stats); - iwr.u.data.flags = 0; - - if(ioctl(sock, SIOCGIWSTATS, &iwr) >= 0) - { - int8_t level = (int8_t) stats.qual.level; // https://stackoverflow.com/questions/18079771/wireless-h-how-do-i-print-out-the-signal-level - item->conn.signalQuality = level >= -50 ? 100 : level <= -100 ? 0 : (level + 100) * 2; - } + #ifdef FF_DETECT_WIFI_WITH_IOCTLS + detectWifiWithIoctls(item); + continue; + #endif - //FIXME: doesn't work - struct iw_encode_ext iwe; - iwr.u.data.pointer = &iwe; - iwr.u.data.length = sizeof(iwe); - iwr.u.data.flags = 0; - if(ioctl(sock, SIOCGIWENCODEEXT, &iwr) >= 0) - { - struct iw_encode_ext* iwe = iwr.u.data.pointer; - switch(iwe->alg) - { - case IW_ENCODE_ALG_WEP: - ffStrbufAppendS(&item->conn.security, "WEP"); - break; - case IW_ENCODE_ALG_TKIP: - ffStrbufAppendS(&item->conn.security, "TKIP"); - break; - case IW_ENCODE_ALG_CCMP: - ffStrbufAppendS(&item->conn.security, "CCMP"); - break; - case IW_ENCODE_ALG_PMK: - ffStrbufAppendS(&item->conn.security, "PMK"); - break; - case IW_ENCODE_ALG_AES_CMAC: - ffStrbufAppendS(&item->conn.security, "CMAC"); - break; - default: - ffStrbufAppendF(&item->conn.security, "Unknown (%d)", (int) iwe->alg); - break; - } - } + error = "`iw` failed and `linux/wireless.h` not found during compilation"; + break; } if_freenameindex(infs); - return NULL; -} - -#endif - -const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) -{ - #ifdef FF_HAVE_LIBNM - detectWifiWithLibnm(result); - if(result->length) // NetworkManager not enabled? #811 - return NULL; - #endif - - #ifdef FF_DETECT_WIFI_WITH_IOCTLS - return detectWifiWithIoctls(result); - #endif - - return "linux/wireless.h not found during compilation"; + return error; } From b111626fe9b98d71386eadbe1b716a4dd5f1dcbf Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 15:21:42 +0800 Subject: [PATCH 44/67] GPU (Linux): use the device name that driver provides --- src/detection/gpu/gpu_bsd.c | 1 + src/detection/gpu/gpu_driver_specific.h | 1 + src/detection/gpu/gpu_linux.c | 1 + src/detection/gpu/gpu_nvidia.c | 9 +++++++++ src/detection/gpu/gpu_wsl.cpp | 1 + src/detection/gpu/nvml.h | 3 +++ 6 files changed, 16 insertions(+) diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 87abb0630d..379f5afa43 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -94,6 +94,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) .type = &gpu->type, .frequency = &gpu->frequency, .coreUsage = &gpu->coreUsage, + .name = options->driverSpecific ? &gpu->name : NULL, }, "libnvidia-ml.so"); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 5bcf4d2db2..8a1623455c 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -43,6 +43,7 @@ typedef struct FFGpuDriverResult double* coreUsage; FFGPUType* type; uint32_t* frequency; + FFstrbuf* name; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index b132d282ad..fba9f60f6b 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -369,6 +369,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .name = options->driverSpecific ? &gpu->name : NULL, }, "libnvidia-ml.so"); } diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 164e824d89..42ed09d91a 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -14,6 +14,7 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo) FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates) FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand) + FF_LIBRARY_SYMBOL(nvmlDeviceGetName) bool inited; } nvmlData; @@ -38,6 +39,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetName) if (ffnvmlInit_v2() != NVML_SUCCESS) { @@ -133,6 +135,13 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR *result.coreUsage = utilization.gpu; } + if (result.name) + { + char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE]; + if (nvmlData.ffnvmlDeviceGetName(device, name, sizeof(name)) == NVML_SUCCESS) + ffStrbufSetS(result.name, name); + } + return NULL; #else diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index 6459b281ca..152b7dba08 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -124,6 +124,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .name = options->driverSpecific ? &gpu->name : NULL, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); } } diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index d3f1904b09..fd10d651fe 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -7,6 +7,7 @@ // https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceStructs.html #define NVML_DEVICE_PCI_BUS_ID_BUFFER_SIZE 32 #define NVML_DEVICE_PCI_BUS_ID_BUFFER_V2_SIZE 16 +#define NVML_DEVICE_NAME_V2_BUFFER_SIZE 96 typedef enum { NVML_SUCCESS = 0 } nvmlReturn_t; typedef struct nvmlDevice_t* nvmlDevice_t; @@ -131,3 +132,5 @@ extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type); // Retrieves the current utilization rates for the device extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization); +// Retrieves the name of this device. +extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length); From 45659854d2202e56746d38048e0756bb69356d7f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 15:24:29 +0800 Subject: [PATCH 45/67] GPU (Linux): don't ignore disabled GPU Should fix #1140 --- src/detection/gpu/gpu_linux.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index fba9f60f6b..a8e73ab709 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -284,14 +284,6 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4) return "Invalid PCI device path"; - ffStrbufAppendS(deviceDir, "/enable"); - if (ffReadFileBuffer(deviceDir->chars, buffer)) - { - if (!ffStrbufStartsWithC(buffer, '1')) - return "GPU disabled"; - } - ffStrbufSubstrBefore(deviceDir, drmDirPathLength); - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId)); ffStrbufInit(&gpu->name); From d96d794d1f6cf4b194e85a6d67a9d6f78fef7563 Mon Sep 17 00:00:00 2001 From: R0CKSTAR Date: Fri, 2 Aug 2024 16:00:54 +0800 Subject: [PATCH 46/67] GPU (Linux): Support Moore Threads GPU (#1142) * feat: Support Moore Threads GPU Signed-off-by: Xiaodong Ye * Fix spell check Signed-off-by: Xiaodong Ye * Fix frequency and add back util Signed-off-by: Xiaodong Ye * Add name field Signed-off-by: Xiaodong Ye --------- Signed-off-by: Xiaodong Ye --- CMakeLists.txt | 3 + src/detection/gpu/gpu.c | 4 + src/detection/gpu/gpu.h | 1 + src/detection/gpu/gpu_driver_specific.h | 1 + src/detection/gpu/gpu_linux.c | 23 +++ src/detection/gpu/gpu_mthreads.c | 191 ++++++++++++++++++++++++ src/detection/gpu/mtml.h | 116 ++++++++++++++ 7 files changed, 339 insertions(+) create mode 100644 src/detection/gpu/gpu_mthreads.c create mode 100644 src/detection/gpu/mtml.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 319bc18e77..9af2b04414 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -843,6 +843,9 @@ if(WIN32) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c) endif() +if(LINUX) + list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_mthreads.c) +endif() include(CheckFunctionExists) check_function_exists(wcwidth HAVE_WCWIDTH) diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index fee845022c..d1831f92a9 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -7,6 +7,7 @@ const char* FF_GPU_VENDOR_NAME_APPLE = "Apple"; const char* FF_GPU_VENDOR_NAME_AMD = "AMD"; const char* FF_GPU_VENDOR_NAME_INTEL = "Intel"; const char* FF_GPU_VENDOR_NAME_NVIDIA = "NVIDIA"; +const char* FF_GPU_VENDOR_NAME_MTHREADS = "Moore Threads"; const char* FF_GPU_VENDOR_NAME_QUALCOMM = "Qualcomm"; const char* FF_GPU_VENDOR_NAME_MTK = "MTK"; const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware"; @@ -24,6 +25,7 @@ const char* ffGetGPUVendorString(unsigned vendorId) case 0x1002: case 0x1022: return FF_GPU_VENDOR_NAME_AMD; case 0x8086: case 0x8087: case 0x03e7: return FF_GPU_VENDOR_NAME_INTEL; case 0x0955: case 0x10de: case 0x12d2: return FF_GPU_VENDOR_NAME_NVIDIA; + case 0x1ed5: return FF_GPU_VENDOR_NAME_MTHREADS; case 0x5143: return FF_GPU_VENDOR_NAME_QUALCOMM; case 0x14c3: return FF_GPU_VENDOR_NAME_MTK; case 0x15ad: return FF_GPU_VENDOR_NAME_VMWARE; @@ -71,6 +73,8 @@ const char* detectByOpenGL(FFlist* gpus) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); else if (ffStrbufContainS(&gpu->name, "NVIDIA")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if (ffStrbufContainS(&gpu->name, "MTT")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS); } diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index ffa82d0cac..6e999d6ee2 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -12,6 +12,7 @@ extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; extern const char* FF_GPU_VENDOR_NAME_INTEL; extern const char* FF_GPU_VENDOR_NAME_NVIDIA; +extern const char* FF_GPU_VENDOR_NAME_MTHREADS; extern const char* FF_GPU_VENDOR_NAME_VMWARE; extern const char* FF_GPU_VENDOR_NAME_PARALLEL; extern const char* FF_GPU_VENDOR_NAME_MICROSOFT; diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 8a1623455c..7b1ec74234 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -49,3 +49,4 @@ typedef struct FFGpuDriverResult const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); +const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index a8e73ab709..5c564c0da5 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -373,6 +373,29 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf gpu->type = FF_GPU_TYPE_DISCRETE; } } + else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) + { + if (options->temp || options->driverSpecific) + { + ffDetectMthreadsGpuInfo(&(FFGpuDriverCondition){ + .type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, + .pciBusId = { + .domain = pciDomain, + .bus = pciBus, + .device = pciDevice, + .func = pciFunc, + }, + }, + (FFGpuDriverResult){ + .temp = options->temp ? &gpu->temperature : NULL, + .memory = options->driverSpecific ? &gpu->dedicated : NULL, + .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .type = &gpu->type, + .frequency = options->driverSpecific ? &gpu->frequency : NULL, + }, + "libmtml.so"); + } + } return NULL; } diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c new file mode 100644 index 0000000000..edddd220b2 --- /dev/null +++ b/src/detection/gpu/gpu_mthreads.c @@ -0,0 +1,191 @@ +#include "gpu_driver_specific.h" + +#include "common/library.h" +#include "mtml.h" + +struct FFMtmlData +{ + FF_LIBRARY_SYMBOL(mtmlDeviceGetBrand) + FF_LIBRARY_SYMBOL(mtmlDeviceGetIndex) + FF_LIBRARY_SYMBOL(mtmlDeviceGetName) + FF_LIBRARY_SYMBOL(mtmlDeviceGetPciInfo) + FF_LIBRARY_SYMBOL(mtmlDeviceGetUUID) + FF_LIBRARY_SYMBOL(mtmlDeviceInitGpu) + FF_LIBRARY_SYMBOL(mtmlDeviceInitMemory) + FF_LIBRARY_SYMBOL(mtmlGpuGetMaxClock) + FF_LIBRARY_SYMBOL(mtmlGpuGetTemperature) + FF_LIBRARY_SYMBOL(mtmlGpuGetUtilization) + FF_LIBRARY_SYMBOL(mtmlLibraryCountDevice) + FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByIndex) + FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByPciSbdf) + FF_LIBRARY_SYMBOL(mtmlLibraryInitSystem) + FF_LIBRARY_SYMBOL(mtmlMemoryGetTotal) + FF_LIBRARY_SYMBOL(mtmlMemoryGetUsed) + FF_LIBRARY_SYMBOL(mtmlMemoryGetUtilization) + + bool inited; + MtmlLibrary *lib; + MtmlSystem *sys; +} mtmlData; + +const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDriverResult result, const char *soName) +{ +#ifndef FF_DISABLE_DLOPEN + + if (!mtmlData.inited) + { + mtmlData.inited = true; + FF_LIBRARY_LOAD(libmtml, NULL, "dlopen mtml failed", soName, 1); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryInit) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryShutDown) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetBrand) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetIndex) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetName) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetPciInfo) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetUUID) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitGpu) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitMemory) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetMaxClock) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetTemperature) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetUtilization) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryCountDevice) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByIndex) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByPciSbdf) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitSystem) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetTotal) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUsed) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUtilization) + + if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS) + { + mtmlData.ffmtmlLibraryInitSystem = NULL; + return "mtmlLibraryInit failed"; + } + if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS) + { + mtmlData.ffmtmlLibraryInitSystem = NULL; + return "mtmlLibraryInitSystem failed"; + } + atexit((void *)ffmtmlLibraryShutDown); + libmtml = NULL; // don't close mtml + } + + if (mtmlData.ffmtmlLibraryInitSystem == NULL) + return "loading mtml library failed"; + + MtmlDevice *device = NULL; + if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) + { + char pciBusIdStr[32]; + snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func); + + MtmlReturn ret = mtmlData.ffmtmlLibraryInitDeviceByPciSbdf(mtmlData.lib, pciBusIdStr, &device); + if (ret != MTML_SUCCESS) + return "mtmlLibraryInitDeviceByPciSbdf() failed"; + } + else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) + { + uint32_t count; + if (mtmlData.ffmtmlLibraryCountDevice(mtmlData.lib, &count) != MTML_SUCCESS) + return "mtmlLibraryCountDevice() failed"; + + for (uint32_t i = 0; i < count; i++, device = NULL) + { + if (mtmlData.ffmtmlLibraryInitDeviceByIndex(mtmlData.lib, i, &device) != MTML_SUCCESS) + continue; + + MtmlPciInfo pciInfo; + if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) != MTML_SUCCESS) + continue; + + if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) || + pciInfo.pciSubsystemId != cond->pciDeviceId.subSystemId) + continue; + + break; + } + if (!device) + return "Device not found"; + } + else + { + return "Unknown condition type"; + } + + MtmlBrandType brand; + if (mtmlData.ffmtmlDeviceGetBrand(device, &brand) == MTML_SUCCESS) + { + switch (brand) + { + case MTML_BRAND_MTT: + *result.type = FF_GPU_TYPE_DISCRETE; + break; + default: + break; + } + } + + if (result.temp) + { + MtmlGpu *gpu = NULL; + if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) + { + uint32_t value; + if (mtmlData.ffmtmlGpuGetTemperature(gpu, &value) == MTML_SUCCESS) + *result.temp = value; + } + } + + if (result.memory) + { + MtmlMemory *mem = NULL; + if (mtmlData.ffmtmlDeviceInitMemory(device, &mem) == MTML_SUCCESS) + { + unsigned long long total; + if (mtmlData.ffmtmlMemoryGetTotal(mem, &total) == MTML_SUCCESS) + result.memory->total = total; + + unsigned long long used; + if (mtmlData.ffmtmlMemoryGetUsed(mem, &used) == MTML_SUCCESS) + result.memory->used = used; + } + } + + if (result.frequency) + { + MtmlGpu *gpu = NULL; + if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) + { + uint32_t clockMHz; + if (mtmlData.ffmtmlGpuGetMaxClock(gpu, &clockMHz) == MTML_SUCCESS) + *result.frequency = clockMHz; + } + } + + if (result.coreUsage) + { + MtmlGpu *gpu = NULL; + if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) + { + unsigned int utilization; + if (mtmlData.ffmtmlGpuGetUtilization(gpu, &utilization) == MTML_SUCCESS) + *result.coreUsage = utilization; + } + } + + if (result.name) + { + char name[MTML_DEVICE_NAME_BUFFER_SIZE]; + if (mtmlData.ffmtmlDeviceGetName(device, name, sizeof(name)) == MTML_SUCCESS) + ffStrbufSetS(result.name, name); + } + + return NULL; + +#else + + FF_UNUSED(cond, result, soName); + return "dlopen is disabled"; + +#endif +} diff --git a/src/detection/gpu/mtml.h b/src/detection/gpu/mtml.h new file mode 100644 index 0000000000..be5a6cee5f --- /dev/null +++ b/src/detection/gpu/mtml.h @@ -0,0 +1,116 @@ +#pragma once + +// DISCLAIMER: +// THIS FILE IS CREATED FROM SCRATCH, BY READING THE OFFICIAL MTML API +// DOCUMENTATION REFERENCED BELOW, IN ORDER TO MAKE FASTFETCH MIT COMPLIANT. + +#define MTML_API __attribute__((visibility("default"))) +#define MTML_DEVICE_PCI_SBDF_BUFFER_SIZE 32 +#define MTML_DEVICE_NAME_BUFFER_SIZE 32 +#define MTML_DEVICE_UUID_BUFFER_SIZE 48 + +/** + * Return values for MTML API calls. + */ +typedef enum +{ + MTML_SUCCESS = 0, +} MtmlReturn; + +/** + * The brand of the device. + */ +typedef enum +{ + MTML_BRAND_MTT = 0, //!< MTT series. + MTML_BRAND_UNKNOWN, //!< An unknown brand. + + // Keep this on the last line. + MTML_BRAND_COUNT //!< The number of brands. +} MtmlBrandType; + +typedef struct MtmlLibrary MtmlLibrary; +typedef struct MtmlSystem MtmlSystem; +typedef struct MtmlDevice MtmlDevice; +typedef struct MtmlGpu MtmlGpu; +typedef struct MtmlMemory MtmlMemory; + +/** + * PCI information about a device. + */ +typedef struct +{ + char sbdf[MTML_DEVICE_PCI_SBDF_BUFFER_SIZE]; //!< The tuple segment:bus:device.function PCI identifier (& NULL terminator). + unsigned int segment; //!< The PCI segment group(domain) on which the device's bus resides, 0 to 0xffffffff. + unsigned int bus; //!< The bus on which the device resides, 0 to 0xff. + unsigned int device; //!< The device ID on the bus, 0 to 31. + unsigned int pciDeviceId; //!< The combined 16-bit device ID and 16-bit vendor ID. + unsigned int pciSubsystemId; //!< The 32-bit sub system device ID. + unsigned int busWidth; //!< @deprecated This value set to zero. + float pciMaxSpeed; //!< The maximum link speed (transfer rate per lane) of the device. The unit is GT/s. + float pciCurSpeed; //!< The current link speed (transfer rate per lane) of the device. The unit is GT/s. + unsigned int pciMaxWidth; //!< The maximum link width of the device. + unsigned int pciCurWidth; //!< The current link width of the device. + unsigned int pciMaxGen; //!< The maximum supported generation of the device. + unsigned int pciCurGen; //!< The current generation of the device. + int rsvd[6]; //!< Reserved for future extension. +} MtmlPciInfo; + +// Retrieves the brand of a device. +MtmlReturn MTML_API mtmlDeviceGetBrand(const MtmlDevice *dev, MtmlBrandType *type); +// Retrieves the index associated with the specified device. +MtmlReturn MTML_API mtmlDeviceGetIndex(const MtmlDevice *dev, unsigned int *index); +// Retrieves the name of a device. +MtmlReturn MTML_API mtmlDeviceGetName(const MtmlDevice *dev, char *name, unsigned int length); +// Retrieves the PCI attributes of a device. +MtmlReturn MTML_API mtmlDeviceGetPciInfo(const MtmlDevice *dev, MtmlPciInfo *pci); +/** + * Retrieves the UUID of a specified device. The UUID is a hexadecimal string in the + * form of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where each 'x' is an ASCII character that represents a hexadecimal + * digit. The UUID is globally unique for every single device thus can be used to identify different devices + * physically. + */ +MtmlReturn MTML_API mtmlDeviceGetUUID(const MtmlDevice *dev, char *uuid, unsigned int length); +// Initializes a GPU opaque object to represent a specific graphic core on the target device that is designated by its index. +MtmlReturn MTML_API mtmlDeviceInitGpu(const MtmlDevice *dev, MtmlGpu **gpu); +// Initializes a memory opaque object to represent the memory on the target device. +MtmlReturn MTML_API mtmlDeviceInitMemory(const MtmlDevice *dev, MtmlMemory **mem); + +// Retrieves the maximum supported clock speed for the device's graphic core. +MtmlReturn MTML_API mtmlGpuGetMaxClock(const MtmlGpu *gpu, unsigned int *clockMhz); +// Retrieves the current temperature readings for the device's graphic core, in degrees Celsius. +MtmlReturn MTML_API mtmlGpuGetTemperature(const MtmlGpu *gpu, unsigned int *temp); +// Retrieves the current utilization rate for the device's graphic core. +MtmlReturn MTML_API mtmlGpuGetUtilization(const MtmlGpu *gpu, unsigned int *utilization); + +// Retrieves the number of devices that can be accessed by the library opaque object. +MtmlReturn MTML_API mtmlLibraryCountDevice(const MtmlLibrary *lib, unsigned int *count); +/** + * Initializes a device opaque object to represent a device that is designated by its index. + * The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice(). + */ +MtmlReturn MTML_API mtmlLibraryInit(MtmlLibrary **lib); +/** + * Initializes a device opaque object to represent a device that is designated by its index. + * The index ranges from (0) to (deviceCount - 1), where deviceCount is retrieved from \ref mtmlLibraryCountDevice(). + */ +MtmlReturn MTML_API mtmlLibraryInitDeviceByIndex(const MtmlLibrary *lib, unsigned int index, MtmlDevice **dev); +/** + * Initializes a device opaque object to represent a device that is designated by its PCI Sbdf. + * The PCI Sbdf format like 00000000:3a:00.0 refer to \ref MtmlPciInfo::sbdf. + */ +MtmlReturn MTML_API mtmlLibraryInitDeviceByPciSbdf(const MtmlLibrary *lib, const char *pciSbdf, MtmlDevice **dev); +// Initializes a MtmlSystem opaque pointer that is bound to a library opaque object. +MtmlReturn MTML_API mtmlLibraryInitSystem(const MtmlLibrary *lib, MtmlSystem **sys); +/** + * Shuts down the library opaque object that is previously initialized by \ref mtmlLibraryInit() and releases its resources. + * The \a lib pointer cannot be used anymore after this function returns. + */ +MtmlReturn MTML_API mtmlLibraryShutDown(MtmlLibrary *lib); + +// Retrieves the amount of total memory available on the device, in bytes. +MtmlReturn MTML_API mtmlMemoryGetTotal(const MtmlMemory *mem, unsigned long long *total); +// Retrieves the amount of used memory on the device, in bytes. +MtmlReturn MTML_API mtmlMemoryGetUsed(const MtmlMemory *mem, unsigned long long *used); +// Retrieves the current memory utilization rate for the device. +MtmlReturn MTML_API mtmlMemoryGetUtilization(const MtmlMemory *mem, unsigned int *utilization); From 1a66bc4ec0dee43a30f26c0db11cc65a0fc9bec7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 16:29:23 +0800 Subject: [PATCH 47/67] GPU: code cleanup; port MT specific code to Windows --- CMakeLists.txt | 5 +-- src/detection/gpu/gpu_driver_specific.h | 50 +++++++++++++++++++++++++ src/detection/gpu/gpu_linux.c | 50 ++++++++++--------------- src/detection/gpu/gpu_windows.c | 37 +----------------- 4 files changed, 71 insertions(+), 71 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9af2b04414..eb74f018a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -838,15 +838,12 @@ endif() # Proprietary GPU driver APIs if(LINUX OR BSD OR WIN32) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c) + list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_mthreads.c) endif() if(WIN32) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c) endif() -if(LINUX) - list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_mthreads.c) -endif() - include(CheckFunctionExists) check_function_exists(wcwidth HAVE_WCWIDTH) if(NOT HAVE_WCWIDTH) diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 7b1ec74234..945b92cff6 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -50,3 +50,53 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); + +FF_MAYBE_UNUSED static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName) +{ + if (vendor == FF_GPU_VENDOR_NAME_NVIDIA) + { + *pDetectFn = ffDetectNvidiaGpuInfo; + #ifdef _WIN32 + *pDllName = "nvml.dll"; + #else + *pDllName = "libnvidia-ml.so"; + #endif + } + else if (vendor == FF_GPU_VENDOR_NAME_MTHREADS) + { + *pDetectFn = ffDetectMthreadsGpuInfo; + #ifdef _WIN32 + *pDllName = "mtml.dll"; + #else + *pDllName = "libmtml.so"; + #endif + } + #ifdef _WIN32 + else if (vendor == FF_GPU_VENDOR_NAME_INTEL) + { + *pDetectFn = ffDetectIntelGpuInfo; + #ifdef _WIN64 + *pDllName = "ControlLib.dll"; + #else + *pDllName = "ControlLib32.dll"; + #endif + } + else if (vendor == FF_GPU_VENDOR_NAME_AMD) + { + *pDetectFn = ffDetectAmdGpuInfo; + #ifdef _WIN64 + *pDllName = "amd_ags_x64.dll"; + #else + *pDllName = "amd_ags_x86.dll"; + #endif + } + #endif + else + { + *pDetectFn = NULL; + *pDllName = NULL; + return false; + } + + return true; +} diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 5c564c0da5..0dd04bc10c 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -343,11 +343,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf pciDetectIntelSpecific(gpu, deviceDir, buffer); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); } - else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) + else { - if (options->temp || options->driverSpecific) + __typeof__(&ffDetectNvidiaGpuInfo) detectFn; + const char* soName; + if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific)) { - ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { + detectFn(&(FFGpuDriverCondition) { .type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, .pciBusId = { .domain = pciDomain, @@ -359,41 +361,27 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, .name = options->driverSpecific ? &gpu->name : NULL, - }, "libnvidia-ml.so"); + }, soName); } if (gpu->type == FF_GPU_TYPE_UNKNOWN) { - if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") || - ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") || - ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) - gpu->type = FF_GPU_TYPE_DISCRETE; - } - } - else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) - { - if (options->temp || options->driverSpecific) - { - ffDetectMthreadsGpuInfo(&(FFGpuDriverCondition){ - .type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, - .pciBusId = { - .domain = pciDomain, - .bus = pciBus, - .device = pciDevice, - .func = pciFunc, - }, - }, - (FFGpuDriverResult){ - .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->driverSpecific ? &gpu->dedicated : NULL, - .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, - .type = &gpu->type, - .frequency = options->driverSpecific ? &gpu->frequency : NULL, - }, - "libmtml.so"); + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) + { + if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") || + ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") || + ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) + gpu->type = FF_GPU_TYPE_DISCRETE; + } + else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) + { + if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) + gpu->type = FF_GPU_TYPE_DISCRETE; + } } } diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 111aced8eb..c0399ecdd7 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -10,41 +10,6 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name) return ffStrbufEqual(&gpu->name, name); } -static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName) -{ - if (vendor == FF_GPU_VENDOR_NAME_NVIDIA) - { - *pDetectFn = ffDetectNvidiaGpuInfo; - *pDllName = "nvml.dll"; - } - else if (vendor == FF_GPU_VENDOR_NAME_INTEL) - { - *pDetectFn = ffDetectIntelGpuInfo; - #ifdef _WIN64 - *pDllName = "ControlLib.dll"; - #else - *pDllName = "ControlLib32.dll"; - #endif - } - else if (vendor == FF_GPU_VENDOR_NAME_AMD) - { - *pDetectFn = ffDetectAmdGpuInfo; - #ifdef _WIN64 - *pDllName = "amd_ags_x64.dll"; - #else - *pDllName = "amd_ags_x86.dll"; - #endif - } - else - { - *pDetectFn = NULL; - *pDllName = NULL; - return false; - } - - return true; -} - const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) }; @@ -150,7 +115,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (vendorId && deviceId) { int bus = -1, dev = -1, func = -1; - if (detectFn == ffDetectNvidiaGpuInfo) + if (detectFn == ffDetectNvidiaGpuInfo || detectFn == ffDetectMthreadsGpuInfo) { // Find PCI id from video id // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\DEVICE_ID\INSTANCE_ID\Device Parameters\VideoID From 4efe12c0d2b175c7c06237d5614081be3c48422a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 2 Aug 2024 16:47:57 +0800 Subject: [PATCH 48/67] GPU (BSD): correctly detect GPU type --- src/detection/gpu/gpu_bsd.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 379f5afa43..2e1bc6977e 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -96,9 +96,22 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) .coreUsage = &gpu->coreUsage, .name = options->driverSpecific ? &gpu->name : NULL, }, "libnvidia-ml.so"); + } - if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) - gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + if (gpu->type == FF_GPU_TYPE_UNKNOWN) + { + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) + { + if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") || + ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") || + ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla")) + gpu->type = FF_GPU_TYPE_DISCRETE; + } + else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS) + { + if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) + gpu->type = FF_GPU_TYPE_DISCRETE; + } } } From a856350416b37cbd9820f04d4165e17b8a775ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 2 Aug 2024 19:04:53 +0800 Subject: [PATCH 49/67] GPU (MT): fix segfault at program exit --- src/detection/gpu/gpu_mthreads.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c index edddd220b2..aefc1d9da6 100644 --- a/src/detection/gpu/gpu_mthreads.c +++ b/src/detection/gpu/gpu_mthreads.c @@ -22,12 +22,18 @@ struct FFMtmlData FF_LIBRARY_SYMBOL(mtmlMemoryGetTotal) FF_LIBRARY_SYMBOL(mtmlMemoryGetUsed) FF_LIBRARY_SYMBOL(mtmlMemoryGetUtilization) + FF_LIBRARY_SYMBOL(mtmlLibraryShutDown) bool inited; MtmlLibrary *lib; MtmlSystem *sys; } mtmlData; +static void shutdownMtml() +{ + mtmlData.ffmtmlLibraryShutDown(mtmlData.lib); +} + const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDriverResult result, const char *soName) { #ifndef FF_DISABLE_DLOPEN @@ -37,7 +43,6 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive mtmlData.inited = true; FF_LIBRARY_LOAD(libmtml, NULL, "dlopen mtml failed", soName, 1); FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryInit) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryShutDown) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetBrand) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetIndex) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetName) @@ -55,6 +60,7 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetTotal) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUsed) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUtilization) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryShutDown) if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS) { @@ -63,10 +69,11 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive } if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS) { + mtmlData.ffmtmlLibraryShutDown(mtmlData.lib); mtmlData.ffmtmlLibraryInitSystem = NULL; return "mtmlLibraryInitSystem failed"; } - atexit((void *)ffmtmlLibraryShutDown); + atexit(shutdownMtml); libmtml = NULL; // don't close mtml } From 0354fd5d9de1d70778cbd3e16778511ec4f5d372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 2 Aug 2024 21:52:24 +0800 Subject: [PATCH 50/67] GPU (Windows): use setupapi to find GPU devices Ref: https://github.com/gpustack/gpustack/pull/97#issuecomment-2264678404 --- src/detection/gpu/gpu_windows.c | 199 +++++++++++++++----------------- 1 file changed, 92 insertions(+), 107 deletions(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index c0399ecdd7..52988f80dd 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -3,48 +3,59 @@ #include "util/windows/unicode.h" #include "util/windows/registry.h" -#include +#define INITGUID +#include +#include +#include -static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name) +static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev) { - return ffStrbufEqual(&gpu->name, name); + if(*hdev) + SetupDiDestroyDeviceInfoList(*hdev); } +#define FF_EMPTY_GUID_STR L"{00000000-0000-0000-0000-000000000000}" +#define FF_GUID_STRLEN (sizeof(FF_EMPTY_GUID_STR) / sizeof(wchar_t) - 1) + const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { - DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) }; - wchar_t regDirectxKey[MAX_PATH] = L"SOFTWARE\\Microsoft\\DirectX\\{"; - const uint32_t regDirectxKeyPrefixLength = (uint32_t) wcslen(regDirectxKey); - wchar_t regControlVideoKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\{"; - const uint32_t regControlVideoKeyPrefixLength = (uint32_t) wcslen(regControlVideoKey); - const uint32_t deviceKeyPrefixLength = strlen("\\Registry\\Machine\\") + regControlVideoKeyPrefixLength; - wchar_t regPciKey[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Enum\\"; - const uint32_t regPciKeyPrefixLength = (uint32_t) wcslen(regPciKey); - - for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i) + HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) = + SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT); + + if(hdev == INVALID_HANDLE_VALUE) + return "SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY) failed"; + + wchar_t regDirectxKey[] = L"SOFTWARE\\Microsoft\\DirectX\\" FF_EMPTY_GUID_STR; + const uint32_t regDirectxKeyPrefixLength = (uint32_t) strlen("SOFTWARE\\Microsoft\\DirectX\\"); + wchar_t regControlVideoKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Video\\" FF_EMPTY_GUID_STR L"\\0000"; + const uint32_t regControlVideoKeyPrefixLength = (uint32_t) strlen("SYSTEM\\CurrentControlSet\\Control\\Video\\"); + + SP_DEVINFO_DATA did = { .cbSize = sizeof(did) }; + for (DWORD idev = 0; SetupDiEnumDeviceInfo(hdev, idev, &did); ++idev) { - if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; + wchar_t hardwareId[256]; + if (!SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_HARDWAREID, NULL, (PBYTE) hardwareId, sizeof(hardwareId), NULL)) + continue; - const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey); - if (__builtin_expect(deviceKeyLength == 100, true)) - { - if (wmemcmp(&displayDevice.DeviceKey[deviceKeyLength - 4], L"0000", 4) != 0) continue; - } - else + wchar_t videoId[39]; { - // DeviceKey can be empty. See #484 - FF_STRBUF_AUTO_DESTROY gpuName = ffStrbufCreateWS(displayDevice.DeviceString); - if (ffListContains(gpus, &gpuName, (void*) isGpuNameEqual)) continue; + FF_HKEY_AUTO_DESTROY hKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); + if (!hKey) continue; + DWORD videoIdLength = sizeof(videoId); + if (RegGetValueW(hKey, NULL, L"VideoID", RRF_RT_REG_SZ, NULL, videoId, &videoIdLength) != ERROR_SUCCESS || videoIdLength != (FF_GUID_STRLEN + 1) * sizeof(wchar_t)) + continue; } - // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html - // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" + wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, videoId, FF_GUID_STRLEN); + FF_HKEY_AUTO_DESTROY hKey = NULL; + if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue; + unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0; - swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); + swscanf(hardwareId, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); - ffStrbufInitWS(&gpu->name, displayDevice.DeviceString); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInitStatic(&gpu->platformApi, "Direct3D"); gpu->temperature = FF_GPU_TEMP_UNSET; @@ -55,56 +66,55 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->deviceId = 0; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{') + if (!ffRegReadStrbuf(hKey, L"DriverDesc", &gpu->name, NULL)) // faster, for some reason { - wmemcpy(regControlVideoKey + regControlVideoKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}\\0000")); - FF_HKEY_AUTO_DESTROY hKey = NULL; - if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue; + wchar_t name[256]; + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) name, sizeof(name), NULL)) + ffStrbufSetWS(&gpu->name, name); + } + ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL); - ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL); + wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, videoId, FF_GUID_STRLEN); + FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; + if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) + { + uint64_t dedicatedVideoMemory = 0; + if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) + gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}")); - FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; - if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) + uint64_t dedicatedSystemMemory, sharedSystemMemory; + if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && + ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) { - uint64_t dedicatedVideoMemory = 0; - if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) - gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; - - uint64_t dedicatedSystemMemory, sharedSystemMemory; - if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && - ffRegReadUint64(hDirectxKey, L"SharedSystemMemory", &sharedSystemMemory, NULL)) - { - gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; - gpu->shared.total = sharedSystemMemory; - } - - ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); - - uint32_t featureLevel = 0; - if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) - ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); - else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) - ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); - } - else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) - { - uint32_t vmem = 0; - if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL)) - gpu->dedicated.total = vmem; - gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; + gpu->shared.total = sharedSystemMemory; } - if (gpu->vendor.length == 0) - { - ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL); - if (ffStrbufContainS(&gpu->vendor, "Intel")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); - else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - } + ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); + + uint32_t featureLevel = 0; + if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); + else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); + } + else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) + { + uint32_t vmem = 0; + if (ffRegReadUint(hKey, L"HardwareInformation.MemorySize", &vmem, NULL)) + gpu->dedicated.total = vmem; + gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + } + + if (gpu->vendor.length == 0) + { + ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL); + if (ffStrbufContainS(&gpu->vendor, "Intel")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); } __typeof__(&ffDetectNvidiaGpuInfo) detectFn; @@ -112,43 +122,18 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { - if (vendorId && deviceId) + uint32_t pciBus, pciAddr; + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && + SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL)) { - int bus = -1, dev = -1, func = -1; - if (detectFn == ffDetectNvidiaGpuInfo || detectFn == ffDetectMthreadsGpuInfo) - { - // Find PCI id from video id - // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\PCI\DEVICE_ID\INSTANCE_ID\Device Parameters\VideoID - wcscpy(regPciKey + regPciKeyPrefixLength, displayDevice.DeviceID); - FF_HKEY_AUTO_DESTROY hKey = NULL; - if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regPciKey, &hKey, NULL)) continue; - for (uint32_t idx = 0; ; ++idx) - { - wchar_t instanceKey[256]; - DWORD bufSizeInstanceKey = sizeof(instanceKey) / sizeof(*instanceKey); - if (RegEnumKeyExW(hKey, idx, instanceKey, &bufSizeInstanceKey, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) break; - wcscpy(instanceKey + bufSizeInstanceKey, L"\\Device Parameters"); - - wchar_t videoId[256]; - DWORD bufSizeVideoId = sizeof(videoId) / sizeof(*videoId); - if (RegGetValueW(hKey, instanceKey, L"VideoID", RRF_RT_REG_SZ, NULL, videoId, &bufSizeVideoId) != ERROR_SUCCESS) continue; - if (videoId[0] != L'{') continue; - if (wmemcmp(videoId + 1 /* Ignore {} */, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000")) != 0) continue; - - // We finally find it - instanceKey[bufSizeInstanceKey] = L'\0'; - bufSizeVideoId = sizeof(videoId) / sizeof(*videoId); - if (RegGetValueW(hKey, instanceKey, L"LocationInformation", RRF_RT_REG_SZ, NULL, videoId, &bufSizeVideoId) != ERROR_SUCCESS) break; - swscanf(videoId, L"%*[^(](%d,%d,%d)", &bus, &dev, &func); - break; - } - } + uint32_t pciDev = (pciAddr >> 16) & 0xFFFF; + uint32_t pciFunc = pciAddr & 0xFFFF; detectFn( &(FFGpuDriverCondition) { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID - | FF_GPU_DRIVER_CONDITION_TYPE_LUID - | (bus >= 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), + | (gpu->deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) + | FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, .pciDeviceId = { .deviceId = deviceId, .vendorId = vendorId, @@ -157,9 +142,9 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }, .pciBusId = { .domain = 0, - .bus = (uint32_t) bus, - .device = (uint32_t) dev, - .func = (uint32_t) func, + .bus = pciBus, + .device = pciDev, + .func = pciFunc, }, .luid = gpu->deviceId, }, From d501c8b41a49c4bade2807d8eb8bfa4b509ad271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 2 Aug 2024 22:23:29 +0800 Subject: [PATCH 51/67] GPU (Windows): fix missing vendor string --- src/detection/gpu/gpu_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 52988f80dd..e9d4ffbb1c 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -54,7 +54,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* swscanf(hardwareId, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - ffStrbufInit(&gpu->vendor); + ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInitStatic(&gpu->platformApi, "Direct3D"); From 0c82a842664bb1ba19fc29559ac3fd6fb0303fbb Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 07:50:15 +0800 Subject: [PATCH 52/67] Global: remove using of libnm --- .github/workflows/ci.yml | 10 +++++----- CMakeLists.txt | 5 ----- debian/control | 2 +- src/common/init.c | 3 --- src/options/library.c | 7 ------- src/options/library.h | 1 - 6 files changed, 6 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 379f819e9b..b5fe55b6c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: run: uname -a - name: configure project - run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_LIBNM=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF + run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF - name: build project run: cmake --build . --target package --verbose -j4 @@ -74,7 +74,7 @@ jobs: run: uname -a - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev + run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev directx-headers-dev - name: install linuxbrew packages run: | @@ -142,7 +142,7 @@ jobs: githubToken: ${{ github.token }} run: | uname -a - apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm + apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev directx-headers-dev rpm cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features @@ -181,7 +181,7 @@ jobs: # CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments` wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb} dpkg -i *.deb - apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev directx-headers-dev rpm + apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev directx-headers-dev rpm cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features @@ -216,7 +216,7 @@ jobs: githubToken: ${{ github.token }} run: | uname -a - apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm + apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev rpm cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . cmake --build . --target package --verbose -j4 ./fastfetch --list-features diff --git a/CMakeLists.txt b/CMakeLists.txt index eb74f018a0..db96fd6cbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,6 @@ cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD OR WIN32 OR SunO cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD OR SunOS" OFF) cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD OR SunOS" OFF) cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR ANDROID OR SunOS" OFF) -cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF) cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) @@ -1064,10 +1063,6 @@ ff_lib_enable(OPENCL "OpenCL" "OpenCL" ) -ff_lib_enable(LIBNM - "libnm" - "libnm" -) ff_lib_enable(FREETYPE "freetype2" "FreeType2" diff --git a/debian/control b/debian/control index 262f6b9440..0f35707a52 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: fastfetch Section: universe/utils Priority: optional Maintainer: Carter Li -Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build +Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build Standards-Version: 4.0.0 Homepage: https://github.com/fastfetch-cli/fastfetch diff --git a/src/common/init.c b/src/common/init.c index c9c80ed97c..96d1702918 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -245,9 +245,6 @@ void ffListFeatures(void) #if FF_HAVE_PULSE "libpulse\n" #endif - #if FF_HAVE_LIBNM - "libnm\n" - #endif #if FF_HAVE_DDCUTIL "libddcutil\n" #endif diff --git a/src/options/library.c b/src/options/library.c index a80f4b6c60..c718f6bbc7 100644 --- a/src/options/library.c +++ b/src/options/library.c @@ -62,8 +62,6 @@ const char* ffOptionsParseLibraryJsonConfig(FFOptionsLibrary* options, yyjson_va ffStrbufSetS(&options->libOSMesa, yyjson_get_str(val)); else if (ffStrEqualsIgnCase(key, "pulse")) ffStrbufSetS(&options->libPulse, yyjson_get_str(val)); - else if (ffStrEqualsIgnCase(key, "nm")) - ffStrbufSetS(&options->libnm, yyjson_get_str(val)); else if (ffStrEqualsIgnCase(key, "ddcutil")) ffStrbufSetS(&options->libDdcutil, yyjson_get_str(val)); else if (ffStrEqualsIgnCase(key, "drm")) @@ -129,8 +127,6 @@ bool ffOptionsParseLibraryCommandLine(FFOptionsLibrary* options, const char* key ffOptionParseString(key, value, &options->libOSMesa); else if(ffStrEqualsIgnCase(subkey, "pulse")) ffOptionParseString(key, value, &options->libPulse); - else if(ffStrEqualsIgnCase(subkey, "nm")) - ffOptionParseString(key, value, &options->libnm); else if(ffStrEqualsIgnCase(subkey, "ddcutil")) ffOptionParseString(key, value, &options->libDdcutil); else if(ffStrEqualsIgnCase(subkey, "drm")) @@ -227,9 +223,6 @@ void ffOptionsGenerateLibraryJsonConfig(FFOptionsLibrary* options, yyjson_mut_do if (!ffStrbufEqual(&options->libPulse, &defaultOptions.libPulse)) yyjson_mut_obj_add_strbuf(doc, obj, "pulse", &options->libPulse); - if (!ffStrbufEqual(&options->libnm, &defaultOptions.libnm)) - yyjson_mut_obj_add_strbuf(doc, obj, "nm", &options->libnm); - if (!ffStrbufEqual(&options->libDdcutil, &defaultOptions.libDdcutil)) yyjson_mut_obj_add_strbuf(doc, obj, "ddcutil", &options->libDdcutil); diff --git a/src/options/library.h b/src/options/library.h index 55f2be4e22..14d38a7289 100644 --- a/src/options/library.h +++ b/src/options/library.h @@ -30,7 +30,6 @@ typedef struct FFOptionsLibrary FFstrbuf libGLX; FFstrbuf libOSMesa; FFstrbuf libPulse; - FFstrbuf libnm; FFstrbuf libDdcutil; FFstrbuf libdrm; #endif From d0b72c545781e5f4c7b5434db1ea53a2a8144e07 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 08:17:14 +0800 Subject: [PATCH 53/67] Shell (Linux): remove version detection for unknown shells It's a dangerous operation. Should fix #1144 --- src/detection/terminalshell/terminalshell.c | 26 ++------------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 230b515c18..9d65bde3aa 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -200,28 +200,6 @@ static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version) NULL }) == NULL; } -#else -static bool getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf* version) -{ - FF_STRBUF_AUTO_DESTROY command = ffStrbufCreate(); - ffStrbufAppendS(&command, "printf \"%s\" \"$"); - ffStrbufAppendTransformS(&command, exeName, toupper); - ffStrbufAppendS(&command, "_VERSION\""); - - if (ffProcessAppendStdOut(version, (char* const[]) { - "env", - "-i", - exe->chars, - "-c", - command.chars, - NULL - }) != NULL) - return false; - - ffStrbufSubstrBeforeFirstC(version, '('); - ffStrbufRemoveStrings(version, 2, (const char*[]) { "-release", "release" }); - return true; -} #endif bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) @@ -261,9 +239,9 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) return getShellVersionWinPowerShell(exe, version); return getFileVersion(exe->chars, version); - #else - return getShellVersionGeneric(exe, exeName, version); #endif + + return false; } FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version) From 831d2a05ce72459228ee1e40ba09a6509514c5cd Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 22:03:34 +0800 Subject: [PATCH 54/67] DBus: code cleanup; prepare for future commits --- src/common/dbus.c | 93 ++++++++++++++++++++++++++++------------------- src/common/dbus.h | 22 ++--------- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/src/common/dbus.c b/src/common/dbus.c index 1715a50887..553d7eff70 100644 --- a/src/common/dbus.c +++ b/src/common/dbus.c @@ -10,9 +10,8 @@ static bool loadLibSymbols(FFDBusLibrary* lib) FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4); FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_append_args, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init_append, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_append_basic, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_arg_type, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_get_basic, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_recurse, false) @@ -20,10 +19,6 @@ static bool loadLibSymbols(FFDBusLibrary* lib) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false) FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_flush, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_block, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_steal_reply, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_pending_call_unref, false) dbus = NULL; // don't auto dlclose return true; } @@ -60,7 +55,7 @@ bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) { int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); - if(argType == DBUS_TYPE_STRING) + if(argType == DBUS_TYPE_STRING || argType == DBUS_TYPE_OBJECT_PATH) { const char* value = NULL; dbus->lib->ffdbus_message_iter_get_basic(iter, &value); @@ -72,6 +67,14 @@ bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) return true; } + if (argType == DBUS_TYPE_BYTE) + { + uint8_t value; + dbus->lib->ffdbus_message_iter_get_basic(iter, &value); + ffStrbufAppendC(result, (char) value); + return false; // Don't append a comma + } + if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY) return false; @@ -93,7 +96,10 @@ bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) ffStrbufAppendS(result, ", "); } - FF_DBUS_ITER_CONTINUE(dbus, &subIter); + if(!dbus->lib->ffdbus_message_iter_next(&subIter)) + break; + else + continue; } if(foundAValue) @@ -122,29 +128,27 @@ bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result) return ffDBusGetBool(dbus, &subIter, result); } -bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result) +bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result) { int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); if(argType == DBUS_TYPE_BYTE) { - dbus->lib->ffdbus_message_iter_get_basic(iter, result); + uint8_t value = 0; + dbus->lib->ffdbus_message_iter_get_basic(iter, &value); + *result = value; return true; } - if(argType != DBUS_TYPE_VARIANT) - return false; - - DBusMessageIter subIter; - dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); - return ffDBusGetByte(dbus, &subIter, result); -} - -bool ffDBusGetUint16(FFDBusData* dbus, DBusMessageIter* iter, uint16_t* result) -{ - int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter); - if(argType == DBUS_TYPE_UINT16) + { + uint16_t value = 0; + dbus->lib->ffdbus_message_iter_get_basic(iter, &value); + *result = value; + return true; + } + + if(argType == DBUS_TYPE_UINT32) { dbus->lib->ffdbus_message_iter_get_basic(iter, result); return true; @@ -155,15 +159,18 @@ bool ffDBusGetUint16(FFDBusData* dbus, DBusMessageIter* iter, uint16_t* result) DBusMessageIter subIter; dbus->lib->ffdbus_message_iter_recurse(iter, &subIter); - return ffDBusGetUint16(dbus, &subIter, result); + return ffDBusGetUint(dbus, &subIter, result); } -DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method) +DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg) { DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method); if(message == NULL) return NULL; + if (arg) + dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID); + DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); dbus->lib->ffdbus_message_unref(message); @@ -177,20 +184,10 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char if(message == NULL) return NULL; - DBusMessageIter requestIterator; - dbus->lib->ffdbus_message_iter_init_append(message, &requestIterator); - - if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &interface)) - { - dbus->lib->ffdbus_message_unref(message); - return NULL; - } - - if(!dbus->lib->ffdbus_message_iter_append_basic(&requestIterator, DBUS_TYPE_STRING, &property)) - { - dbus->lib->ffdbus_message_unref(message); - return NULL; - } + dbus->lib->ffdbus_message_append_args(message, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_STRING, &property, + DBUS_TYPE_INVALID); DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL); @@ -219,4 +216,24 @@ bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* return ret; } +bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result) +{ + DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property); + if(reply == NULL) + return false; + + DBusMessageIter rootIterator; + if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) + { + dbus->lib->ffdbus_message_unref(reply); + return false; + } + + bool ret = ffDBusGetUint(dbus, &rootIterator, result); + + dbus->lib->ffdbus_message_unref(reply); + + return ret; +} + #endif //FF_HAVE_DBUS diff --git a/src/common/dbus.h b/src/common/dbus.h index bf6a5cc980..876ef355c6 100644 --- a/src/common/dbus.h +++ b/src/common/dbus.h @@ -7,22 +7,12 @@ #include "common/library.h" #define FF_DBUS_TIMEOUT_MILLISECONDS 35 - -#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \ - { \ - if(!(dbus)->lib->ffdbus_message_iter_has_next(iterator)) \ - break; \ - (dbus)->lib->ffdbus_message_iter_next(iterator); \ - continue; \ - } - typedef struct FFDBusLibrary { FF_LIBRARY_SYMBOL(dbus_bus_get) FF_LIBRARY_SYMBOL(dbus_message_new_method_call) + FF_LIBRARY_SYMBOL(dbus_message_append_args) FF_LIBRARY_SYMBOL(dbus_message_iter_init) - FF_LIBRARY_SYMBOL(dbus_message_iter_init_append) - FF_LIBRARY_SYMBOL(dbus_message_iter_append_basic) FF_LIBRARY_SYMBOL(dbus_message_iter_get_arg_type) FF_LIBRARY_SYMBOL(dbus_message_iter_get_basic) FF_LIBRARY_SYMBOL(dbus_message_iter_recurse) @@ -30,10 +20,6 @@ typedef struct FFDBusLibrary FF_LIBRARY_SYMBOL(dbus_message_iter_next) FF_LIBRARY_SYMBOL(dbus_message_unref) FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block) - FF_LIBRARY_SYMBOL(dbus_connection_flush) - FF_LIBRARY_SYMBOL(dbus_pending_call_block) - FF_LIBRARY_SYMBOL(dbus_pending_call_steal_reply) - FF_LIBRARY_SYMBOL(dbus_pending_call_unref) } FFDBusLibrary; typedef struct FFDBusData @@ -45,10 +31,10 @@ typedef struct FFDBusData const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result); bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result); -bool ffDBusGetByte(FFDBusData* dbus, DBusMessageIter* iter, uint8_t* result); -bool ffDBusGetUint16(FFDBusData* dbus, DBusMessageIter* iter, uint16_t* result); -DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method); +bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result); +DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg); DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property); bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result); +bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result); #endif // FF_HAVE_DBUS From e6cf7fdb9fae9e09b4269cdc295bb6be1124a6ef Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 22:04:53 +0800 Subject: [PATCH 55/67] Bluetooth (Linux): update for DBus api changes --- src/detection/bluetooth/bluetooth_linux.c | 23 ++++++++-------- .../bluetoothradio/bluetoothradio_linux.c | 27 +++++++------------ 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index ef66cfcc3a..b7ae5a8394 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -67,7 +67,11 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue else if(ffStrEquals(deviceProperty, "Icon")) ffDBusGetString(dbus, &dictIter, &device->type); else if(ffStrEquals(deviceProperty, "Percentage")) - ffDBusGetByte(dbus, &dictIter, &device->battery); + { + uint32_t percentage; + if (ffDBusGetUint(dbus, &dictIter, &percentage)) + device->battery = (uint8_t) percentage; + } else if(ffStrEquals(deviceProperty, "Connected")) ffDBusGetBool(dbus, &dictIter, &device->connected); } @@ -97,11 +101,10 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB DBusMessageIter arrayIter; dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); - while(true) + do { detectBluetoothValue(dbus, &arrayIter, device); - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); - } + } while (dbus->lib->ffdbus_message_iter_next(&arrayIter)); } static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter) @@ -137,11 +140,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage device->battery = 0; device->connected = false; - while(true) + do { detectBluetoothProperty(dbus, &arrayIter, device); - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); - } + } while (dbus->lib->ffdbus_message_iter_next(&arrayIter)); if(device->name.length == 0) { @@ -160,11 +162,10 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt DBusMessageIter arrayIter; dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter); - while(true) + do { detectBluetoothObject(devices, dbus, &arrayIter); - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); - } + } while (dbus->lib->ffdbus_message_iter_next(&arrayIter)); } static const char* detectBluetooth(FFlist* devices) @@ -174,7 +175,7 @@ static const char* detectBluetooth(FFlist* devices) if(error) return error; - DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL); if(!managedObjects) return "Failed to call GetManagedObjects"; diff --git a/src/detection/bluetoothradio/bluetoothradio_linux.c b/src/detection/bluetoothradio/bluetoothradio_linux.c index dca38cf036..6157ee16bd 100644 --- a/src/detection/bluetoothradio/bluetoothradio_linux.c +++ b/src/detection/bluetoothradio/bluetoothradio_linux.c @@ -65,16 +65,12 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue ffDBusGetString(dbus, &dictIter, &device->name); else if(ffStrEquals(deviceProperty, "Manufacturer")) { - uint16_t vendorId; - if (ffDBusGetUint16(dbus, &dictIter, &vendorId)) + uint32_t vendorId; + if (ffDBusGetUint(dbus, &dictIter, &vendorId)) ffStrbufSetStatic(&device->vendor, ffBluetoothRadioGetVendor(vendorId)); } else if(ffStrEquals(deviceProperty, "Version")) - { - uint8_t byte; - if (ffDBusGetByte(dbus, &dictIter, &byte)) - device->lmpVersion = byte; - } + ffDBusGetUint(dbus, &dictIter, (uint32_t*) &device->lmpVersion); else if(ffStrEquals(deviceProperty, "Powered")) ffDBusGetBool(dbus, &dictIter, &device->enabled); else if(ffStrEquals(deviceProperty, "Discoverable")) @@ -108,11 +104,10 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB DBusMessageIter arrayIter; dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); - while(true) + do { detectBluetoothValue(dbus, &arrayIter, device); - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); - } + } while (dbus->lib->ffdbus_message_iter_next(&arrayIter)); } static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter) @@ -149,11 +144,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage device->lmpSubversion = INT_MIN; device->enabled = false; - while(true) + do { detectBluetoothProperty(dbus, &arrayIter, device); - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); - } + } while (dbus->lib->ffdbus_message_iter_next(&arrayIter)); if(device->name.length == 0) { @@ -171,11 +165,10 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt DBusMessageIter arrayIter; dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter); - while(true) + do { detectBluetoothObject(devices, dbus, &arrayIter); - FF_DBUS_ITER_CONTINUE(dbus, &arrayIter); - } + } while (dbus->lib->ffdbus_message_iter_next(&arrayIter)); } static const char* detectBluetooth(FFlist* devices) @@ -185,7 +178,7 @@ static const char* detectBluetooth(FFlist* devices) if(error) return error; - DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL); if(!managedObjects) return "Failed to call GetManagedObjects"; From 493cf8ff6ca0e91a03910aa52ac6c154799c3c8f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 22:05:29 +0800 Subject: [PATCH 56/67] Media (Linux): detect playing status; update dbus api change --- src/detection/media/media_linux.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/detection/media/media_linux.c b/src/detection/media/media_linux.c index 7d40927d7c..83949bcdff 100644 --- a/src/detection/media/media_linux.c +++ b/src/detection/media/media_linux.c @@ -11,6 +11,13 @@ #include "common/dbus.h" #include "common/library.h" +#define FF_DBUS_ITER_CONTINUE(dbus, iterator) \ + { \ + if(!(dbus)->lib->ffdbus_message_iter_next(iterator)) \ + break; \ + continue; \ + } + static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result) { DBusMessage* reply = ffDBusGetProperty(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "Metadata"); @@ -85,6 +92,8 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul return false; } + ffDBusGetPropertyString(data, busName, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", "PlaybackStatus", &result->status); + //Set short bus name ffStrbufAppendS(&result->playerId, busName + sizeof(FF_DBUS_MPRIS_PREFIX) - 1); @@ -119,7 +128,7 @@ static void getBestBus(FFDBusData* data, FFMediaResult* result) getBusProperties(data, FF_DBUS_MPRIS_PREFIX"plasma-browser-integration", result) ) return; - DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames"); + DBusMessage* reply = ffDBusGetMethodReply(data, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL); if(reply == NULL) return; From 3a61b31e0a5bdf0b369a2b278a4e20e158c89100 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 22:06:37 +0800 Subject: [PATCH 57/67] Wifi (Linux): implement libnm stuff with plain dbus calls --- src/detection/wifi/wifi_linux.c | 144 ++++++++++++++++++++++++++++---- 1 file changed, 129 insertions(+), 15 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 137b818165..95a81325d7 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,4 +1,5 @@ #include "wifi.h" +#include "common/dbus.h" #include "common/processing.h" #include "common/properties.h" #include "util/stringUtils.h" @@ -6,6 +7,118 @@ #include #include +// https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApFlags +typedef enum { + NM_802_11_AP_FLAGS_NONE = 0x00000000, + NM_802_11_AP_FLAGS_PRIVACY = 0x00000001, + NM_802_11_AP_FLAGS_WPS = 0x00000002, + NM_802_11_AP_FLAGS_WPS_PBC = 0x00000004, + NM_802_11_AP_FLAGS_WPS_PIN = 0x00000008, +} NM80211ApFlags; + +// https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApSecurityFlags +typedef enum { + NM_802_11_AP_SEC_NONE = 0x00000000, + NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001, + NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002, + NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004, + NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008, + NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010, + NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020, + NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040, + NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080, + NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100, + NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200, + NM_802_11_AP_SEC_KEY_MGMT_SAE = 0x00000400, + NM_802_11_AP_SEC_KEY_MGMT_OWE = 0x00000800, + NM_802_11_AP_SEC_KEY_MGMT_OWE_TM = 0x00001000, + NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192 = 0x00002000, +} NM80211ApSecurityFlags; + +static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer) +{ + FFDBusData dbus; + const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus); + if(error) + return error; + + { + DBusMessage* device = ffDBusGetMethodReply(&dbus, "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", "GetDeviceByIpIface", item->inf.description.chars); + if(!device) + return "Failed to call GetDeviceByIpIface"; + + ffStrbufClear(buffer); + DBusMessageIter rootIter; + if(!dbus.lib->ffdbus_message_iter_init(device, &rootIter) || !ffDBusGetString(&dbus, &rootIter, buffer)) + { + dbus.lib->ffdbus_message_unref(device); + return "Failed to get device path"; + } + dbus.lib->ffdbus_message_unref(device); + } + + if (item->conn.txRate != item->conn.txRate) + { + uint32_t bitrate; + if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", buffer->chars, "org.freedesktop.NetworkManager.Device.Wireless", "Bitrate", &bitrate)) + item->conn.txRate = bitrate / 1000.; + } + + FF_STRBUF_AUTO_DESTROY apPath = ffStrbufCreate(); + if (!ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", buffer->chars, "org.freedesktop.NetworkManager.Device.Wireless", "ActiveAccessPoint", &apPath)) + return "Failed to get active access point path"; + + if (!item->conn.status.length) + ffStrbufSetStatic(&item->conn.status, "connected"); + + if (!item->conn.ssid.length) + ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Ssid", &item->conn.ssid); + + if (!item->conn.bssid.length) + ffDBusGetPropertyString(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "HwAddress", &item->conn.bssid); + + if (item->conn.signalQuality != item->conn.signalQuality) + { + uint32_t strengthPercent; + if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Strength", &strengthPercent)) + item->conn.signalQuality = strengthPercent; + } + + NM80211ApFlags flags; + NM80211ApSecurityFlags wpaFlags, rsnFlags; + if (ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "Flags", &flags) && + ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars, "org.freedesktop.NetworkManager.AccessPoint", "WpaFlags", &wpaFlags) && + ffDBusGetPropertyUint(&dbus, "org.freedesktop.NetworkManager", apPath.chars , "org.freedesktop.NetworkManager.AccessPoint", "RsnFlags", &rsnFlags)) + { + if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpaFlags == NM_802_11_AP_SEC_NONE) + && (rsnFlags == NM_802_11_AP_SEC_NONE)) + ffStrbufAppendS(&item->conn.security, "WEP/"); + if (wpaFlags != NM_802_11_AP_SEC_NONE) + ffStrbufAppendS(&item->conn.security, "WPA/"); + if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + ffStrbufAppendS(&item->conn.security, "WPA2/"); + } + if (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_SAE) { + ffStrbufAppendS(&item->conn.security, "WPA3/"); + } + if ((rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE) + || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_OWE_TM)) { + ffStrbufAppendS(&item->conn.security, "OWE/"); + } + if ((wpaFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + || (rsnFlags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + ffStrbufAppendS(&item->conn.security, "802.1X/"); + } + if (!item->conn.security.length) + ffStrbufAppendS(&item->conn.security, "Insecure"); + else + ffStrbufTrimRight(&item->conn.security, '/'); + } + + return NULL; +} + static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) { const char* error = NULL; @@ -28,9 +141,9 @@ static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) return NULL; } - ffStrbufAppendS(&item->conn.status, "connected"); ffStrbufSubstrBeforeFirstC(&item->conn.bssid, ' '); + ffStrbufUpperCase(&item->conn.bssid); ffParsePropLines(output.chars, "SSID: ", &item->conn.ssid); @@ -63,8 +176,6 @@ static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) } #if FF_HAVE_LINUX_WIRELESS -#define FF_DETECT_WIFI_WITH_IOCTLS - #include "common/io/io.h" #include @@ -86,7 +197,10 @@ static const char* detectWifiWithIoctls(FFWifiResult* item) iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; iwr.u.essid.flags = 0; if(ioctl(sock, SIOCGIWESSID, &iwr) >= 0) + { + ffStrbufSetStatic(&item->conn.status, "connected"); ffStrbufRecalculateLength(&item->conn.ssid); + } if(ioctl(sock, SIOCGIWNAME, &iwr) >= 0 && !ffStrEqualsIgnCase(iwr.u.name, "IEEE 802.11")) { @@ -99,10 +213,13 @@ static const char* detectWifiWithIoctls(FFWifiResult* item) if(ioctl(sock, SIOCGIWAP, &iwr) >= 0) { for(int i = 0; i < 6; ++i) - ffStrbufAppendF(&item->conn.bssid, "%.2X-", (uint8_t) iwr.u.ap_addr.sa_data[i]); + ffStrbufAppendF(&item->conn.bssid, "%.2X:", (uint8_t) iwr.u.ap_addr.sa_data[i]); ffStrbufTrimRight(&item->conn.bssid, '-'); } + if(ioctl(sock, SIOCGIWRATE, &iwr) >= 0) + item->conn.txRate = iwr.u.bitrate.value / 1000000.; + struct iw_statistics stats; iwr.u.data.pointer = &stats; iwr.u.data.length = sizeof(stats); @@ -156,7 +273,6 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) return "if_nameindex() failed"; FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - const char* error = NULL; for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i) { @@ -184,18 +300,16 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) if (!ffStrbufEqualS(&item->inf.status, "up")) continue; - if (detectWifiWithIw(item, &buffer) == NULL) - continue; - - #ifdef FF_DETECT_WIFI_WITH_IOCTLS - detectWifiWithIoctls(item); - continue; - #endif + if (detectWifiWithIw(item, &buffer) != NULL) + { + #ifdef FF_HAVE_LINUX_WIRELESS + detectWifiWithIoctls(item); + #endif + } - error = "`iw` failed and `linux/wireless.h` not found during compilation"; - break; + detectWifiWithNm(item, &buffer); } if_freenameindex(infs); - return error; + return NULL; } From 6b0db6fa746c3d5e2273cf76b6f7544f3a6585fe Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 3 Aug 2024 22:16:07 +0800 Subject: [PATCH 58/67] Wifi (Linux): fix compiling without dbus --- src/detection/wifi/wifi_linux.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 95a81325d7..1848c236d9 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -4,9 +4,9 @@ #include "common/properties.h" #include "util/stringUtils.h" -#include -#include +#include +#ifdef FF_HAVE_DBUS // https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NM80211ApFlags typedef enum { NM_802_11_AP_FLAGS_NONE = 0x00000000, @@ -118,6 +118,7 @@ static const char* detectWifiWithNm(FFWifiResult* item, FFstrbuf* buffer) return NULL; } +#endif // FF_HAVE_DBUS static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) { @@ -178,7 +179,6 @@ static const char* detectWifiWithIw(FFWifiResult* item, FFstrbuf* buffer) #if FF_HAVE_LINUX_WIRELESS #include "common/io/io.h" -#include #include #include #include @@ -263,8 +263,7 @@ static const char* detectWifiWithIoctls(FFWifiResult* item) return NULL; } - -#endif +#endif // FF_HAVE_LINUX_WIRELESS const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) { @@ -307,7 +306,9 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) #endif } - detectWifiWithNm(item, &buffer); + #ifdef FF_HAVE_DBUS + detectWifiWithNm(item, &buffer); + #endif } if_freenameindex(infs); From 8284d73cc9d98913be8021ddcc6c7ecc0f7daa1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 4 Aug 2024 14:11:57 +0800 Subject: [PATCH 59/67] Doc (Logo): metion size requirement [ci skip] --- .github/ISSUE_TEMPLATE/logo_request.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/logo_request.md b/.github/ISSUE_TEMPLATE/logo_request.md index 98bfff8988..ea141df00e 100644 --- a/.github/ISSUE_TEMPLATE/logo_request.md +++ b/.github/ISSUE_TEMPLATE/logo_request.md @@ -15,6 +15,9 @@ Paste content of /etc/os-release and /etc/lsb-release here. If none of these fil ``` # Ascii + +An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release` + ``` Paste ascii art here. ``` From 1101d2e90e203f02169e96af396ef75fbfacf485 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 4 Aug 2024 20:08:21 +0800 Subject: [PATCH 60/67] Disk (BSD): minor fix for a type, fixes calculation of disk usage on 32-bit (#1150) --- src/detection/disk/disk_bsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 3046a3577e..81be9c83fc 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -123,7 +123,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) FFDisk* disk = ffListAdd(disks); - disk->bytesTotal = fs->f_blocks * fs->f_bsize; + disk->bytesTotal = (uint64_t)fs->f_blocks * fs->f_bsize; disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize; disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize; disk->bytesUsed = 0; // To be filled in ./disk.c From d81cd50f648133287c097851fd7e0bdaf021956d Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Sun, 4 Aug 2024 20:13:28 +0800 Subject: [PATCH 61/67] Shell (Linux): don't detect hyfetch as shell on NixOS (#1149) On NixOS, Hyfetch has been placed in a "wrapper script" in order to set the correct PATH that it needs to run correctly. As a result, the actual Hyfetch executable has been renamed `.hyfetch-wrapped`, which results in this check failing to detect Hyfetch on NixOS properly. With this patch the logic has been changed to check if the program name contains the string `hyfetch`, which should work for the NixOS case. --- src/detection/terminalshell/terminalshell_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 3a5449258e..30e1319040 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -50,7 +50,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) ffStrbufEqualS(&result->processName, "perf") || ffStrbufEqualS(&result->processName, "guake-wrapped") || ffStrbufEqualS(&result->processName, "time") || - ffStrbufEqualS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend + ffStrbufContainS(&result->processName, "hyfetch") || //when hyfetch uses fastfetch as backend ffStrbufEqualS(&result->processName, "clifm") || //https://github.com/leo-arch/clifm/issues/289 ffStrbufEqualS(&result->processName, "valgrind") || ffStrbufEqualS(&result->processName, "fastfetch") || //994 From f683351fe3ffc664f18721c77f9c041d150a6a12 Mon Sep 17 00:00:00 2001 From: keklick1337 <86933883+keklick1337@users.noreply.github.com> Date: Sun, 4 Aug 2024 17:50:49 +0400 Subject: [PATCH 62/67] Logo (Builtin): QTS logo (#1152) --- src/logo/ascii/qts.txt | 14 ++++++++++++++ src/logo/builtin.c | 11 +++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/logo/ascii/qts.txt diff --git a/src/logo/ascii/qts.txt b/src/logo/ascii/qts.txt new file mode 100644 index 0000000000..3fe32a8500 --- /dev/null +++ b/src/logo/ascii/qts.txt @@ -0,0 +1,14 @@ + $1###########################- + $1############################### +$1=#########**************######### +$1########## ######## +$1########## ######## +$1########## ######## +$1########## ######## +$1########## ######## +$1########## $2. $1######## +$1########## $2+=. $1:##### +$1+#########+=========- $2%%%* $1=# + $1#####################* $2%%%%# + $1-#####################* $2%%%%%. + $2``````` \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index b23d3c3e93..49924eb081 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3508,6 +3508,17 @@ static const FFlogo P[] = { }; static const FFlogo Q[] = { + // QTS + { + .names = {"qts"}, + .lines = FASTFETCH_DATATEXT_LOGO_QTS, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_RED, + }, + .colorKeys = FF_COLOR_FG_BLUE, + .colorTitle = FF_COLOR_FG_BLUE, + }, // Q4OS { .names = {"Q4OS"}, From b2cc5c4f043a3af500f62789c33874e29fbcad21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 5 Aug 2024 08:54:25 +0800 Subject: [PATCH 63/67] CMake: clarify BSD is FreeBSD Fix #1154 --- CMakeLists.txt | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index db96fd6cbd..b51e4370f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ if(ANDROID) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") - set(BSD TRUE CACHE BOOL "..." FORCE) + set(FreeBSD TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") set(SunOS TRUE CACHE BOOL "..." FORCE) elseif(NOT APPLE AND NOT WIN32) @@ -44,27 +44,27 @@ include(CheckIncludeFile) include(CMakeDependentOption) -cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID OR SunOS" OFF) -cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF) -cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR BSD OR APPLE OR SunOS" OFF) +cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD" OFF) +cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF) cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR BSD OR APPLE OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR BSD OR APPLE OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR APPLE OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF) cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) -cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32 OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF) cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) @@ -542,7 +542,7 @@ elseif(ANDROID) src/detection/camera/camera_android.c src/util/platform/FFPlatform_unix.c ) -elseif(BSD) +elseif(FreeBSD) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c src/common/io/io_unix.c @@ -835,7 +835,7 @@ if(ENABLE_DIRECTX_HEADERS) endif() # Proprietary GPU driver APIs -if(LINUX OR BSD OR WIN32) +if(LINUX OR FreeBSD OR WIN32) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_mthreads.c) endif() @@ -895,7 +895,7 @@ if(APPLE AND EXISTS "/usr/bin/otool") target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}") endif() endif() -if(BSD AND EXISTS "/usr/local/bin/objdump") +if(FreeBSD AND EXISTS "/usr/local/bin/objdump") execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[^ )]*' -o | sort -Vru | head -1" OUTPUT_VARIABLE OBJDUMP_T_RESULT) if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)") @@ -1128,7 +1128,7 @@ elseif(WIN32) PRIVATE "hid" PRIVATE "wtsapi32" ) -elseif(BSD) +elseif(FreeBSD) target_link_libraries(libfastfetch PRIVATE "m" PRIVATE "usbhid" From 6ca65b916615af1c34b09447f65c25a602e5d93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 5 Aug 2024 10:07:17 +0800 Subject: [PATCH 64/67] GPU (BSD): improve type detection for Intel integrated GPUs --- src/detection/gpu/gpu_bsd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 2e1bc6977e..519263556c 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -112,6 +112,10 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT ")) gpu->type = FF_GPU_TYPE_DISCRETE; } + else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) + { + gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + } } } From 1de97fa3ed1965f3dc35fe341db7f6dbe939d906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 5 Aug 2024 10:09:40 +0800 Subject: [PATCH 65/67] Doc: update changelog for v2.21.0 --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3a5239216..1a475abd0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +# 2.21.0 + +Changes: +* We no longer use `libnm` for Wifi detection on Linux. Instead, we use `libdbus` to communicate with NetworkManager directly + * To package managers: libnm dependency should be removed + +Features: +* Add module `BluetoothRadio` that prints bluetooth radios installed on the system + * Don't confuse with module `Bluetooth` which lists connected bluetooth devices +* Detect more information when `--gpu-driver-specific` is used (GPU) +* Detect which type of nvidia driver (open source or proprietary) is used (GPU, Linux) +* `--gpu-driver-specific` adds supports for Moore Threads GPU (#1142, GPU, Linux / Windows) +* Use SetupAPI for detecting GPUs to support GPU detection when running fastfetch as a Windows Service (GPU, Windows) + * See https://github.com/gpustack/gpustack/pull/97#issuecomment-2264699787 for detail +* Detect playback status (Media, Linux) + +Bugfixes: +* Don't try to connect display server in tty mode (Linux, #1110) +* Improve ssh detection +* Fix max frequency printing in custom format (CPU) +* Fix displaying random characters when detecting kitty term font (#1136 / #1145, TerminalFont, Linux) +* Make sure to detect all physical memory devices (#1137) +* Don't detect `wl-restart` as WM (#1135, WM, Linux) +* Use PCI bus ID to match Nvidia cards; fix multi-GPU detection (GPU) +* Ignore invalid GPU (#1066, GPU, macOS) +* Print error when invalid color code is found (#1138) +* Fix invalid refresh rate detection on old macOS versions (Display, macOS) +* Fix disk size detection on 32-bit systems (Disk, BSD) +* Don't ignore disabled GPUs (#1140, GPU, Linux) +* Fix GPU type detection on FreeBSD (GPU, FreeBSD) +* Remove shell version detection for unknown shells (#1144, Shell) +* Don't detect hyfetch as shell on NixOS (Shell, NixOS) + +Logos: +* Update EndeavourOS_small +* Add QTS + # 2.20.0 This release fixes regression of `2.19.0` on M1 MacBook Air. It also introduces a new option `--key-type icon` to display predefined icons in keys (requires newest nerd font). See `fastfetch -h key-type` for detail. From b24877af0b772ff7fd37eaf7b32be6a9283eab1d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 5 Aug 2024 10:53:28 +0800 Subject: [PATCH 66/67] CMake: Release v2.21.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b51e4370f9..713ec814b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.20.0 + VERSION 2.21.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From 312d4cc5185e183d12bee96c30131f6fa9092ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 5 Aug 2024 13:49:32 +0800 Subject: [PATCH 67/67] Monitor: improve refreshRate formatting --- src/modules/monitor/monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index d83e3431e3..6fdd53eb5c 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -54,7 +54,7 @@ void ffPrintMonitor(FFMonitorOptions* options) printf("%ux%u px", display->width, display->height); if (display->refreshRate > 0) - printf(" @ %.3f Hz", display->refreshRate); + printf(" @ %g Hz", ((int) (display->refreshRate * 1000 + 0.5)) / 1000.0); if (inch > 0) printf(" - %ux%u mm (%.2f inches, %.2f ppi)\n", display->physicalWidth, display->physicalHeight, inch, ppi); else