mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
242 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1006f513f5 | |||
| 652c4b2e82 | |||
| 3c618a8cd0 | |||
| b5821de793 | |||
| dec604691c | |||
| 72baa6cca9 | |||
| 34b023a74f | |||
| 8249a8ed6a | |||
| 7e1ac5e24a | |||
| 55c72a8bb3 | |||
| b602bb20c2 | |||
| 46ed24275f | |||
| 71db83f806 | |||
| 0746afa0c2 | |||
| 805c384819 | |||
| 9e4c0e318c | |||
| 51eaac2fd7 | |||
| 92c3df82e6 | |||
| 7f238a701e | |||
| 72236f62ad | |||
| 51b0c43d76 | |||
| 79e2007d30 | |||
| 02eb604ceb | |||
| ce6b2b85f7 | |||
| 48d1980061 | |||
| 40fae5c5f1 | |||
| e296ee1040 | |||
| 199e71553d | |||
| 13fa218e5a | |||
| eed5efabea | |||
| d2315e967e | |||
| cbe3c70480 | |||
| c918226909 | |||
| 18472660ae | |||
| 458c2ccd01 | |||
| 7bb9efcebb | |||
| 8a42dfd68d | |||
| 3edd8a6740 | |||
| cba22b7155 | |||
| 246ad6d288 | |||
| 295e119810 | |||
| cfe22f9524 | |||
| de2c1d7786 | |||
| 7d74339aa0 | |||
| 7589e962c2 | |||
| 9a189694f9 | |||
| 4069fbfe7b | |||
| 7ccd886909 | |||
| 42957356b2 | |||
| 9038cd32b2 | |||
| 128c3bfea6 | |||
| 60ed822f6a | |||
| 527ec1bc61 | |||
| cbf203901b | |||
| cf6f3dbe0c | |||
| ab625497ce | |||
| 83532b68dd | |||
| cd2a1495b8 | |||
| b01d2bdd8c | |||
| 736d5316cc | |||
| efe42a2c7d | |||
| ee07755139 | |||
| 3d924eeadd | |||
| aaa091f23b | |||
| 53cd1e5378 | |||
| 3747683f0d | |||
| 59c1e3d8c5 | |||
| 1206f6d2ba | |||
| 9aad3e339a | |||
| ef9221f305 | |||
| 391a3a0430 | |||
| 6b0314f14b | |||
| 8e316eb080 | |||
| 999f2170fe | |||
| 0282b884cc | |||
| ef7e6d0a6a | |||
| 77253a8d81 | |||
| 2041272f5f | |||
| d2a41bdfe1 | |||
| 025a708ecb | |||
| 4e2c124442 | |||
| 79ba9d7a68 | |||
| ee60ec3530 | |||
| 9d7cbb0fe3 | |||
| 0b98a14977 | |||
| 8f51763374 | |||
| 28ea765f19 | |||
| 5378d05bfb | |||
| bbf04f0d40 | |||
| ec6195133b | |||
| fa8c99601c | |||
| a5d5de90f8 | |||
| 994fd359a5 | |||
| a9a5790cba | |||
| 31b3fe403a | |||
| 14b74fe51d | |||
| 35a5a03cd7 | |||
| f927b8ea87 | |||
| ebefcec3e2 | |||
| c151bf0b37 | |||
| a767104b96 | |||
| 18fced9b2e | |||
| 713ef0ce34 | |||
| 5b2db02bc1 | |||
| 0f69dc5980 | |||
| 6af57ff5b6 | |||
| 7d7789565b | |||
| 0eb76e9636 | |||
| 8b1ee64a3e | |||
| b0acf168bf | |||
| 7ddc207574 | |||
| d1a791b333 | |||
| 62ca495155 | |||
| e7974a7cea | |||
| 24cb83dd18 | |||
| da5c44b3d0 | |||
| bd71aa931f | |||
| 4d1f242e1d | |||
| d810245d55 | |||
| 06181ec433 | |||
| 8404ae034f | |||
| 8e7d465333 | |||
| 87813b3306 | |||
| 9610a1ab23 | |||
| 5f14781970 | |||
| 356488be0c | |||
| e013c87890 | |||
| 7d78d92a92 | |||
| 06af39835a | |||
| eee8fb78d2 | |||
| 413f91260d | |||
| a44daa04d6 | |||
| d6cb405afe | |||
| b2a853cb6e | |||
| 0168f2e9a8 | |||
| 3992d85eb6 | |||
| 5096180e92 | |||
| 947d2ff0a9 | |||
| 1e4f174415 | |||
| 2808b1a653 | |||
| c749f214e0 | |||
| d0d9831d41 | |||
| b3945e277c | |||
| 9f77851176 | |||
| 963eaa5395 | |||
| 07dfe57386 | |||
| a3c0085e2b | |||
| c8f28e4c79 | |||
| 861eea5899 | |||
| 1227799a38 | |||
| 35d1497053 | |||
| ea3734f004 | |||
| 5d35dade60 | |||
| 0c844fc342 | |||
| c1ed0a4e91 | |||
| e1af6fc0fe | |||
| c1d41a36bb | |||
| 958bde228b | |||
| 6655c446ba | |||
| 43657e8fd6 | |||
| 38f216291e | |||
| 01de158bba | |||
| 5a34b8d01f | |||
| afa0a7dac8 | |||
| 974ee2ab0d | |||
| ab1e3db665 | |||
| 95b64622c4 | |||
| d3c7529c45 | |||
| 89db425a03 | |||
| 269ad36df5 | |||
| 22cdb1247f | |||
| 905ed76ddd | |||
| 6da57d64c3 | |||
| 37e0a7b03f | |||
| 0c65cdc1f5 | |||
| 653e689f18 | |||
| a8aaf605b1 | |||
| 5f638a67ed | |||
| 0645f559af | |||
| f5a57ab747 | |||
| 92e05f7e38 | |||
| 8ba031b761 | |||
| fdb68669f4 | |||
| 12155e029b | |||
| 7926b74917 | |||
| 61af59fc00 | |||
| bc52613410 | |||
| f84bb1ebe2 | |||
| a160bc8de5 | |||
| cb599c6f2a | |||
| 5693700c16 | |||
| e8c067ff3d | |||
| 80cc4e3f4a | |||
| 8e78fadbeb | |||
| 1215eb06ca | |||
| 2aa899d83c | |||
| cf096eb101 | |||
| 5b4a26393d | |||
| 2ba878cbab | |||
| 0af40ab6a3 | |||
| b9777bec77 | |||
| 8801921d02 | |||
| c0c32456e8 | |||
| 640fa146c1 | |||
| de91429e1a | |||
| 1621484c96 | |||
| d8297d296e | |||
| 48bb82c8fb | |||
| c1c7f7b93f | |||
| 1d35811253 | |||
| fe0b43d92d | |||
| 446fe907d2 | |||
| d578f1006c | |||
| 33f3199383 | |||
| 21f3875c4f | |||
| 6bcd75835e | |||
| 24cec76251 | |||
| f8ac56691f | |||
| 810112cb26 | |||
| 2340c2afd7 | |||
| b6c8649cbf | |||
| 92a6b01133 | |||
| 396112e8ea | |||
| 5eacd0bb8e | |||
| ea3ea196aa | |||
| 0e6be69eb8 | |||
| d69e19377e | |||
| f4f466d4ba | |||
| 10b2fe13bd | |||
| b5dc4f59f1 | |||
| 7c0b743c61 | |||
| 6bd909c89d | |||
| 1fef41241a | |||
| 5c75e271ef | |||
| b6b1993f62 | |||
| cd0109c382 | |||
| 6698283430 | |||
| 83ce3e4554 | |||
| ff0f91dc3c | |||
| ab028964bf | |||
| 21353b8256 | |||
| 0a1de91a29 |
@@ -19,7 +19,10 @@ assignees: ''
|
||||
|
||||
# Often helpful information:
|
||||
|
||||
The content of the configuration file you use (if any)
|
||||
Screenshot:
|
||||
<!-- Paste the screenshot here -->
|
||||
|
||||
The content of the configuration file you use (if any):
|
||||
```
|
||||
//paste here
|
||||
```
|
||||
|
||||
+158
-57
@@ -10,7 +10,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install codespell
|
||||
shell: bash
|
||||
@@ -26,7 +26,6 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
compiler: [
|
||||
{ cc: gcc, cxx: "g++" },
|
||||
{ cc: clang, cxx: "clang++" },
|
||||
@@ -37,7 +36,7 @@ jobs:
|
||||
# The feature libraries are all build against glibc, so they can't be used with musl
|
||||
- compiler: { cc: "musl-gcc", cxx: "musl-g++" }
|
||||
enableFeatures: ON
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -46,16 +45,16 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev 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 directx-headers-dev libdrm-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic 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 libddcutil-dev libchafa-dev libdrm-dev directx-headers-dev
|
||||
|
||||
- name: configure project
|
||||
env:
|
||||
CC: ${{ matrix.compiler.cc }}
|
||||
CXX: ${{ matrix.compiler.cxx }}
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} -DENABLE_DRM=${{ matrix.enableFeatures }} .
|
||||
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} -DENABLE_DRM=${{ matrix.enableFeatures }} -DENABLE_DDCUTIL=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build .
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
@@ -72,9 +71,68 @@ jobs:
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-20.04 # 22.04 ships a newer version of glibc than debian stable, allow those people to use the debian package
|
||||
Linux-old-amd64:
|
||||
name: Linux-old-amd64
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
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
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-old-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
runs-on: ubuntu-22.04 # Ubuntu 22.04 uses Glibc 2.35. Should be fine with Debian 12, which uses Glibc 2.36 (https://packages.debian.org/source/bookworm/glibc)
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -88,15 +146,15 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libpci-dev 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 libnm-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick ddcutil --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
@@ -104,10 +162,10 @@ jobs:
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -134,11 +192,46 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux
|
||||
name: fastfetch-linux-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos:
|
||||
name: MacOS
|
||||
linux-aarch64:
|
||||
name: Linux-aarch64
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
id: runcmd
|
||||
with:
|
||||
arch: aarch64
|
||||
distro: ubuntu22.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
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -156,7 +249,7 @@ jobs:
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
@@ -164,10 +257,10 @@ jobs:
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -190,11 +283,11 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos
|
||||
name: fastfetch-macos-universal
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
freebsd:
|
||||
name: FreeBSD
|
||||
freebsd-amd64:
|
||||
name: FreeBSD-amd64
|
||||
runs-on: macos-12
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -211,9 +304,9 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd v4l_compat
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
cmake --build . --target package --verbose
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch
|
||||
time ./fastfetch --format json
|
||||
@@ -224,11 +317,11 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-freebsd
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
win64:
|
||||
name: Win64
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -254,7 +347,7 @@ jobs:
|
||||
run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/bin/{OpenCL,vulkan-1}.dll .
|
||||
@@ -278,19 +371,19 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-amd64.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-amd64.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-win64
|
||||
path: ./fastfetch-*-Win64.*
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-*-windows-amd64.*
|
||||
|
||||
win32:
|
||||
name: Win32
|
||||
windows-i686:
|
||||
name: Windows-i686
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
@@ -313,7 +406,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c, cpp
|
||||
|
||||
@@ -321,10 +414,10 @@ jobs:
|
||||
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
|
||||
@@ -345,27 +438,28 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-i686.zip *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-windows-i686.7z *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-win32
|
||||
path: ./fastfetch-*-Win32.*
|
||||
name: fastfetch-windows-i686
|
||||
path: ./fastfetch-*-windows-i686.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- linux
|
||||
- macos
|
||||
- freebsd
|
||||
- win64
|
||||
- win32
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
- windows-amd64
|
||||
- windows-i686
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -376,38 +470,45 @@ jobs:
|
||||
repository: ${{ github.repository }}
|
||||
|
||||
- name: download artifacts
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: rm old artifacts
|
||||
run: |
|
||||
rm -rf fastfetch-*-old-*
|
||||
|
||||
- name: create release
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
artifactErrorsFailBuild: true
|
||||
artifacts: fastfetch-*/fastfetch-*
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details."
|
||||
|
||||
- name: download source tarballs
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux-amd64.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
|
||||
ls fastfetch-*/*
|
||||
|
||||
- name: generate release notes
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
run: |
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux-amd64.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
|
||||
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
|
||||
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
|
||||
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
|
||||
|
||||
- name: update release body
|
||||
if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
if: needs.linux-amd64.outputs.ffversion != steps.get_version_release.outputs.release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: ${{ needs.linux.outputs.ffversion }}
|
||||
tag: ${{ needs.linux-amd64.outputs.ffversion }}
|
||||
commit: ${{ github.sha }}
|
||||
bodyFile: fastfetch-release-notes.md
|
||||
allowUpdates: true
|
||||
|
||||
+103
@@ -1,3 +1,106 @@
|
||||
# 2.8.2
|
||||
|
||||
Changes:
|
||||
* The linux binaries are now built with glibc 2.35, which means they no longer support Debian 11 and Ubuntu 20.04. Users using these distros may download the artifacts `fastfetch-linux-old` from GitHub Actions.
|
||||
|
||||
Features:
|
||||
* Rewrite GPU module, drop libpci dependency (GPU, Linux)
|
||||
* Detect marketing name of Apple Silicon CPUs for asahi linux (CPU, Linux)
|
||||
* Add new module `Camera`, which prints the name and resolution of connected cameras
|
||||
|
||||
Bugfixes:
|
||||
* Fix compatibility with packages installed by flatpak (Terminal, Linux)
|
||||
* Don't show an empty battery if no battery is detected (macOS, Battery)
|
||||
* Don't show `not connected` if no power adapter is found (macOS / Linux, PowerAdapter)
|
||||
* Make format of battery status be consistent with other platforms (Linux, Battery)
|
||||
|
||||
Logo:
|
||||
* Print Asahi logo in asahi linux (Logo, Linux)
|
||||
* Add Asahi2, z/OS, Tatra, PikaOS
|
||||
|
||||
# 2.7.1
|
||||
|
||||
Features:
|
||||
* Config presets in app folder now work with symlinks
|
||||
|
||||
Bugfixes:
|
||||
* Fix a possible segfault when detecting terminal (Terminal, Linux)
|
||||
|
||||
# 2.7.0
|
||||
|
||||
Features:
|
||||
* Add new module `TerminalTheme`, which prints the foreground and background color of the current terminal window. Currently doesn't work on Windows.
|
||||
* Allow command substitution when expanding paths. For example, now it's possible to use `"source": "$(ls ~/path/to/images/*.png | shuf -n 1)"` in JSONC config file to randomly choose an image to display. (#698)
|
||||
* Use native methods instead of pciutils to detect GPUs in FreeBSD. (GPU, FreeBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fix text formatting (Wifi, Linux)
|
||||
* Fix terminal detection in some cases (Terminal)
|
||||
* Remove trailing `\0` in JSON results (FreeBSD)
|
||||
* Fix uninitialized variables (GPU, Linux)
|
||||
* Fix a possible segfault (OpenCL)
|
||||
|
||||
Logo:
|
||||
* Add ASCII logos for fedora immutable variants (#700)
|
||||
|
||||
# 2.6.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix module not working (Bluetooth)
|
||||
|
||||
# 2.6.2
|
||||
|
||||
Bugfixes:
|
||||
* Fix building for GCC in Windows (Windows)
|
||||
|
||||
# 2.6.1
|
||||
|
||||
Features:
|
||||
* Improve xonsh shell detection (Shell)
|
||||
* Support colored percentage values (Bluetooth / Gamepad / Sound)
|
||||
* Add `--<module>-percent-[green|yellow]` options to specify threshold of percentage colors
|
||||
* eg. `--disk-percent-green 20 --disk-percent-yellow 50` will show green if disk usage is less than 20%, yellow if disk usage is less then 50%, and red otherwise.
|
||||
* Add `--percent-color-[green|yellow|red]` options to specify color of different percent value states.
|
||||
* eg. `--percent-color-green blue` will show blue color if percent value falls in green state.
|
||||
* Improve Intel macbook support (macOS)
|
||||
|
||||
Bugfixes:
|
||||
* Fix segfault in CPU module when running in aarch64 machine without `lscpu` installed (CPU, Linux)
|
||||
* Don't use `login` as terminal process (Terminal, Linux)
|
||||
* Silence warnings when building in 32bit machines.
|
||||
* Create sub folders when writing config file (#690)
|
||||
* Improve user specific locale detection; fix locale detection in Windows 7 (Locale)
|
||||
* Fix GPU type detection (GPU, macOS)
|
||||
|
||||
# 2.6.0
|
||||
|
||||
Changes:
|
||||
* Remove support of option `--battery-dir`. We detect a lot of things in `/sys/class/*` and only module `Battery` supports specifying a custom directory for some reason, which is weird.
|
||||
* Remove `--chassis-use-wmi` which is no longer used.
|
||||
|
||||
Features:
|
||||
* Add `ENABLE_PROPRIETARY_GPU_DRIVER_API` cmake option to disable using of proprietary GPU driver APIs (GPU)
|
||||
* Support wallpaper detection for macOS Sonoma (Wallpaper, macOS)
|
||||
* Support power adapter detection for Asahi Linux (PowerAdapter, Linux)
|
||||
* Support battery serial number and manufacturer date detection (Battery)
|
||||
* Support host serial number and UUID detection (Host)
|
||||
* Support battery level detection for gamepads where possible (Gamepad)
|
||||
* Support maximum CPU clock detection. Previously base clock was printed (CPU, Windows)
|
||||
* Support manufacture date and serial number detection for physical monitors (Monitor)
|
||||
* Support ash (default shell of BusyBox) version detection (Shell, Linux)
|
||||
* Sound module in FreeBSD now uses native `ioctl`s. Pulseaudio dependency is no longer used.
|
||||
* Locale module in Windows now prints the same format as in Linux and other posix systems.
|
||||
|
||||
Bugfixes:
|
||||
* Fix overall memory leaks (macOS)
|
||||
* Remove trailing `\0` in JSON results (FreeBSD)
|
||||
* Fix physical monitor detection with Nvidia drivers (Monitor, Linux)
|
||||
* Don't print llvmpipe in vulkan module (Vulkan)
|
||||
* Fix system yyjson usage in `fastfetch.c`. Previously embedded `3rdparty/yyjson/yyjson.h` was used in `fastfetch.c` even if `ENABLE_SYSTEM_YYJSON` was set (CMake)
|
||||
* Fix locale module printing unexpected results in specific environments (Locale)
|
||||
* Fix battery temperature detection in Windows. Note only smart batteries report temperatures but few laptops uses smart battery (Battery, Windows)
|
||||
* Print device name if no backlight name is available, so we don't print empty parentheses (Brightness, FreeBSD)
|
||||
|
||||
# 2.5.0
|
||||
|
||||
Changes:
|
||||
|
||||
+62
-29
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.5.0
|
||||
VERSION 2.8.2
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -42,7 +42,6 @@ include(CheckIncludeFile)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" 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" OFF)
|
||||
@@ -66,14 +65,14 @@ cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR WIN32" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF)
|
||||
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
option(ENABLE_PROPRIETARY_GPU_DRIVER_API "Enable proprietary GPU driver API (NVML, IGCL and AGS)" ON)
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
|
||||
@@ -109,12 +108,8 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
|
||||
endif()
|
||||
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc")
|
||||
endif()
|
||||
|
||||
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
|
||||
@@ -268,7 +263,7 @@ file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
|
||||
#######################
|
||||
|
||||
set(LIBFASTFETCH_SRC
|
||||
src/common/bar.c
|
||||
src/common/percent.c
|
||||
src/common/commandoption.c
|
||||
src/common/font.c
|
||||
src/common/format.c
|
||||
@@ -290,13 +285,13 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/displayserver/displayserver.c
|
||||
src/detection/font/font.c
|
||||
src/detection/gpu/gpu.c
|
||||
src/detection/locale/locale.c
|
||||
src/detection/media/media.c
|
||||
src/detection/netio/netio.c
|
||||
src/detection/opencl/opencl.c
|
||||
src/detection/os/os.c
|
||||
src/detection/packages/packages.c
|
||||
src/detection/publicip/publicip.c
|
||||
src/detection/terminaltheme/terminaltheme.c
|
||||
src/detection/terminalfont/terminalfont.c
|
||||
src/detection/terminalshell/terminalshell.c
|
||||
src/detection/version/version.c
|
||||
@@ -313,6 +308,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/board/board.c
|
||||
src/modules/brightness/brightness.c
|
||||
src/modules/break/break.c
|
||||
src/modules/camera/camera.c
|
||||
src/modules/chassis/chassis.c
|
||||
src/modules/colors/colors.c
|
||||
src/modules/cpu/cpu.c
|
||||
@@ -352,6 +348,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/swap/swap.c
|
||||
src/modules/media/media.c
|
||||
src/modules/terminal/terminal.c
|
||||
src/modules/terminaltheme/terminaltheme.c
|
||||
src/modules/terminalfont/terminalfont.c
|
||||
src/modules/terminalsize/terminalsize.c
|
||||
src/modules/theme/theme.c
|
||||
@@ -374,7 +371,6 @@ set(LIBFASTFETCH_SRC
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
src/util/platform/FFPlatform.c
|
||||
src/util/stringUtils.c
|
||||
src/util/smbiosHelper.c
|
||||
)
|
||||
|
||||
@@ -405,12 +401,12 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/libc/libc_linux.c
|
||||
src/detection/lm/lm_linux.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_linux.c
|
||||
src/detection/media/media_linux.c
|
||||
@@ -420,7 +416,7 @@ if(LINUX)
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/os/os_linux.c
|
||||
src/detection/packages/packages_linux.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/poweradapter/poweradapter_linux.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
@@ -437,6 +433,7 @@ if(LINUX)
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(ANDROID)
|
||||
@@ -464,6 +461,7 @@ elseif(ANDROID)
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/libc/libc_android.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_nosupport.c
|
||||
src/detection/media/media_nosupport.c
|
||||
@@ -489,6 +487,7 @@ elseif(ANDROID)
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(BSD)
|
||||
@@ -518,13 +517,13 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/xcb.c
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gpu/gpu_bsd.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/lm/lm_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/libc/libc_bsd.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_bsd.c
|
||||
src/detection/media/media_linux.c
|
||||
@@ -537,7 +536,7 @@ elseif(BSD)
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_bsd.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_bsd.c
|
||||
src/detection/swap/swap_bsd.c
|
||||
src/detection/temps/temps_bsd.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
@@ -551,6 +550,7 @@ elseif(BSD)
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
elseif(APPLE)
|
||||
@@ -580,6 +580,7 @@ elseif(APPLE)
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/libc/libc_apple.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_apple.c
|
||||
src/detection/media/media_apple.m
|
||||
@@ -600,11 +601,12 @@ elseif(APPLE)
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_apple.c
|
||||
src/detection/wallpaper/wallpaper_apple.m
|
||||
src/detection/wifi/wifi_apple.m
|
||||
src/detection/wm/wm_apple.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
@@ -620,7 +622,7 @@ elseif(WIN32)
|
||||
src/detection/bluetooth/bluetooth_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/brightness/brightness_windows.cpp
|
||||
src/detection/chassis/chassis_windows.cpp
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
src/detection/cpuusage/cpuusage_windows.c
|
||||
src/detection/cursor/cursor_windows.c
|
||||
@@ -630,13 +632,11 @@ elseif(WIN32)
|
||||
src/detection/displayserver/displayserver_windows.c
|
||||
src/detection/font/font_windows.c
|
||||
src/detection/gpu/gpu_windows.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gpu/gpu_intel.c
|
||||
src/detection/gpu/gpu_amd.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_windows.c
|
||||
src/detection/libc/libc_windows.cpp
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/locale/locale_windows.c
|
||||
src/detection/localip/localip_windows.c
|
||||
src/detection/gamepad/gamepad_windows.c
|
||||
src/detection/media/media_nosupport.c
|
||||
@@ -662,6 +662,7 @@ elseif(WIN32)
|
||||
src/detection/wm/wm_windows.cpp
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/camera/camera_windows.cpp
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
src/util/windows/registry.c
|
||||
@@ -676,6 +677,17 @@ if(ENABLE_DIRECTX_HEADERS)
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp)
|
||||
endif()
|
||||
|
||||
if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32))
|
||||
message(STATUS "Enabling proprietary GPU driver API")
|
||||
if(LINUX OR BSD OR WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
|
||||
endif()
|
||||
if(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c)
|
||||
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(wcwidth HAVE_WCWIDTH)
|
||||
if(NOT HAVE_WCWIDTH)
|
||||
@@ -699,9 +711,20 @@ add_library(libfastfetch OBJECT
|
||||
${LIBFASTFETCH_SRC}
|
||||
)
|
||||
|
||||
if(ENABLE_PROPRIETARY_GPU_DRIVER_API AND (LINUX OR BSD OR WIN32))
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_PROPRIETARY_GPU_DRIVER_API)
|
||||
endif()
|
||||
|
||||
if(yyjson_FOUND)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
|
||||
target_link_libraries(libfastfetch PRIVATE yyjson)
|
||||
target_link_libraries(libfastfetch PRIVATE yyjson::yyjson)
|
||||
# `target_link_libraries(yyjson::yyjson)` sets rpath implicitly
|
||||
else()
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
|
||||
@@ -773,10 +796,6 @@ function(ff_lib_enable VARNAME PKGCONFIG_NAMES CMAKE_NAME)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
ff_lib_enable(LIBPCI
|
||||
"libpci"
|
||||
"Pci"
|
||||
)
|
||||
ff_lib_enable(VULKAN
|
||||
"vulkan"
|
||||
"Vulkan"
|
||||
@@ -899,9 +918,11 @@ if(LINUX)
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "-framework AVFoundation"
|
||||
PRIVATE "-framework Cocoa"
|
||||
PRIVATE "-framework CoreFoundation"
|
||||
PRIVATE "-framework CoreAudio"
|
||||
PRIVATE "-framework CoreMedia"
|
||||
PRIVATE "-framework CoreVideo"
|
||||
PRIVATE "-framework CoreWLAN"
|
||||
PRIVATE "-framework IOBluetooth"
|
||||
@@ -993,6 +1014,13 @@ set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
|
||||
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(yyjson_FOUND)
|
||||
target_compile_definitions(fastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
|
||||
target_link_libraries(fastfetch PRIVATE yyjson::yyjson)
|
||||
target_compile_definitions(flashfetch PRIVATE FF_USE_SYSTEM_YYJSON)
|
||||
target_link_libraries(flashfetch PRIVATE yyjson::yyjson)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(TARGET_NAME fastfetch)
|
||||
target_sources(fastfetch
|
||||
@@ -1079,6 +1107,11 @@ install(
|
||||
##################
|
||||
|
||||
set(CPACK_GENERATOR "TGZ;ZIP")
|
||||
if(APPLE)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-macos-universal" CPACK_PACKAGE_FILE_NAME)
|
||||
else() # We don't use this in Windows
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB;RPM")
|
||||
@@ -1095,7 +1128,7 @@ set(CPACK_SET_DESTDIR ON)
|
||||
set(CPACK_PACKAGE_CONTACT "Linus Dierheimer <Linus@Dierheimer.de>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION "\
|
||||
fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way. \
|
||||
It is written in c to achieve much better performance.\
|
||||
It is written mostly in C to achieve much better performance.\
|
||||
")
|
||||
|
||||
include(CPack)
|
||||
|
||||
@@ -384,7 +384,6 @@ __fastfetch_completion()
|
||||
"--lib-pulse"
|
||||
"--lib-ddcutil"
|
||||
"--lib-nm"
|
||||
"--battery-dir"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_LOGO=(
|
||||
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
fastfetch (2.7.1ubuntu2) jammy; urgency=medium
|
||||
|
||||
* Ignore .git
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 14:23:23 +0800
|
||||
|
||||
fastfetch (2.7.1ubuntu1) jammy; urgency=medium
|
||||
|
||||
* Update build scripts
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 07 Feb 2024 13:53:37 +0800
|
||||
|
||||
fastfetch (2.7.1) jammy; urgency=medium
|
||||
|
||||
* Initial release.
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
12
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libnm-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
Package: fastfetch
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way.
|
||||
It is written mainly in C, with performance and customizability in mind.
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: fastfetch
|
||||
Source: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
Files: *
|
||||
Copyright: 2024 fastfetch-cli
|
||||
License: Expat
|
||||
|
||||
Files: src/3rdparty/yyjson/*
|
||||
Copyright: 2020 YaoYuan
|
||||
License: Expat
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
fastfetch_2.7.1ubuntu2_source.buildinfo universe/utils optional
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
debuild -S -i -I
|
||||
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=cmake+ninja
|
||||
|
||||
override_dh_ctest_configure:
|
||||
dh_ctest_configure -- -DSET_TWEAK=OFF -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
version=4
|
||||
opts="filenamemangle=s%.*/@ANY_VERSION@%@PACKAGE@-$1.tar.gz%,searchmode=plain" \
|
||||
https://api.github.com/repos/fastfetch-cli/fastfetch/releases?per_page=100 \
|
||||
https://api.github.com/repos/fastfetch-cli/fastfetch/tarball/@ANY_VERSION@
|
||||
+134
-21
@@ -26,6 +26,24 @@
|
||||
"format": {
|
||||
"description": "Output format of the module",
|
||||
"type": "string"
|
||||
},
|
||||
"percent": {
|
||||
"description": "Threshold of percentage colors",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"green": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 100,
|
||||
"description": "Value less then green will be shown in green"
|
||||
},
|
||||
"yellow": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 100,
|
||||
"description": "Value greater than green and less then yellow will be shown in yellow.\nValue greater than yellow will be shown in red"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -439,6 +457,24 @@
|
||||
"minimum": 0,
|
||||
"maximum": 9,
|
||||
"default": 0
|
||||
},
|
||||
"color": {
|
||||
"type": "object",
|
||||
"description": "Set color used in different states of percentage bars and numbers",
|
||||
"properties": {
|
||||
"green": {
|
||||
"description": "Color used in green state",
|
||||
"$ref": "#/$defs/colors"
|
||||
},
|
||||
"yellow": {
|
||||
"description": "Color used in yellow state",
|
||||
"$ref": "#/$defs/colors"
|
||||
},
|
||||
"red": {
|
||||
"description": "Color used in red state",
|
||||
"$ref": "#/$defs/colors"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -612,6 +648,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"title",
|
||||
"theme",
|
||||
"uptime",
|
||||
@@ -672,10 +709,6 @@
|
||||
"const": "font",
|
||||
"description": "Print system font name"
|
||||
},
|
||||
{
|
||||
"const": "gamepad",
|
||||
"description": "List connected gamepads"
|
||||
},
|
||||
{
|
||||
"const": "host",
|
||||
"description": "Print product name of your computer"
|
||||
@@ -700,10 +733,6 @@
|
||||
"const": "media",
|
||||
"description": "Print playing song name"
|
||||
},
|
||||
{
|
||||
"const": "memory",
|
||||
"description": "Print system memory usage info"
|
||||
},
|
||||
{
|
||||
"const": "monitor",
|
||||
"description": "Print connected physical monitor information"
|
||||
@@ -732,10 +761,6 @@
|
||||
"const": "shell",
|
||||
"description": "Print current shell name and version"
|
||||
},
|
||||
{
|
||||
"const": "swap",
|
||||
"description": "Print swap (paging file) space usage"
|
||||
},
|
||||
{
|
||||
"const": "terminal",
|
||||
"description": "Print current terminal name and version"
|
||||
@@ -748,6 +773,10 @@
|
||||
"const": "terminalsize",
|
||||
"description": "Print current terminal size"
|
||||
},
|
||||
{
|
||||
"const": "terminaltheme",
|
||||
"description": "Print current terminal theme (foreground and background colors)"
|
||||
},
|
||||
{
|
||||
"const": "theme",
|
||||
"description": "Print current theme of desktop environment"
|
||||
@@ -804,10 +833,6 @@
|
||||
"const": "battery",
|
||||
"description": "Print battery capacity, status, etc"
|
||||
},
|
||||
"dir": {
|
||||
"description": "The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only",
|
||||
"type": "string"
|
||||
},
|
||||
"useSetupApi": {
|
||||
"description": "Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only",
|
||||
"type": "boolean",
|
||||
@@ -818,6 +843,9 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -845,6 +873,9 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -867,6 +898,9 @@
|
||||
"const": "brightness",
|
||||
"description": "Print current brightness level of your monitors"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"ddcciSleep": {
|
||||
"type": "integer",
|
||||
"description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail",
|
||||
@@ -883,11 +917,6 @@
|
||||
"const": "chassis",
|
||||
"description": "Print chassis type (desktop, laptop, etc)"
|
||||
},
|
||||
"useWmi": {
|
||||
"description": "Set if WMI query should be used on Windows, which detects more information but slower",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -943,6 +972,9 @@
|
||||
"const": "cpuusage",
|
||||
"description": "Print CPU usage. Costs some time to collect data"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"separate": {
|
||||
"type": "boolean",
|
||||
"description": "Display CPU usage per CPU logical core, instead of an average result",
|
||||
@@ -1112,6 +1144,9 @@
|
||||
"description": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes",
|
||||
"default": false
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -1179,6 +1214,31 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "Gamepad",
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "gamepad",
|
||||
"description": "List connected gamepads"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "GPU",
|
||||
"properties": {
|
||||
@@ -1281,6 +1341,31 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "Memory",
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "memory",
|
||||
"description": "Print system memory usage info"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "NetIO",
|
||||
"properties": {
|
||||
@@ -1467,6 +1552,34 @@
|
||||
],
|
||||
"default": "main"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
"keyColor": {
|
||||
"$ref": "#/$defs/keyColor"
|
||||
},
|
||||
"keyWidth": {
|
||||
"$ref": "#/$defs/keyWidth"
|
||||
},
|
||||
"format": {
|
||||
"$ref": "#/$defs/format"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"title": "Swap",
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "swap",
|
||||
"description": "Print swap (paging file) space usage"
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
"gpu",
|
||||
@@ -49,6 +50,7 @@
|
||||
"users",
|
||||
"bluetooth",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"weather",
|
||||
"netio",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
"cpu",
|
||||
"cpuusage",
|
||||
"gpu",
|
||||
@@ -55,6 +56,7 @@
|
||||
"users",
|
||||
"bluetooth",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
{
|
||||
"type": "weather",
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
#include "common/bar.h"
|
||||
#include "common/color.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red)
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100 && red <= 100);
|
||||
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksGreen = (uint32_t) (green / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksRed = (uint32_t) (red / 100.0 * options->barWidth + 0.5);
|
||||
assert(blocksPercent <= options->barWidth);
|
||||
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "[ ");
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < blocksPercent; ++i)
|
||||
{
|
||||
if(!options->pipe)
|
||||
{
|
||||
if (i == blocksGreen)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
else if (i == blocksYellow)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
|
||||
else if (i == blocksRed)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
ffStrbufAppend(buffer, &options->barCharElapsed);
|
||||
}
|
||||
|
||||
if (blocksPercent < options->barWidth)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
|
||||
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &options->barCharTotal);
|
||||
}
|
||||
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
// if (green < yellow)
|
||||
// [0, green]: print green
|
||||
// (green, yellow]: print yellow
|
||||
// (yellow, 100]: print red
|
||||
//
|
||||
// if (green > yellow)
|
||||
// [green, 100]: print green
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): PRINT RED
|
||||
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses)
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
if(percent != percent)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
|
||||
else if(green < yellow)
|
||||
{
|
||||
if (percent <= green)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
else if (percent <= yellow)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (percent >= green)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
else if (percent >= yellow)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_YELLOW "m");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
|
||||
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, ')');
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
enum
|
||||
{
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
};
|
||||
|
||||
void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, uint8_t red);
|
||||
void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t yellow, bool parentheses);
|
||||
+1
-1
@@ -57,7 +57,7 @@ static inline uint32_t getArgumentIndex(const FFstrbuf* placeholderValue)
|
||||
uint32_t result = UINT32_MAX;
|
||||
|
||||
if(placeholderValue->chars[0] != '-')
|
||||
sscanf(placeholderValue->chars, "%u", &result);
|
||||
sscanf(placeholderValue->chars, "%" PRIu32, &result);
|
||||
|
||||
return result == 0 ? UINT32_MAX : result;
|
||||
}
|
||||
|
||||
+12
-3
@@ -163,9 +163,6 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_THREADS
|
||||
"threads\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
"libpci\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
@@ -241,9 +238,21 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_DDCUTIL
|
||||
"libddcutil\n"
|
||||
#endif
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
"videodev2\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
"Directx Headers\n"
|
||||
#endif
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
"Proprietary GPU driver API\n"
|
||||
#endif
|
||||
#ifdef FF_USE_SYSTEM_YYJSON
|
||||
"System yyjson\n"
|
||||
#endif
|
||||
#ifdef FF_USE_PCI_MEMORY
|
||||
"PCI memory\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
|
||||
unsigned int mode = fileStat.st_mode & S_IFMT;
|
||||
|
||||
if(pathType & FF_PATHTYPE_FILE && mode == S_IFREG)
|
||||
if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR)
|
||||
return true;
|
||||
|
||||
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
|
||||
|
||||
@@ -115,7 +115,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
#if __has_include(<wordexp.h>) // https://github.com/termux/termux-packages/pull/7056
|
||||
|
||||
wordexp_t exp;
|
||||
if(wordexp(in, &exp, WRDE_NOCMD) != 0)
|
||||
if(wordexp(in, &exp, 0) != 0)
|
||||
return false;
|
||||
|
||||
if (exp.we_wordc == 1)
|
||||
|
||||
@@ -15,6 +15,7 @@ static FFModuleBaseInfo* B[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* C[] = {
|
||||
(void*) &instance.config.modules.camera,
|
||||
(void*) &instance.config.modules.chassis,
|
||||
(void*) &instance.config.modules.command,
|
||||
(void*) &instance.config.modules.colors,
|
||||
@@ -124,6 +125,7 @@ static FFModuleBaseInfo* T[] = {
|
||||
(void*) &instance.config.modules.terminal,
|
||||
(void*) &instance.config.modules.terminalFont,
|
||||
(void*) &instance.config.modules.terminalSize,
|
||||
(void*) &instance.config.modules.terminalTheme,
|
||||
(void*) &instance.config.modules.title,
|
||||
(void*) &instance.config.modules.theme,
|
||||
NULL,
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ void ffOptionParseColor(const char* value, FFstrbuf* buffer)
|
||||
while(*value != '\0')
|
||||
{
|
||||
#define FF_APPEND_COLOR_CODE_COND(prefix, code) \
|
||||
if(strncasecmp(value, #prefix, strlen(#prefix)) == 0) { ffStrbufAppendS(buffer, code); value += strlen(#prefix); }
|
||||
if(ffStrStartsWithIgnCase(value, #prefix)) { ffStrbufAppendS(buffer, code); value += strlen(#prefix); }
|
||||
|
||||
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
|
||||
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/percent.h"
|
||||
#include "common/color.h"
|
||||
#include "common/option.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config)
|
||||
{
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
|
||||
assert(blocksPercent <= options->barWidth);
|
||||
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "[ ");
|
||||
}
|
||||
|
||||
if (percent != percent)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
|
||||
|
||||
for (uint32_t i = 0; i < options->barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &options->barCharElapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* colorGreen = instance.config.display.percentColorGreen.chars;
|
||||
const char* colorYellow = instance.config.display.percentColorYellow.chars;
|
||||
const char* colorRed = instance.config.display.percentColorRed.chars;
|
||||
|
||||
for (uint32_t i = 0; i < blocksPercent; ++i)
|
||||
{
|
||||
if(!options->pipe)
|
||||
{
|
||||
uint32_t section1Begin = (uint32_t) ((green <= yellow ? green : yellow) / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t section2Begin = (uint32_t) ((green > yellow ? green : yellow) / 100.0 * options->barWidth + 0.5);
|
||||
if (i == section2Begin)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", (green > yellow ? colorGreen : colorRed));
|
||||
else if (i == section1Begin)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
|
||||
else if (i == 0)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", (green <= yellow ? colorGreen : colorRed));
|
||||
}
|
||||
ffStrbufAppend(buffer, &options->barCharElapsed);
|
||||
}
|
||||
|
||||
if (blocksPercent < options->barWidth)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
|
||||
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &options->barCharTotal);
|
||||
}
|
||||
}
|
||||
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses)
|
||||
{
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
const char* colorGreen = instance.config.display.percentColorGreen.chars;
|
||||
const char* colorYellow = instance.config.display.percentColorYellow.chars;
|
||||
const char* colorRed = instance.config.display.percentColorRed.chars;
|
||||
|
||||
if(percent != percent)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
|
||||
else if(green <= yellow)
|
||||
{
|
||||
if (percent > yellow)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
|
||||
else if (percent > green)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (percent < yellow)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorRed);
|
||||
else if (percent < green)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorYellow);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "\e[%sm", colorGreen);
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
|
||||
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, ')');
|
||||
}
|
||||
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config)
|
||||
{
|
||||
if (!ffStrStartsWithIgnCase(subkey, "percent-"))
|
||||
return false;
|
||||
|
||||
subkey += strlen("percent-");
|
||||
|
||||
if (ffStrEqualsIgnCase(subkey, "green"))
|
||||
{
|
||||
uint32_t num = ffOptionParseUInt32(key, value);
|
||||
if (num > 100)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
|
||||
exit(480);
|
||||
}
|
||||
config->green = (uint8_t) num;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(subkey, "yellow"))
|
||||
{
|
||||
uint32_t num = ffOptionParseUInt32(key, value);
|
||||
if (num > 100)
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s must be between 0 and 100\n", key);
|
||||
exit(480);
|
||||
}
|
||||
config->yellow = (uint8_t) num;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config)
|
||||
{
|
||||
if (!ffStrEqualsIgnCase(key, "percent"))
|
||||
return false;
|
||||
|
||||
if (!yyjson_is_obj(value))
|
||||
{
|
||||
fprintf(stderr, "Error: usage: %s must be an object\n", key);
|
||||
exit(480);
|
||||
}
|
||||
|
||||
yyjson_val* greenVal = yyjson_obj_get(value, "green");
|
||||
if (greenVal)
|
||||
{
|
||||
int num = yyjson_get_int(greenVal);
|
||||
if (num < 0 || num > 100)
|
||||
{
|
||||
fputs("Error: usage: percent.green must be between 0 and 100\n", stderr);
|
||||
exit(480);
|
||||
}
|
||||
config->green = (uint8_t) num;
|
||||
}
|
||||
|
||||
yyjson_val* yellowVal = yyjson_obj_get(value, "yellow");
|
||||
if (yellowVal)
|
||||
{
|
||||
int num = yyjson_get_int(yellowVal);
|
||||
if (num < 0 || num > 100)
|
||||
{
|
||||
fputs("Error: usage: percent.yellow must be between 0 and 100\n", stderr);
|
||||
exit(480);
|
||||
}
|
||||
config->yellow = (uint8_t) num;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config)
|
||||
{
|
||||
if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow)
|
||||
return;
|
||||
|
||||
yyjson_mut_val* percent = yyjson_mut_obj_add_obj(doc, module, "percent");
|
||||
if (config.green != defaultConfig.green)
|
||||
yyjson_mut_obj_add_uint(doc, percent, "green", config.green);
|
||||
if (config.yellow != defaultConfig.yellow)
|
||||
yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
enum
|
||||
{
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
};
|
||||
|
||||
typedef struct FFPercentConfig
|
||||
{
|
||||
uint8_t green;
|
||||
uint8_t yellow;
|
||||
} FFPercentConfig;
|
||||
|
||||
// if (green <= yellow)
|
||||
// [0, green]: print green
|
||||
// (green, yellow]: print yellow
|
||||
// (yellow, 100]: print red
|
||||
//
|
||||
// if (green > yellow)
|
||||
// [green, 100]: print green
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): print red
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentConfig config);
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentConfig config, bool parentheses);
|
||||
|
||||
typedef struct yyjson_val yyjson_val;
|
||||
typedef struct yyjson_mut_doc yyjson_mut_doc;
|
||||
typedef struct yyjson_mut_val yyjson_mut_val;
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentConfig* config);
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentConfig* config);
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentConfig defaultConfig, FFPercentConfig config);
|
||||
@@ -13,13 +13,6 @@
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
|
||||
static inline void waitpid_wrapper(const pid_t* pid)
|
||||
{
|
||||
// remove zombie processes
|
||||
if (*pid > 0)
|
||||
waitpid(*pid, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int ffPipe2(int *fds, int flags)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
@@ -41,7 +34,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if(ffPipe2(pipes, O_CLOEXEC) == -1)
|
||||
return "pipe() failed";
|
||||
|
||||
__attribute__((__cleanup__(waitpid_wrapper))) pid_t childPid = fork();
|
||||
pid_t childPid = fork();
|
||||
if(childPid == -1)
|
||||
{
|
||||
close(pipes[0]);
|
||||
@@ -74,11 +67,13 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (poll(&pollfd, 1, timeout) == 0)
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout";
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
}
|
||||
}
|
||||
@@ -87,7 +82,19 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (nRead > 0)
|
||||
ffStrbufAppendNS(buffer, (uint32_t) nRead, str);
|
||||
else if (nRead == 0)
|
||||
return NULL;
|
||||
{
|
||||
int stat_loc = 0;
|
||||
if (waitpid(childPid, &stat_loc, 0) == childPid)
|
||||
{
|
||||
if (!WIFEXITED(stat_loc))
|
||||
return "child process exited abnormally";
|
||||
if (WEXITSTATUS(stat_loc) == 127)
|
||||
return "command was not found";
|
||||
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
|
||||
return NULL;
|
||||
}
|
||||
return "waitpid() failed";
|
||||
}
|
||||
else if (nRead < 0)
|
||||
break;
|
||||
};
|
||||
|
||||
@@ -83,8 +83,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
|
||||
char str[FF_PIPE_BUFSIZ];
|
||||
DWORD nRead = 0;
|
||||
FF_AUTO_CLOSE_FD HANDLE hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
OVERLAPPED overlapped = { .hEvent = hEvent };
|
||||
OVERLAPPED overlapped = { };
|
||||
// ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
|
||||
do
|
||||
{
|
||||
@@ -93,11 +92,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
if (!timeout || WaitForSingleObject(hEvent, (DWORD) timeout) != WAIT_OBJECT_0)
|
||||
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "WaitForSingleObject(hEvent) failed or timeout";
|
||||
return "WaitForSingleObject(hChildPipeRead) failed or timeout";
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
|
||||
|
||||
@@ -411,9 +411,8 @@ bool ffSettingsGetFreeBSDKenv(const char* propName, FFstrbuf* result)
|
||||
//https://wiki.ghostbsd.org/index.php/Kenv
|
||||
ffStrbufEnsureFree(result, KENV_MVALLEN);
|
||||
int len = kenv(KENV_GET, propName, result->chars + result->length, KENV_MVALLEN);
|
||||
if (len <= 0) return false;
|
||||
result->length += (uint32_t) len;
|
||||
result->chars[result->length] = '\0';
|
||||
if (len <= 1) return false; // number of bytes copied, including NUL terminator
|
||||
result->length += (uint32_t) len - 1;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -42,6 +42,6 @@ static inline void ffTimeSleep(uint32_t msec)
|
||||
#ifdef _WIN32
|
||||
SleepEx(msec, TRUE);
|
||||
#else
|
||||
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
|
||||
nanosleep(&(struct timespec){ msec / 1000, (long) (msec % 1000) * 1000000 }, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
+56
-19
@@ -198,6 +198,7 @@
|
||||
{
|
||||
"long": "logo-color-[1-9]",
|
||||
"desc": "Overwrite a color in the logo",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color"
|
||||
},
|
||||
@@ -432,6 +433,7 @@
|
||||
{
|
||||
"long": "color-keys",
|
||||
"desc": "Set the color of the keys",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color"
|
||||
}
|
||||
@@ -439,6 +441,7 @@
|
||||
{
|
||||
"long": "color-title",
|
||||
"desc": "Set the color of the title",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color"
|
||||
}
|
||||
@@ -548,6 +551,33 @@
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "percent-color-green",
|
||||
"desc": "Set color used in green state of percentage bars and numbers",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "green"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "percent-color-yellow",
|
||||
"desc": "Set color used in yellow state of percentage bars and numbers",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "light_yellow"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "percent-color-red",
|
||||
"desc": "Set color used in red state of percentage bars and numbers",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "light_red"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "bar-char-elapsed",
|
||||
"desc": "Set the character to use in elapsed part of percentage bars",
|
||||
@@ -821,6 +851,7 @@
|
||||
{
|
||||
"long": "title-color-user",
|
||||
"desc": "Set color of the user name (left part)",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "Use color of \"--color-title\""
|
||||
@@ -829,6 +860,7 @@
|
||||
{
|
||||
"long": "title-color-at",
|
||||
"desc": "Set color of the @ symbol (middle part)",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "Use color of \"--color-title\""
|
||||
@@ -837,21 +869,12 @@
|
||||
{
|
||||
"long": "title-color-host",
|
||||
"desc": "Set color of the host name (right part)",
|
||||
"remark": "See `-h color` for the list of available colors",
|
||||
"arg": {
|
||||
"type": "color",
|
||||
"default": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "chassis-use-wmi",
|
||||
"desc": "Set if WMI query should be used on Windows",
|
||||
"remark": "WMI query detects more information but is slower. Windows only",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "separator-string",
|
||||
"desc": "Set the string printed by the separator module",
|
||||
@@ -1026,15 +1049,6 @@
|
||||
"default": "main"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "battery-dir",
|
||||
"desc": "The directory where the battery folders are",
|
||||
"remark": "Linux only",
|
||||
"arg": {
|
||||
"type": "path",
|
||||
"default": "/sys/class/power_supply/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "battery-use-setup-api",
|
||||
"desc": "Set if \"SetupAPI\" should be used on Windows to detect battery info",
|
||||
@@ -1370,6 +1384,29 @@
|
||||
"type": "num"
|
||||
},
|
||||
"pseudo": true
|
||||
},
|
||||
{
|
||||
"long": "<module>-percent-green",
|
||||
"desc": [
|
||||
"Threshold of percentage colors",
|
||||
"Value less then percent-green will be shown in green"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num"
|
||||
},
|
||||
"pseudo": true
|
||||
},
|
||||
{
|
||||
"long": "<module>-percent-yellow",
|
||||
"desc": [
|
||||
"Threshold of percentage colors",
|
||||
"Value greater than percent-green and less then yellow will be shown in yellow",
|
||||
"Value greater than percent-yellow will be shown in red"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num"
|
||||
},
|
||||
"pseudo": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
typedef struct FFBatteryResult
|
||||
{
|
||||
FFstrbuf manufacturer;
|
||||
FFstrbuf manufactureDate;
|
||||
FFstrbuf modelName;
|
||||
FFstrbuf technology;
|
||||
double capacity;
|
||||
FFstrbuf status;
|
||||
FFstrbuf serial;
|
||||
double capacity;
|
||||
double temperature;
|
||||
uint32_t cycleCount;
|
||||
} FFBatteryResult;
|
||||
|
||||
@@ -40,6 +40,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
|
||||
ffStrbufAppendS(&battery->status, yyjson_get_str(yyjson_obj_get(root, "status")));
|
||||
|
||||
@@ -4,86 +4,104 @@
|
||||
#include "detection/temps/temps_apple.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/pwr_mgt/IOPM.h>
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
|
||||
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
|
||||
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryBattery = registryEntry;
|
||||
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
if (IORegistryEntryCreateCFProperties(entryBattery, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
continue;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSMaxCapacityKey), &maxCapacity) != NULL || maxCapacity <= 0)
|
||||
continue;
|
||||
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSCurrentCapacityKey), ¤tCapacity) != NULL || currentCapacity <= 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
bool boolValue;
|
||||
const char* error;
|
||||
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
battery->capacity = 0.0/0.0;
|
||||
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity)))
|
||||
return error;
|
||||
if (maxCapacity <= 0)
|
||||
return "Querying MaxCapacity failed";
|
||||
|
||||
if ((error = ffCfDictGetInt(properties, CFSTR("CurrentCapacity"), ¤tCapacity)))
|
||||
return error;
|
||||
if(currentCapacity <= 0)
|
||||
return "Querying CurrentCapacity failed";
|
||||
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
battery->capacity = currentCapacity * 100.0 / maxCapacity;
|
||||
|
||||
ffCfDictGetString(properties, CFSTR("DeviceName"), &battery->modelName);
|
||||
ffCfDictGetString(properties, CFSTR(kIOPMDeviceNameKey), &battery->modelName);
|
||||
ffCfDictGetString(properties, CFSTR(kIOPMPSSerialKey), &battery->serial);
|
||||
ffCfDictGetString(properties, CFSTR(kIOPMPSManufacturerKey), &battery->manufacturer);
|
||||
|
||||
if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue)
|
||||
{
|
||||
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
|
||||
if (!battery->manufacturer.length)
|
||||
ffStrbufAppendS(&battery->manufacturer, "Apple Inc.");
|
||||
ffStrbufAppendS(&battery->technology, "Lithium");
|
||||
if (!battery->modelName.length)
|
||||
ffStrbufAppendS(&battery->modelName, "Built-in");
|
||||
}
|
||||
|
||||
int32_t cycleCount = 0;
|
||||
ffCfDictGetInt(properties, CFSTR("CycleCount"), &cycleCount);
|
||||
ffCfDictGetInt(properties, CFSTR(kIOPMPSCycleCountKey), &cycleCount);
|
||||
battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount;
|
||||
|
||||
if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue)
|
||||
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "AC connected, ");
|
||||
else
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue)
|
||||
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if (!ffCfDictGetBool(properties, CFSTR("AtCriticalLevel"), &boolValue) && boolValue)
|
||||
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
int sbdsManufactureDate = 0;
|
||||
if (ffCfDictGetInt(properties, CFSTR(kIOPMPSManufactureDateKey), &sbdsManufactureDate) == NULL)
|
||||
{
|
||||
int day = sbdsManufactureDate & 0b11111;
|
||||
int month = (sbdsManufactureDate >> 5) & 0b1111;
|
||||
int year = (sbdsManufactureDate >> 9) + 1800;
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
|
||||
}
|
||||
else
|
||||
{
|
||||
CFDictionaryRef batteryData;
|
||||
if (ffCfDictGetDict(properties, CFSTR("BatteryData"), &batteryData) == NULL)
|
||||
{
|
||||
char manufactureDate[sizeof(uint64_t)];
|
||||
if (ffCfDictGetInt64(batteryData, CFSTR(kIOPMPSManufactureDateKey), (int64_t*) manufactureDate) == NULL)
|
||||
{
|
||||
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
|
||||
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
|
||||
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
|
||||
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
int64_t temp;
|
||||
if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp))
|
||||
if (!ffCfDictGetInt64(properties, CFSTR(kIOPMPSBatteryTemperatureKey), &temp))
|
||||
battery->temperature = (double) temp / 10 - 273.15;
|
||||
else
|
||||
ffDetectSmcTemps(FF_TEMP_BATTERY, &battery->temperature);
|
||||
}
|
||||
|
||||
IOObjectRelease(registryEntry);
|
||||
}
|
||||
|
||||
IOObjectRelease(iterator);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
battery->capacity = battio.battinfo.cap;
|
||||
if(battio.battinfo.state == ACPI_BATT_STAT_INVALID)
|
||||
@@ -52,13 +54,13 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
else if(battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if(battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
|
||||
ffStrbufAppendS(&battery->status, "Ctritical, ");
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
}
|
||||
|
||||
int acadStatus;
|
||||
if (ioctl(acpifd, ACPIIO_ACAD_GET_STATUS, &acadStatus) >= 0 && acadStatus)
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "AC connected");
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,110 +5,159 @@
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
||||
|
||||
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY testBatteryBuffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
|
||||
|
||||
//type must exist and be "Battery"
|
||||
ffStrbufAppendS(dir, "/type");
|
||||
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||
ffStrbufTrimRightSpace(&testBatteryBuffer);
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0)
|
||||
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery"))
|
||||
return;
|
||||
|
||||
//scope may not exist or must not be "Device"
|
||||
ffStrbufAppendS(dir, "/scope");
|
||||
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||
ffStrbufTrimRightSpace(&testBatteryBuffer);
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
|
||||
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
|
||||
return;
|
||||
|
||||
FFBatteryResult* result = ffListAdd(results);
|
||||
|
||||
//capacity must exist and be not empty
|
||||
ffStrbufAppendS(dir, "/capacity");
|
||||
bool available = ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if(available)
|
||||
result->capacity = ffStrbufToDouble(&testBatteryBuffer);
|
||||
|
||||
if(!available)
|
||||
{
|
||||
result->capacity = 0.0/0.0;
|
||||
--results->length;
|
||||
if (!available)
|
||||
return;
|
||||
}
|
||||
|
||||
FFBatteryResult* result = ffListAdd(results);
|
||||
result->capacity = ffStrbufToDouble(&tmpBuffer);
|
||||
|
||||
//At this point, we have a battery. Try to get as much values as possible.
|
||||
|
||||
ffStrbufInit(&result->manufacturer);
|
||||
ffStrbufAppendS(dir, "/manufacturer");
|
||||
ffReadFileBuffer(dir->chars, &result->manufacturer);
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
else if (ffStrEquals(id, "macsmc-battery")) // asahi
|
||||
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->modelName);
|
||||
ffStrbufAppendS(dir, "/model_name");
|
||||
ffReadFileBuffer(dir->chars, &result->modelName);
|
||||
ffStrbufTrimRightSpace(&result->modelName);
|
||||
if (ffReadFileBuffer(dir->chars, &result->modelName))
|
||||
ffStrbufTrimRightSpace(&result->modelName);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->technology);
|
||||
ffStrbufAppendS(dir, "/technology");
|
||||
ffReadFileBuffer(dir->chars, &result->technology);
|
||||
ffStrbufTrimRightSpace(&result->technology);
|
||||
if (ffReadFileBuffer(dir->chars, &result->technology))
|
||||
ffStrbufTrimRightSpace(&result->technology);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->status);
|
||||
ffStrbufAppendS(dir, "/status");
|
||||
ffReadFileBuffer(dir->chars, &result->status);
|
||||
ffStrbufTrimRightSpace(&result->status);
|
||||
if (ffReadFileBuffer(dir->chars, &result->status))
|
||||
ffStrbufTrimRightSpace(&result->status);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
// Unknown, Charging, Discharging, Not charging, Full
|
||||
if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
|
||||
ffStrbufSetStatic(&result->status, "AC Connected");
|
||||
else if (ffStrbufEqualS(&result->status, "Unknown"))
|
||||
ffStrbufClear(&result->status);
|
||||
|
||||
ffStrbufAppendS(dir, "/capacity_level");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
|
||||
{
|
||||
if (result->status.length)
|
||||
ffStrbufAppendS(&result->status, ", Critical");
|
||||
else
|
||||
ffStrbufSetStatic(&result->status, "Critical");
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->serial);
|
||||
ffStrbufAppendS(dir, "/serial_number");
|
||||
if (ffReadFileBuffer(dir->chars, &result->serial))
|
||||
ffStrbufTrimRightSpace(&result->serial);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufAppendS(dir, "/cycle_count");
|
||||
ffReadFileBuffer(dir->chars, &testBatteryBuffer);
|
||||
ffStrbufTrimRightSpace(&testBatteryBuffer);
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (dir->length)
|
||||
if (available)
|
||||
{
|
||||
int64_t cycleCount = 0;
|
||||
cycleCount = (int64_t) strtoll(testBatteryBuffer.chars, NULL, 10);
|
||||
int64_t cycleCount = ffStrbufToSInt(&tmpBuffer, 0);
|
||||
result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount;
|
||||
}
|
||||
|
||||
ffStrbufInit(&result->manufactureDate);
|
||||
ffStrbufAppendS(dir, "/manufacture_year");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
{
|
||||
int year = (int) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (year > 0)
|
||||
{
|
||||
ffStrbufAppendS(dir, "/manufacture_month");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
{
|
||||
int month = (int) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (month > 0)
|
||||
{
|
||||
ffStrbufAppendS(dir, "/manufacture_day");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
{
|
||||
int day = (int) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (day > 0)
|
||||
{
|
||||
ffStrbufSetF(&result->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
if (options->temp)
|
||||
{
|
||||
const FFlist* tempsResult = ffDetectTemps();
|
||||
|
||||
FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult)
|
||||
{
|
||||
if (ffStrbufEqualS(&value->deviceName, id))
|
||||
{
|
||||
result->temperature = value->value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ffStrbufAppendS(dir, "/temp");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
result->temperature = ffStrbufToDouble(&tmpBuffer) / 10;
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppend(&baseDir, &options->dir);
|
||||
ffStrbufEnsureEndsWithC(&baseDir, '/');
|
||||
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
|
||||
|
||||
uint32_t baseDirLength = baseDir.length;
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
|
||||
if(dirp == NULL)
|
||||
return "opendir(batteryDir) == NULL";
|
||||
return "opendir(\"/sys/class/power_supply/\") == NULL";
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
@@ -122,7 +171,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
}
|
||||
|
||||
if(results->length == 0)
|
||||
return "batteryDir doesn't contain any battery folder";
|
||||
return "\"/sys/class/power_supply/\" doesn't contain any battery folder";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "battery.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
@@ -75,19 +76,19 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
|
||||
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lead Acid");
|
||||
ffStrbufInitStatic(&battery->technology, "Lead Acid");
|
||||
else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Lithium Ion");
|
||||
ffStrbufInitStatic(&battery->technology, "Lithium Ion");
|
||||
else if(memcmp(bi.Chemistry, "NiCd", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Cadmium");
|
||||
ffStrbufInitStatic(&battery->technology, "Nickel Cadmium");
|
||||
else if(memcmp(bi.Chemistry, "NiMH", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Metal Hydride");
|
||||
ffStrbufInitStatic(&battery->technology, "Nickel Metal Hydride");
|
||||
else if(memcmp(bi.Chemistry, "NiZn", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Nickel Zinc");
|
||||
ffStrbufInitStatic(&battery->technology, "Nickel Zinc");
|
||||
else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0)
|
||||
ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese");
|
||||
ffStrbufInitStatic(&battery->technology, "Rechargeable Alkaline-Manganese");
|
||||
else
|
||||
ffStrbufInitS(&battery->technology, "Unknown");
|
||||
ffStrbufInitStatic(&battery->technology, "Unknown");
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->modelName);
|
||||
@@ -105,6 +106,22 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
ffStrbufSetWS(&battery->manufacturer, name);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
bqi.InformationLevel = BatteryManufactureDate;
|
||||
BATTERY_MANUFACTURE_DATE date;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year + 1900, date.Month, date.Day);
|
||||
}
|
||||
|
||||
{
|
||||
ffStrbufInit(&battery->serial);
|
||||
bqi.InformationLevel = BatterySerialNumber;
|
||||
wchar_t name[64];
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL))
|
||||
ffStrbufSetWS(&battery->serial, name);
|
||||
}
|
||||
|
||||
battery->cycleCount = bi.CycleCount;
|
||||
|
||||
battery->temperature = 0.0/0.0;
|
||||
@@ -113,7 +130,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
bqi.InformationLevel = BatteryTemperature;
|
||||
ULONG temp;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL))
|
||||
battery->temperature = temp;
|
||||
battery->temperature = temp / 10.0 - 273.15;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -140,6 +157,83 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct FFSmbiosPortableBattery
|
||||
{
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
// 2.1+
|
||||
uint8_t Location; // string
|
||||
uint8_t Manufacturer; // string
|
||||
uint8_t ManufactureDate; // string
|
||||
uint8_t SerialNumber; // string
|
||||
uint8_t DeviceName; // string
|
||||
uint8_t DeviceChemistry; // enum
|
||||
uint16_t DesignCapacity; // varies
|
||||
uint16_t DesignVoltage; // varies
|
||||
uint8_t SbdsVersionNumber; // string
|
||||
uint8_t MaximumErrorInBatteryData; // varies
|
||||
|
||||
// 2.2+
|
||||
uint16_t SbdsSerialNumber; // varies
|
||||
uint16_t SbdsManufactureDate; // varies
|
||||
uint8_t SbdsDeviceChemistry; // string
|
||||
uint8_t DesignCapacityMultiplier; // varies
|
||||
uint16_t OEMSpecific; // varies
|
||||
} FFSmbiosPortableBattery;
|
||||
|
||||
const char* detectBySmbios(FFBatteryResult* battery)
|
||||
{
|
||||
const FFSmbiosPortableBattery* data = (const FFSmbiosPortableBattery*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PORTABLE_BATTERY];
|
||||
if (!data)
|
||||
return "Portable battery section is not found in SMBIOS data";
|
||||
|
||||
const char* strings = (const char*) data + data->Header.Length;
|
||||
|
||||
ffStrbufSetStatic(&battery->modelName, ffSmbiosLocateString(strings, data->DeviceName));
|
||||
ffCleanUpSmbiosValue(&battery->modelName);
|
||||
ffStrbufSetStatic(&battery->manufacturer, ffSmbiosLocateString(strings, data->Manufacturer));
|
||||
ffCleanUpSmbiosValue(&battery->manufacturer);
|
||||
|
||||
if (data->ManufactureDate)
|
||||
{
|
||||
ffStrbufSetStatic(&battery->manufactureDate, ffSmbiosLocateString(strings, data->ManufactureDate));
|
||||
ffCleanUpSmbiosValue(&battery->manufactureDate);
|
||||
}
|
||||
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsManufactureDate))
|
||||
{
|
||||
int day = data->SbdsManufactureDate & 0b11111;
|
||||
int month = (data->SbdsManufactureDate >> 5) & 0b1111;
|
||||
int year = (data->SbdsManufactureDate >> 9) + 1800;
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
|
||||
}
|
||||
|
||||
switch (data->DeviceChemistry)
|
||||
{
|
||||
case 0x01: ffStrbufSetStatic(&battery->technology, "Other"); break;
|
||||
case 0x02: ffStrbufSetStatic(&battery->technology, "Unknown"); break;
|
||||
case 0x03: ffStrbufSetStatic(&battery->technology, "Lead Acid"); break;
|
||||
case 0x04: ffStrbufSetStatic(&battery->technology, "Nickel Cadmium"); break;
|
||||
case 0x05: ffStrbufSetStatic(&battery->technology, "Nickel metal hydride"); break;
|
||||
case 0x06: ffStrbufSetStatic(&battery->technology, "Lithium-ion"); break;
|
||||
case 0x07: ffStrbufSetStatic(&battery->technology, "Zinc air"); break;
|
||||
case 0x08: ffStrbufSetStatic(&battery->technology, "Lithium Polymer"); break;
|
||||
}
|
||||
|
||||
if (data->SerialNumber)
|
||||
{
|
||||
ffStrbufSetStatic(&battery->serial, ffSmbiosLocateString(strings, data->SerialNumber));
|
||||
ffCleanUpSmbiosValue(&battery->serial);
|
||||
}
|
||||
else if (data->Header.Length > offsetof(FFSmbiosPortableBattery, SbdsSerialNumber))
|
||||
{
|
||||
ffStrbufSetF(&battery->serial, "%4X", data->SbdsSerialNumber);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
SYSTEM_BATTERY_STATE info;
|
||||
@@ -148,8 +242,10 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->serial);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
|
||||
@@ -162,6 +258,9 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
}
|
||||
else if(info.Discharging)
|
||||
ffStrbufAppendS(&battery->status, "Discharging");
|
||||
|
||||
detectBySmbios(battery);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return "NtPowerInformation(SystemBatteryState) failed";
|
||||
@@ -169,7 +268,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
return true
|
||||
return options->useSetupApi
|
||||
? detectWithSetupApi(options, results)
|
||||
: detectWithNtApi(options, results);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* result)
|
||||
@@ -15,5 +16,18 @@ const char* ffDetectBios(FFBiosResult* result)
|
||||
ffSettingsGetFreeBSDKenv("smbios.bios.version", &result->version);
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
ffSysctlGetString("machdep.bootmethod", &result->type);
|
||||
|
||||
if (result->type.length == 0)
|
||||
{
|
||||
if (ffSettingsGetFreeBSDKenv("loader.efi", &result->type))
|
||||
ffStrbufSetStatic(&result->type, ffStrbufEqualS(&result->type, "1") ? "UEFI" : "BIOS");
|
||||
else
|
||||
{
|
||||
ffStrbufSetStatic(&result->type,
|
||||
ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) ||
|
||||
ffPathExists("/boot/efi/efi" /*efi partition*/, FF_PATHTYPE_DIRECTORY)
|
||||
? "UEFI" : "BIOS");
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "bios.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
#include <ntstatus.h>
|
||||
@@ -26,27 +25,46 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
|
||||
};
|
||||
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
|
||||
|
||||
|
||||
typedef struct FFSmbiosBios
|
||||
{
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
uint8_t Vendor; // string
|
||||
uint8_t BiosVersion; // string
|
||||
uint16_t BiosStartingAddressSegment; // varies
|
||||
uint8_t BiosReleaseDate; // string
|
||||
uint8_t BiosRomSize; // string
|
||||
uint32_t BiosCharacteristics; // bit field
|
||||
|
||||
// 2.4+
|
||||
uint8_t BiosCharacteristicsExtensionBytes[2]; // bit field
|
||||
uint8_t SystemBiosMajorRelease; // varies
|
||||
uint8_t SystemBiosMinorRelease; // varies
|
||||
uint8_t EmbeddedControllerFirmwareMajorRelease; // varies
|
||||
uint8_t EmbeddedControllerFirmwareMinorRelease; // varies
|
||||
|
||||
// 3.1+
|
||||
uint16_t ExtendedBiosRomSize; // bit field
|
||||
} FFSmbiosBios;
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
|
||||
const FFSmbiosBios* data = (const FFSmbiosBios*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_BIOS];
|
||||
if (!data)
|
||||
return "BIOS section is not found in SMBIOS data";
|
||||
|
||||
if(!ffRegReadStrbuf(hKey, L"BIOSVersion", &bios->version, NULL))
|
||||
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\BIOSVersion\" doesn't exist";
|
||||
const char* strings = (const char*) data + data->Header.Length;
|
||||
|
||||
ffStrbufSetStatic(&bios->version, ffSmbiosLocateString(strings, data->BiosVersion));
|
||||
ffCleanUpSmbiosValue(&bios->version);
|
||||
ffRegReadStrbuf(hKey, L"BIOSVendor", &bios->vendor, NULL);
|
||||
ffStrbufSetStatic(&bios->vendor, ffSmbiosLocateString(strings, data->Vendor));
|
||||
ffCleanUpSmbiosValue(&bios->vendor);
|
||||
ffRegReadStrbuf(hKey, L"BIOSReleaseDate", &bios->date, NULL);
|
||||
ffStrbufSetStatic(&bios->date, ffSmbiosLocateString(strings, data->BiosReleaseDate));
|
||||
ffCleanUpSmbiosValue(&bios->date);
|
||||
|
||||
uint32_t major, minor;
|
||||
if(
|
||||
ffRegReadUint(hKey, L"BiosMajorRelease", &major, NULL) &&
|
||||
ffRegReadUint(hKey, L"BiosMinorRelease", &minor, NULL)
|
||||
)
|
||||
ffStrbufAppendF(&bios->release, "%u.%u", (unsigned)major, (unsigned)minor);
|
||||
if (data->Header.Length > offsetof(FFSmbiosBios, SystemBiosMajorRelease))
|
||||
ffStrbufSetF(&bios->release, "%u.%u", data->SystemBiosMajorRelease, data->SystemBiosMinorRelease);
|
||||
|
||||
// Same as GetFirmwareType, but support (?) Windows 7
|
||||
// https://ntdoc.m417z.com/system_information_class
|
||||
|
||||
@@ -7,6 +7,7 @@ typedef struct FFBoardResult
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf version;
|
||||
FFstrbuf serial;
|
||||
} FFBoardResult;
|
||||
|
||||
const char* ffDetectBoard(FFBoardResult* board);
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
#include "board.h"
|
||||
|
||||
#include "common/sysctl.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
const char* ffDetectBoard(FFBoardResult* result)
|
||||
{
|
||||
const char* error = ffSysctlGetString("hw.model", &result->name);
|
||||
if (error)
|
||||
return error;
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice"));
|
||||
if (!service)
|
||||
return "No IOPlatformExpertDevice found";
|
||||
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
|
||||
ffStrbufSetS(&result->name, name);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
|
||||
if (manufacturer)
|
||||
ffCfStrGetString(manufacturer, &result->vendor);
|
||||
|
||||
ffStrbufSetStatic(&result->vendor, "Apple");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ const char* ffDetectBoard(FFBoardResult* result)
|
||||
{
|
||||
ffSettingsGetFreeBSDKenv("smbios.planar.product", &result->name);
|
||||
ffCleanUpSmbiosValue(&result->name);
|
||||
ffSettingsGetFreeBSDKenv("smbios.planar.serial", &result->serial);
|
||||
ffCleanUpSmbiosValue(&result->serial);
|
||||
ffSettingsGetFreeBSDKenv("smbios.planar.maker", &result->vendor);
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
ffSettingsGetFreeBSDKenv("smbios.planar.version", &result->version);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
const char* ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_serial", "/sys/class/dmi/id/board_serial", &board->serial);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
|
||||
return NULL;
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
#include "board.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
typedef struct FFSmbiosBaseboard
|
||||
{
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
uint8_t Manufacturer; // string
|
||||
uint8_t Product; // string
|
||||
uint8_t Version; // string
|
||||
uint8_t SerialNumber; // string
|
||||
uint8_t AssetTag; // string
|
||||
uint8_t FeatureFlags; // bit field
|
||||
uint8_t LocationInChassis; // string
|
||||
uint16_t ChassisHandle; // varies
|
||||
uint8_t BoardType; // enum
|
||||
uint8_t NumberOfContainedObjectHandle; // varies
|
||||
uint16_t ContainedObjectHandle[]; // varies
|
||||
} FFSmbiosBaseboard;
|
||||
|
||||
const char* ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
const FFSmbiosBaseboard* data = (const FFSmbiosBaseboard*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_BASEBOARD_INFO];
|
||||
if (!data)
|
||||
return "Baseboard information section is not found in SMBIOS data";
|
||||
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\") failed";
|
||||
|
||||
if(!ffRegReadStrbuf(hKey, L"BaseBoardProduct", &board->name, NULL))
|
||||
return "ffRegReadStrbuf(hKey, L\"BaseBoardProduct\") failed";
|
||||
const char* strings = (const char*) data + data->Header.Length;
|
||||
|
||||
ffStrbufSetStatic(&board->name, ffSmbiosLocateString(strings, data->Product));
|
||||
ffCleanUpSmbiosValue(&board->name);
|
||||
ffRegReadStrbuf(hKey, L"BaseBoardManufacturer", &board->vendor, NULL);
|
||||
ffStrbufSetStatic(&board->serial, ffSmbiosLocateString(strings, data->SerialNumber));
|
||||
ffCleanUpSmbiosValue(&board->serial);
|
||||
ffStrbufSetStatic(&board->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
|
||||
ffCleanUpSmbiosValue(&board->vendor);
|
||||
ffRegReadStrbuf(hKey, L"BaseBoardVersion", &board->version, NULL);
|
||||
ffStrbufSetStatic(&board->version, ffSmbiosLocateString(strings, data->Version));
|
||||
ffCleanUpSmbiosValue(&board->version);
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -57,35 +57,35 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
|
||||
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
|
||||
return "IOAVService is not available";
|
||||
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
|
||||
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
|
||||
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = NULL;
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
continue;
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryAv = registryEntry;
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFBooleanRef IOAVServiceUserInterfaceSupported = IORegistryEntryCreateCFProperty(entryAv, CFSTR("IOAVServiceUserInterfaceSupported"), kCFAllocatorDefault, kNilOptions);
|
||||
if (IOAVServiceUserInterfaceSupported && !CFBooleanGetValue(IOAVServiceUserInterfaceSupported))
|
||||
{
|
||||
// IOAVServiceCreateWithService won't work
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef location = IORegistryEntryCreateCFProperty(entryAv, CFSTR("Location"), kCFAllocatorDefault, kNilOptions);
|
||||
if (location && CFStringCompare(location, CFSTR("Embedded"), 0) == 0)
|
||||
{
|
||||
// Builtin display should be handled by DisplayServices
|
||||
continue;
|
||||
}
|
||||
|
||||
service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
|
||||
if (!service) continue;
|
||||
}
|
||||
|
||||
ffStrbufClear(&location);
|
||||
if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded"))
|
||||
{
|
||||
// Builtin display should be handled by DisplayServices
|
||||
IOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
|
||||
IOObjectRelease(registryEntry);
|
||||
|
||||
if (!service) continue;
|
||||
|
||||
{
|
||||
uint8_t i2cIn[4] = { 0x82, 0x01, 0x10 /* luminance */ };
|
||||
i2cIn[3] = 0x6e ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2];
|
||||
|
||||
@@ -36,6 +36,8 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
struct backlight_info info;
|
||||
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
|
||||
ffStrbufAppendS(&brightness->name, info.name);
|
||||
else
|
||||
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFCameraResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf id;
|
||||
FFstrbuf colorspace;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} FFCameraResult;
|
||||
|
||||
const char* ffDetectCamera(FFlist* result /* list of FFCameraResult */);
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "camera.h"
|
||||
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
#define FF_TERMUX_API_PATH FASTFETCH_TARGET_DIR_ROOT "/libexec/termux-api"
|
||||
#define FF_TERMUX_API_PARAM "CameraInfo"
|
||||
|
||||
static inline void wrapYyjsonFree(yyjson_doc** doc)
|
||||
{
|
||||
assert(doc);
|
||||
if (*doc)
|
||||
yyjson_doc_free(*doc);
|
||||
}
|
||||
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
if(ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
FF_TERMUX_API_PATH,
|
||||
FF_TERMUX_API_PARAM,
|
||||
NULL
|
||||
}))
|
||||
return "Starting `" FF_TERMUX_API_PATH " " FF_TERMUX_API_PARAM "` failed";
|
||||
|
||||
yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(buffer.chars, buffer.length, 0, NULL, NULL);
|
||||
if (!doc)
|
||||
return "Failed to parse camera info";
|
||||
|
||||
yyjson_val* root = yyjson_doc_get_root(doc);
|
||||
if (!yyjson_is_arr(root))
|
||||
return "Camera info result is not a JSON array";
|
||||
|
||||
yyjson_val* device;
|
||||
size_t idx, max;
|
||||
yyjson_arr_foreach(root, idx, max, device)
|
||||
{
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
{
|
||||
const char* facing = yyjson_get_str(yyjson_obj_get(device, "facing"));
|
||||
if (facing)
|
||||
ffStrbufInitF(&camera->name, "builtin-%s", facing);
|
||||
else
|
||||
ffStrbufInitStatic(&camera->name, "Unknown");
|
||||
}
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInitS(&camera->id, yyjson_get_str(yyjson_obj_get(device, "id")));
|
||||
yyjson_val* sizes = yyjson_arr_get_first(yyjson_obj_get(device, "jpeg_output_sizes"));
|
||||
if (yyjson_is_obj(sizes))
|
||||
{
|
||||
camera->width = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "width"));
|
||||
camera->height = (uint32_t) yyjson_get_uint(yyjson_obj_get(sizes, "height"));
|
||||
}
|
||||
else
|
||||
camera->width = camera->height = 0;
|
||||
ffStrbufInit(&camera->colorspace);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "camera.h"
|
||||
|
||||
#import <AVFoundation/AVCaptureDevice.h>
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified];
|
||||
if (!session)
|
||||
return "Failed to create AVCaptureDeviceDiscoverySession";
|
||||
|
||||
for (AVCaptureDevice* device in session.devices)
|
||||
{
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&camera->name, device.localizedName.UTF8String);
|
||||
ffStrbufInitS(&camera->vendor, device.manufacturer.UTF8String);
|
||||
ffStrbufInitS(&camera->id, device.uniqueID.UTF8String);
|
||||
switch (device.activeColorSpace)
|
||||
{
|
||||
case AVCaptureColorSpace_sRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case AVCaptureColorSpace_P3_D65: ffStrbufInitStatic(&camera->colorspace, "P3-D65"); break;
|
||||
case 2 /*AVCaptureColorSpace_HLG_BT2020*/: ffStrbufInitStatic(&camera->colorspace, "BT2020-HLG"); break;
|
||||
case 3 /*AVCaptureColorSpace_AppleLog*/: ffStrbufInitStatic(&camera->colorspace, "AppleLog"); break;
|
||||
}
|
||||
|
||||
CMVideoDimensions size = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription);
|
||||
camera->width = size.width < 0 ? 0 : (uint32_t) size.width;
|
||||
camera->height = size.height < 0 ? 0 : (uint32_t) size.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "camera.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
#include <linux/videodev2.h>
|
||||
#endif
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
#if __has_include(<linux/videodev2.h>)
|
||||
char path[] = "/dev/videoN";
|
||||
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
path[sizeof(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
break;
|
||||
|
||||
struct v4l2_capability cap = {};
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
continue;
|
||||
|
||||
struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
|
||||
if (ioctl(fd, VIDIOC_G_FMT, &fmt) < 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&camera->name, (const char*) cap.card);
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInitS(&camera->id, (const char*) cap.bus_info);
|
||||
switch (fmt.fmt.pix.colorspace)
|
||||
{
|
||||
case V4L2_COLORSPACE_SMPTE170M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 170M"); break;
|
||||
case V4L2_COLORSPACE_SMPTE240M: ffStrbufInitStatic(&camera->colorspace, "SMPTE 240M"); break;
|
||||
case V4L2_COLORSPACE_BT878: ffStrbufInitStatic(&camera->colorspace, "BT.808"); break;
|
||||
case V4L2_COLORSPACE_470_SYSTEM_M: ffStrbufInitStatic(&camera->colorspace, "NTSC"); break;
|
||||
case V4L2_COLORSPACE_470_SYSTEM_BG: ffStrbufInitStatic(&camera->colorspace, "EBU 3213"); break;
|
||||
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
|
||||
case V4L2_COLORSPACE_REC709:
|
||||
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case V4L2_COLORSPACE_OPRGB: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
|
||||
case V4L2_COLORSPACE_BT2020: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case V4L2_COLORSPACE_RAW: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
|
||||
case V4L2_COLORSPACE_DCI_P3: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
default: ffStrbufInit(&camera->colorspace); break;
|
||||
}
|
||||
camera->width = fmt.fmt.pix.width;
|
||||
camera->height = fmt.fmt.pix.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(result);
|
||||
return "Fastfetch was compiled without <linux/videodev2.h>";
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
extern "C" {
|
||||
#include "camera.h"
|
||||
#include "common/library.h"
|
||||
}
|
||||
#include "util/windows/com.hpp"
|
||||
#include "util/windows/unicode.hpp"
|
||||
|
||||
#include <initguid.h>
|
||||
#include <mfapi.h>
|
||||
#include <mfidl.h>
|
||||
|
||||
template <typename Fn>
|
||||
struct on_scope_exit {
|
||||
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
|
||||
~on_scope_exit() { this->_fn(); }
|
||||
|
||||
private:
|
||||
Fn _fn;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(mfplat, NULL, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
|
||||
FF_LIBRARY_LOAD(mf, NULL, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
|
||||
|
||||
const char* error = ffInitCom();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
IMFAttributes* FF_AUTO_RELEASE_COM_OBJECT attrs = nullptr;
|
||||
if (FAILED(ffMFCreateAttributes(&attrs, 1)))
|
||||
return "MFCreateAttributes() failed";
|
||||
|
||||
if (FAILED(attrs->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
)))
|
||||
return "SetGUID(MF_*) failed";
|
||||
|
||||
IMFActivate** devices = NULL;
|
||||
uint32_t count;
|
||||
|
||||
if (FAILED(ffMFEnumDeviceSources(attrs, &devices, &count)))
|
||||
return "MFEnumDeviceSources() failed";
|
||||
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
IMFActivate* device = devices[i];
|
||||
|
||||
wchar_t buffer[256];
|
||||
uint32_t length = 0;
|
||||
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
ffStrbufInitNWS(&camera->name, length, buffer);
|
||||
ffStrbufInit(&camera->colorspace);
|
||||
ffStrbufInit(&camera->vendor);
|
||||
ffStrbufInit(&camera->id);
|
||||
camera->width = 0;
|
||||
camera->height = 0;
|
||||
|
||||
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0)
|
||||
ffStrbufSetNWS(&camera->id, length, buffer);
|
||||
|
||||
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
|
||||
if (FAILED(device->ActivateObject(IID_PPV_ARGS(&source))))
|
||||
continue;
|
||||
|
||||
on_scope_exit destroySource([&] { source->Shutdown(); });
|
||||
|
||||
IMFPresentationDescriptor* FF_AUTO_RELEASE_COM_OBJECT pd = nullptr;
|
||||
if (FAILED(source->CreatePresentationDescriptor(&pd)))
|
||||
continue;
|
||||
|
||||
IMFStreamDescriptor* FF_AUTO_RELEASE_COM_OBJECT sd = NULL;
|
||||
BOOL selected;
|
||||
if (FAILED(pd->GetStreamDescriptorByIndex(0, &selected, &sd)))
|
||||
continue;
|
||||
|
||||
IMFMediaTypeHandler* FF_AUTO_RELEASE_COM_OBJECT handler = NULL;
|
||||
if (FAILED(sd->GetMediaTypeHandler(&handler)))
|
||||
continue;
|
||||
|
||||
DWORD mediaTypeCount;
|
||||
if (FAILED(handler->GetMediaTypeCount(&mediaTypeCount)))
|
||||
continue;
|
||||
|
||||
// Assume first type is the maximum resolution
|
||||
IMFMediaType* FF_AUTO_RELEASE_COM_OBJECT type = NULL;
|
||||
for (DWORD idx = 0; SUCCEEDED(handler->GetMediaTypeByIndex(idx, &type)); ++idx)
|
||||
{
|
||||
GUID majorType;
|
||||
if (FAILED(type->GetMajorType(&majorType)) || majorType != MFMediaType_Video)
|
||||
continue;
|
||||
|
||||
MFVideoPrimaries primaries;
|
||||
static_assert(sizeof(primaries) == sizeof(uint32_t), "");
|
||||
if (SUCCEEDED(type->GetUINT32(MF_MT_VIDEO_PRIMARIES, (uint32_t*) &primaries)))
|
||||
{
|
||||
switch (primaries)
|
||||
{
|
||||
case MFVideoPrimaries_BT709: ffStrbufSetStatic(&camera->colorspace, "sRGB"); break;
|
||||
case MFVideoPrimaries_BT470_2_SysM:
|
||||
case MFVideoPrimaries_BT470_2_SysBG: ffStrbufSetStatic(&camera->colorspace, "NTSC"); break;
|
||||
case MFVideoPrimaries_SMPTE170M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 170M"); break;
|
||||
case MFVideoPrimaries_SMPTE240M: ffStrbufSetStatic(&camera->colorspace, "SMPTE 240M"); break;
|
||||
case MFVideoPrimaries_EBU3213: ffStrbufSetStatic(&camera->colorspace, "EBU 3213"); break;
|
||||
case MFVideoPrimaries_SMPTE_C: ffStrbufSetStatic(&camera->colorspace, "SMPTE C"); break;
|
||||
case MFVideoPrimaries_BT2020: ffStrbufSetStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case MFVideoPrimaries_XYZ: ffStrbufSetStatic(&camera->colorspace, "XYZ"); break;
|
||||
case MFVideoPrimaries_DCI_P3: ffStrbufSetStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
case MFVideoPrimaries_ACES: ffStrbufSetStatic(&camera->colorspace, "ACES"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
MFGetAttributeSize(type, MF_MT_FRAME_SIZE, &camera->width, &camera->height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CoTaskMemFree(devices);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
const char* ffChassisTypeToString(uint32_t type)
|
||||
{
|
||||
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
|
||||
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.7.0.pdf
|
||||
// 7.4.1 System Enclosure or Chassis Types
|
||||
switch (type)
|
||||
switch (type & 0b01111111)
|
||||
{
|
||||
case 0x01: return "Other";
|
||||
case 0x02: return "Unknown";
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
typedef struct FFChassisResult
|
||||
{
|
||||
FFstrbuf type;
|
||||
FFstrbuf serial;
|
||||
FFstrbuf vendor;
|
||||
FFstrbuf version;
|
||||
} FFChassisResult;
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options);
|
||||
const char* ffDetectChassis(FFChassisResult* result);
|
||||
const char* ffChassisTypeToString(uint32_t type);
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
#include "common/settings.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
{
|
||||
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
|
||||
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
|
||||
ffCleanUpSmbiosValue(&result->type);
|
||||
ffSettingsGetFreeBSDKenv("smbios.chassis.maker", &result->vendor);
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
ffSettingsGetFreeBSDKenv("smbios.chassis.serial", &result->serial);
|
||||
ffCleanUpSmbiosValue(&result->serial);
|
||||
ffSettingsGetFreeBSDKenv("smbios.chassis.version", &result->version);
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
return NULL;
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_serial", "/sys/class/dmi/id/chassis_serial", &result->serial);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "chassis.h"
|
||||
|
||||
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "chassis.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
// 7.4
|
||||
typedef struct FFSmbiosSystemEnclosure
|
||||
{
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
uint8_t Manufacturer; // string
|
||||
uint8_t Type; // varies
|
||||
uint8_t Version; // string
|
||||
uint8_t SerialNumber; // string
|
||||
uint8_t AssetTagNumber; // string
|
||||
|
||||
// 2.1+
|
||||
uint8_t BootupState; // enum
|
||||
uint8_t PowerSupplyState; // enum
|
||||
uint8_t ThermalState; // enum
|
||||
uint8_t SecurityStatus; // enum
|
||||
|
||||
// 2.3+
|
||||
uint32_t OEMDefined; // varies
|
||||
uint8_t Height; // varies
|
||||
uint8_t NumberOfPowerCords; // varies
|
||||
uint8_t ContainedElementCount; // varies
|
||||
uint8_t ContainedRecordLength; // varies
|
||||
uint8_t ContainedElements[]; // varies
|
||||
} FFSmbiosSystemEnclosure;
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
{
|
||||
const FFSmbiosSystemEnclosure* data = (const FFSmbiosSystemEnclosure*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_SYSTEM_ENCLOSURE];
|
||||
if (!data)
|
||||
return "System enclosure is not found in SMBIOS data";
|
||||
|
||||
const char* strings = (const char*) data + data->Header.Length;
|
||||
|
||||
ffStrbufSetStatic(&result->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
ffStrbufSetStatic(&result->serial, ffSmbiosLocateString(strings, data->SerialNumber));
|
||||
ffCleanUpSmbiosValue(&result->serial);
|
||||
ffStrbufSetStatic(&result->version, ffSmbiosLocateString(strings, data->Version));
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
ffStrbufSetStatic(&result->type, ffChassisTypeToString(data->Type));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
extern "C" {
|
||||
#include "chassis.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
}
|
||||
#include "util/windows/unicode.hpp"
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
static const char* detectWithRegistry(FFChassisResult* result)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL)) // SMBIOS
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
|
||||
|
||||
uint32_t type = 0;
|
||||
if(!ffRegReadUint(hKey, L"EnclosureType", &type, NULL))
|
||||
return "\"HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\BIOS\\EnclosureType\" doesn't exist";
|
||||
|
||||
const char* typeStr = ffChassisTypeToString(type);
|
||||
if(!typeStr)
|
||||
return "Unknown chassis type";
|
||||
|
||||
ffStrbufAppendS(&result->type, typeStr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
{
|
||||
FFWmiQuery query(L"SELECT Version, ChassisTypes, Manufacturer FROM Win32_SystemEnclosure");
|
||||
if (!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
if (FFWmiRecord record = query.next())
|
||||
{
|
||||
if (auto vtProp = record.get(L"ChassisTypes"))
|
||||
{
|
||||
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
|
||||
if(len == 0)
|
||||
return "ChassisTypes contain no data";
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
ffStrbufAppendS(&result->type, ", ");
|
||||
ffStrbufAppendS(&result->type, ffChassisTypeToString((uint32_t) arr[i]));
|
||||
}
|
||||
}
|
||||
else
|
||||
return "Get ChassisTypes failed";
|
||||
|
||||
if (auto vtProp = record.get(L"Version"))
|
||||
{
|
||||
ffStrbufSetWSV(&result->version, vtProp.get<std::wstring_view>());
|
||||
ffCleanUpSmbiosValue(&result->version);
|
||||
}
|
||||
|
||||
if (auto vtProp = record.get(L"Manufacturer"))
|
||||
{
|
||||
ffStrbufSetWSV(&result->vendor, vtProp.get<std::wstring_view>());
|
||||
ffCleanUpSmbiosValue(&result->vendor);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return "No WMI result returned";
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
|
||||
{
|
||||
if (options->useWmi)
|
||||
return detectWithWmi(result);
|
||||
return detectWithRegistry(result);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "cpu.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "detection/temps/temps_apple.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
{
|
||||
@@ -35,44 +36,33 @@ static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
// https://github.com/giampaolo/psutil/pull/2222/files
|
||||
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess)
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
|
||||
if (!entryDevice)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
|
||||
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
|
||||
if (IORegistryEntryCreateCFProperties(entryDevice, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
return "IORegistryEntryCreateCFProperties() failed";
|
||||
|
||||
uint32_t pMin, eMin, aMax, pCoreLength;
|
||||
if (ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength) != NULL) // pCore
|
||||
return "\"voltage-states5-sram\" in \"pmgr\" is not found";
|
||||
if (ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL) != NULL) // eCore
|
||||
return "\"voltage-states1-sram\" in \"pmgr\" is not found";
|
||||
|
||||
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
|
||||
|
||||
if (pCoreLength >= 8)
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
|
||||
continue;
|
||||
if (strcmp(name, "pmgr") != 0)
|
||||
continue;
|
||||
|
||||
uint32_t pMin, eMin, aMax, pCoreLength;
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
|
||||
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
|
||||
|
||||
if (pCoreLength >= 8)
|
||||
{
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
|
||||
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
|
||||
}
|
||||
else
|
||||
cpu->frequencyMax = 0.0;
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
|
||||
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
|
||||
}
|
||||
else
|
||||
cpu->frequencyMax = 0.0;
|
||||
|
||||
IOObjectRelease(iterator);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/properties.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <stdlib.h>
|
||||
@@ -34,6 +35,10 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
FF_AUTO_FREE char* line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
#ifdef __aarch64__
|
||||
FF_STRBUF_AUTO_DESTROY implementer = ffStrbufCreate();
|
||||
#endif
|
||||
|
||||
while(getline(&line, &len, cpuinfo) != -1)
|
||||
{
|
||||
//Stop after the first CPU
|
||||
@@ -47,12 +52,36 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
|
||||
ffParsePropLine(line, "isa :", cpuIsa) ||
|
||||
ffParsePropLine(line, "uarch :", cpuUarch) ||
|
||||
|
||||
#ifdef __aarch64__
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", &implementer)) ||
|
||||
#endif
|
||||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
// https://github.com/util-linux/util-linux/blob/2cd89de14549d2b2c079a4f8b73f75500d229fee/sys-utils/lscpu-arm.c#L286
|
||||
if (cpu->vendor.length == 0 && implementer.length > 2 /* 0xX */)
|
||||
{
|
||||
uint32_t implId = (uint32_t) strtoul(implementer.chars, NULL, 16);
|
||||
switch (implId)
|
||||
{
|
||||
case 0x41: ffStrbufSetStatic(&cpu->vendor, "ARM"); break;
|
||||
case 0x42: ffStrbufSetStatic(&cpu->vendor, "Broadcom"); break;
|
||||
case 0x48: ffStrbufSetStatic(&cpu->vendor, "HiSilicon"); break;
|
||||
case 0x4e: ffStrbufSetStatic(&cpu->vendor, "Nvidia"); break;
|
||||
case 0x51: ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); break;
|
||||
case 0x53: ffStrbufSetStatic(&cpu->vendor, "Samsung"); break;
|
||||
case 0x61: ffStrbufSetStatic(&cpu->vendor, "Apple"); break;
|
||||
case 0x69: ffStrbufSetStatic(&cpu->vendor, "Intel"); break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -121,6 +150,44 @@ static void parseIsa(FFstrbuf* cpuIsa)
|
||||
}
|
||||
}
|
||||
|
||||
void detectAsahi(FFCPUResult* cpu)
|
||||
{
|
||||
// In Asahi Linux, reading /proc/device-tree/compatible gives
|
||||
// information on the device model. It consists of 3 NUL terminated
|
||||
// strings, the second of which gives the actual SoC model. But it
|
||||
// is not the marketing name, i.e. for M2 there is "apple,t8112" in
|
||||
// the compatible string.
|
||||
if (cpu->name.length == 0 && ffStrbufEqualS(&cpu->vendor, "Apple"))
|
||||
{
|
||||
char content[32];
|
||||
ssize_t length = ffReadFileData("/proc/device-tree/compatible", sizeof(content), content);
|
||||
if (length <= 0) return;
|
||||
|
||||
// get the second NUL terminated string
|
||||
char* modelName = memchr(content, '\0', (size_t) length) + 1;
|
||||
if (modelName - content < length && ffStrStartsWith(modelName, "apple,t"))
|
||||
{
|
||||
// https://github.com/AsahiLinux/docs/wiki/Codenames
|
||||
switch (strtoul(modelName + strlen("apple,t"), NULL, 10))
|
||||
{
|
||||
case 8103: ffStrbufSetStatic(&cpu->name, "Apple M1"); break;
|
||||
case 6000: ffStrbufSetStatic(&cpu->name, "Apple M1 Pro"); break;
|
||||
case 6001: ffStrbufSetStatic(&cpu->name, "Apple M1 Max"); break;
|
||||
case 6002: ffStrbufSetStatic(&cpu->name, "Apple M1 Ultra"); break;
|
||||
case 8112: ffStrbufSetStatic(&cpu->name, "Apple M2"); break;
|
||||
case 6020: ffStrbufSetStatic(&cpu->name, "Apple M2 Pro"); break;
|
||||
case 6021: ffStrbufSetStatic(&cpu->name, "Apple M2 Max"); break;
|
||||
case 6022: ffStrbufSetStatic(&cpu->name, "Apple M2 Ultra"); break;
|
||||
case 8122: ffStrbufSetStatic(&cpu->name, "Apple M3"); break;
|
||||
case 6030: ffStrbufSetStatic(&cpu->name, "Apple M3 Pro"); break;
|
||||
case 6031:
|
||||
case 6034: ffStrbufSetStatic(&cpu->name, "Apple M3 Max"); break;
|
||||
default: ffStrbufSetStatic(&cpu->name, "Apple Silicon"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
@@ -167,6 +234,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectAndroid(cpu);
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__aarch64__)
|
||||
detectAsahi(cpu);
|
||||
#endif
|
||||
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
@@ -191,6 +262,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffStrbufAppendS(&cpu->vendor, pstart);
|
||||
}
|
||||
pstart = pend + 1;
|
||||
if (pstart >= buffer.chars + buffer.length)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +280,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
if (*pstart == '-')
|
||||
{
|
||||
ffStrbufAppendS(&cpu->name, "Unknown");
|
||||
if (cpu->vendor.length > 0)
|
||||
ffStrbufAppend(&cpu->name, &cpu->vendor);
|
||||
else
|
||||
ffStrbufAppendS(&cpu->name, "Unknown");
|
||||
++pstart;
|
||||
continue;
|
||||
}
|
||||
@@ -222,6 +298,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
}
|
||||
|
||||
pstart = pend + 1;
|
||||
if (pstart >= buffer.chars + buffer.length)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,81 @@
|
||||
#include "detection/temps/temps_windows.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
// 7.5
|
||||
typedef struct FFSmbiosProcessorInfo
|
||||
{
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
uint8_t SocketDesignation; // string
|
||||
uint8_t ProcessorType; // enum
|
||||
uint8_t ProcessorFamily; // enum
|
||||
uint8_t ProcessorManufacturer; // string
|
||||
uint64_t ProcessorID; // varies
|
||||
uint8_t ProcessorVersion; // string
|
||||
uint8_t Voltage; // varies
|
||||
uint16_t ExternalClock; // varies
|
||||
uint16_t MaxSpeed; // varies
|
||||
uint16_t CurrentSpeed; // varies
|
||||
uint8_t Status; // varies
|
||||
uint8_t ProcessorUpgrade; // enum
|
||||
|
||||
// 2.1+
|
||||
uint16_t L1CacheHandle; // varies
|
||||
uint16_t L2CacheHandle; // varies
|
||||
uint16_t L3CacheHandle; // varies
|
||||
|
||||
// 2.3+
|
||||
uint8_t SerialNumber; // string
|
||||
uint8_t AssertTag; // string
|
||||
uint8_t PartNumber; // string
|
||||
|
||||
// 2.5+
|
||||
uint8_t CoreCount; // varies
|
||||
uint8_t CoreEnabled; // varies
|
||||
uint8_t ThreadCount; // varies
|
||||
uint16_t ProcessorCharacteristics; // bit field
|
||||
|
||||
// 2.6+
|
||||
uint16_t ProcessorFamily2; // enum
|
||||
|
||||
// 3.0+
|
||||
uint16_t CoreCount2; // varies
|
||||
uint16_t CoreEnabled2; // varies
|
||||
uint16_t ThreadCount2; // varies
|
||||
|
||||
// 3.6+
|
||||
uint16_t ThreadEnabled; // varies
|
||||
} FFSmbiosProcessorInfo;
|
||||
|
||||
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
|
||||
{
|
||||
const FFSmbiosProcessorInfo* data = (const FFSmbiosProcessorInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_PROCESSOR_INFO];
|
||||
|
||||
if (!data)
|
||||
return "Processor information is not found in SMBIOS data";
|
||||
|
||||
while (data->ProcessorType != 0x03 /*Central Processor*/ || (data->Status & 0b00000111) != 1 /*Enabled*/)
|
||||
{
|
||||
data = (const FFSmbiosProcessorInfo*) ffSmbiosNextEntry(&data->Header);
|
||||
if (data->Header.Type != FF_SMBIOS_TYPE_PROCESSOR_INFO)
|
||||
return "No active CPU is found in SMBIOS data";
|
||||
}
|
||||
|
||||
double speed;
|
||||
if (data->MaxSpeed > 0 && data->MaxSpeed < 30000) // VMware reports weird values
|
||||
speed = data->MaxSpeed / 1000.0;
|
||||
else
|
||||
speed = data->CurrentSpeed / 1000.0;
|
||||
|
||||
if (cpu->frequencyMax < speed)
|
||||
cpu->frequencyMax = speed;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByOS(FFCPUResult* cpu)
|
||||
{
|
||||
{
|
||||
DWORD length = 0;
|
||||
@@ -42,14 +115,24 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t mhz;
|
||||
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||
cpu->frequencyMax = mhz / 1000.0;
|
||||
cpu->frequencyMin = cpu->frequencyMax = mhz / 1000.0;
|
||||
}
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
const char* error = detectByOS(cpu);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if(options->temp)
|
||||
ffDetectSmbiosTemp(&cpu->temperature, NULL);
|
||||
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -8,22 +8,14 @@
|
||||
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
|
||||
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
|
||||
|
||||
static inline void wrapIoObjectRelease(io_service_t* service)
|
||||
{
|
||||
assert(service);
|
||||
if (*service)
|
||||
IOObjectRelease(*service);
|
||||
}
|
||||
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
|
||||
|
||||
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
|
||||
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
|
||||
{
|
||||
@@ -89,7 +90,7 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
|
||||
ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(sysBlockStat) - 1, sysBlockStat);
|
||||
if (fileSize <= 0) continue;
|
||||
sysBlockStat[fileSize] = '\0';
|
||||
if (sscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, §orRead, &nWritten, §orWritten) <= 0)
|
||||
if (sscanf(sysBlockStat, "%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u", &nRead, §orRead, &nWritten, §orWritten) <= 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,8 +129,9 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
(uint32_t) (monitorInfo->info.rcMonitor.bottom - monitorInfo->info.rcMonitor.top),
|
||||
rotation,
|
||||
&name,
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER ? FF_DISPLAY_TYPE_UNKNOWN :
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED ||
|
||||
path->targetInfo.outputTechnology == DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED
|
||||
? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL,
|
||||
!!(monitorInfo->info.dwFlags & MONITORINFOF_PRIMARY),
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "displayserver_linux.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "common/settings.h"
|
||||
#endif
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
{
|
||||
@@ -31,6 +34,26 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
if(ds->displays.length == 0)
|
||||
ffdsConnectDrm(ds);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if(ds->displays.length == 0)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
|
||||
if (ffSettingsGetFreeBSDKenv("screen.width", &buf))
|
||||
{
|
||||
uint32_t width = (uint32_t) ffStrbufToUInt(&buf, 0);
|
||||
if (width)
|
||||
{
|
||||
ffStrbufClear(&buf);
|
||||
if (ffSettingsGetFreeBSDKenv("screen.height", &buf))
|
||||
{
|
||||
uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0);
|
||||
ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//This fills in missing information about WM / DE by using env vars and iterating processes
|
||||
ffdsDetectWMDE(ds);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t width = 0, height = 0;
|
||||
unsigned width = 0, height = 0;
|
||||
|
||||
int scanned = sscanf(modes, "%ux%u", &width, &height);
|
||||
if(scanned == 2 && width > 0 && height > 0)
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
typedef struct FFGamepadDevice
|
||||
{
|
||||
FFstrbuf identifier;
|
||||
FFstrbuf serial;
|
||||
FFstrbuf name;
|
||||
uint8_t battery; // 0-100%
|
||||
} FFGamepadDevice;
|
||||
|
||||
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */);
|
||||
|
||||
@@ -1,18 +1,34 @@
|
||||
#include "gamepad.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
|
||||
static void enumSet(const void* value, void *context)
|
||||
static void enumSet(IOHIDDeviceRef value, FFlist* results)
|
||||
{
|
||||
CFStringRef product = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDProductKey));
|
||||
CFStringRef serialNumber = IOHIDDeviceGetProperty((IOHIDDeviceRef) value, CFSTR(kIOHIDSerialNumberKey));
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd((FFlist*) context);
|
||||
ffStrbufInit(&device->identifier);
|
||||
ffCfStrGetString(serialNumber, &device->identifier);
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(results);
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInit(&device->name);
|
||||
ffCfStrGetString(product, &device->name);
|
||||
device->battery = 0;
|
||||
|
||||
CFStringRef manufacturer = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDManufacturerKey));
|
||||
ffCfStrGetString(manufacturer, &device->name);
|
||||
|
||||
CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey));
|
||||
if (device->name.length)
|
||||
{
|
||||
ffCfStrGetString(product, &device->serial);
|
||||
ffStrbufAppendC(&device->name, ' ');
|
||||
ffStrbufAppend(&device->name, &device->serial);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffCfStrGetString(product, &device->name);
|
||||
}
|
||||
|
||||
CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey));
|
||||
ffCfStrGetString(serialNumber, &device->serial);
|
||||
}
|
||||
|
||||
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
@@ -21,21 +37,29 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
|
||||
return "IOHIDManagerOpen() failed";
|
||||
|
||||
CFNumberRef FF_CFTYPE_AUTO_RELEASE genericDesktop = ffCfCreateInt(kHIDPage_GenericDesktop);
|
||||
CFNumberRef FF_CFTYPE_AUTO_RELEASE gamePad = ffCfCreateInt(kHIDUsage_GD_GamePad);
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
CFSTR(kIOHIDDeviceUsageKey)
|
||||
}, (const void **)(CFNumberRef[]){
|
||||
genericDesktop,
|
||||
gamePad
|
||||
ffCfCreateInt(kHIDPage_GenericDesktop),
|
||||
ffCfCreateInt(kHIDUsage_GD_Joystick)
|
||||
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
IOHIDManagerSetDeviceMatching(manager, matching);
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching2 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
CFSTR(kIOHIDDeviceUsageKey)
|
||||
}, (const void **)(CFNumberRef[]){
|
||||
ffCfCreateInt(kHIDPage_GenericDesktop),
|
||||
ffCfCreateInt(kHIDUsage_GD_GamePad)
|
||||
}, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
CFArrayRef FF_CFTYPE_AUTO_RELEASE matchings = CFArrayCreate(kCFAllocatorDefault, (const void **)(CFTypeRef[]){
|
||||
matching1, matching2
|
||||
}, 2, &kCFTypeArrayCallBacks);
|
||||
IOHIDManagerSetDeviceMatchingMultiple(manager, matchings);
|
||||
|
||||
CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager);
|
||||
if (set)
|
||||
CFSetApplyFunction(set, &enumSet, devices);
|
||||
IOHIDManagerClose(manager, 0);
|
||||
CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices);
|
||||
IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -42,8 +42,9 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1)
|
||||
{
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitS(&device->identifier, di.udi_serial);
|
||||
ffStrbufInitS(&device->serial, di.udi_serial);
|
||||
ffStrbufInitF(&device->name, "%s %s", di.udi_vendor, di.udi_product);
|
||||
device->battery = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,39 +5,88 @@
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static void detectGamepad(FFlist* devices, FFstrbuf* name, FFstrbuf* path)
|
||||
{
|
||||
uint32_t baseLen = path->length;
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInitMove(&device->name, name);
|
||||
device->battery = 0;
|
||||
|
||||
ffStrbufAppendS(path, "uniq");
|
||||
if (ffAppendFileBuffer(path->chars, &device->serial))
|
||||
ffStrbufTrimRightSpace(&device->serial);
|
||||
|
||||
ffStrbufSubstrBefore(path, baseLen);
|
||||
ffStrbufAppendS(path, "device/power_supply/"); // /sys/class/input/jsX/device/device/power_supply
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path->chars);
|
||||
if (dirp)
|
||||
{
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.' || (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN))
|
||||
continue;
|
||||
ffStrbufAppendS(path, entry->d_name);
|
||||
ffStrbufAppendS(path, "/capacity"); // /sys/class/input/jsX/device/device/power_supply/XXX/capacity
|
||||
char capacity[32];
|
||||
ssize_t nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
|
||||
if (nRead > 0) // Tested with a PS4 controller
|
||||
{
|
||||
capacity[nRead] = '\0';
|
||||
device->battery = (uint8_t) strtoul(capacity, NULL, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
ffStrbufAppendS(path, "_level");
|
||||
nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
|
||||
if (nRead > 0) // Tested with a NS Pro controller
|
||||
{
|
||||
// https://github.com/torvalds/linux/blob/52b1853b080a082ec3749c3a9577f6c71b1d4a90/drivers/power/supply/power_supply_sysfs.c#L124
|
||||
switch (capacity[0])
|
||||
{
|
||||
case 'C': device->battery = 1; break; // Critical
|
||||
case 'L': device->battery = 25; break; // Low
|
||||
case 'N': device->battery = 50; break; // Normal
|
||||
case 'H': device->battery = 75; break; // High
|
||||
case 'F': device->battery = 100; break; // Full
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
DIR* dirp = opendir("/sys/class/input/");
|
||||
if(dirp == NULL)
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/");
|
||||
if (dirp == NULL)
|
||||
return "opendir(\"/sys/class/input/\") == NULL";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/");
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(!ffStrStartsWith(entry->d_name, "js"))
|
||||
if (!ffStrStartsWith(entry->d_name, "js"))
|
||||
continue;
|
||||
if(!isdigit(entry->d_name[2]))
|
||||
if (!isdigit(entry->d_name[2]))
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
ffStrbufAppendS(&path, "/device/name");
|
||||
|
||||
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
|
||||
if (ffAppendFileBuffer(path.chars, &name))
|
||||
{
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitS(&device->identifier, entry->d_name);
|
||||
ffStrbufInit(&device->name);
|
||||
if (ffAppendFileBuffer(path.chars, &device->name))
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
ffStrbufTrimRightSpace(&name);
|
||||
ffStrbufSubstrBefore(&path, path.length - 4);
|
||||
detectGamepad(devices, &name, &path);
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <winternl.h>
|
||||
#include <windows.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
|
||||
static const char* detectKnownDeviceName(uint32_t vendorId, uint32_t productId)
|
||||
{
|
||||
switch (vendorId)
|
||||
{
|
||||
@@ -30,38 +31,14 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x0268: return "Sony Playstation 3 Controller";
|
||||
case 0x0268: return "Sony DualShock 3 / Six Axis";
|
||||
|
||||
case 0x05C4: return "Sony DualShock 4 Gen1";
|
||||
case 0x09CC: return "Sony DualShock 4 Gen2";
|
||||
case 0x0BA0: return "Sony PS4 Controller USB receiver";
|
||||
case 0x0BA0: return "Sony DualShock 4 USB receiver";
|
||||
|
||||
case 0x0CE6: return "Sony DualSense";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Microsoft
|
||||
case 0x045E:
|
||||
{
|
||||
switch (productId)
|
||||
{
|
||||
case 0x02E0: return "Microsoft X-Box One S pad (Wireless)";
|
||||
case 0x02FD: return "Microsoft X-Box One S pad (Wireless, 2016 FW)";
|
||||
case 0x0B05: return "Microsoft X-Box One Elite Series 2 pad (Wireless)";
|
||||
case 0x0B13: return "Microsoft X-Box Series X (Wireless)";
|
||||
|
||||
case 0x028E: return "Microsoft XBox 360";
|
||||
case 0x028F: return "Microsoft XBox 360 v2";
|
||||
case 0x02A1: return "Microsoft XBox 360";
|
||||
case 0x0291: return "Microsoft XBox 360 USB receiver";
|
||||
case 0x02A0: return "Microsoft XBox 360 Big Button IR";
|
||||
case 0x02DD: return "Microsoft XBox One";
|
||||
case 0xB326: return "Microsoft XBox One Firmware 2015";
|
||||
case 0x02E3: return "Microsoft XBox One Elite";
|
||||
case 0x02FF: return "Microsoft XBox One Elite";
|
||||
case 0x02EA: return "Microsoft XBox One S";
|
||||
case 0x0DF2: return "Sony DualSense Edge";
|
||||
|
||||
default: return NULL;
|
||||
}
|
||||
@@ -83,6 +60,7 @@ static const char* detectKnownGamepad(uint32_t vendorId, uint32_t productId)
|
||||
}
|
||||
}
|
||||
|
||||
case 0x045E: // Microsoft Xbox compatible controllers should be handled by Windows without problems
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -98,7 +76,8 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1)
|
||||
return "GetRawInputDeviceList(pRawInputDeviceList) failed";
|
||||
|
||||
for (UINT i = 0; i < nDevices; ++i) {
|
||||
for (UINT i = 0; i < nDevices; ++i)
|
||||
{
|
||||
if (pRawInputDeviceList[i].dwType != 2) continue;
|
||||
|
||||
HANDLE hDevice = pRawInputDeviceList[i].hDevice;
|
||||
@@ -117,20 +96,94 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
continue;
|
||||
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInitWS(&device->identifier, devName);
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInit(&device->name);
|
||||
device->battery = 0;
|
||||
|
||||
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
const char* knownGamepad = detectKnownDeviceName(rdi.hid.dwVendorId, rdi.hid.dwProductId);
|
||||
if (knownGamepad)
|
||||
ffStrbufSetS(&device->name, knownGamepad);
|
||||
else
|
||||
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
if (!hHidFile)
|
||||
{
|
||||
if (!knownGamepad)
|
||||
ffStrbufSetF(&device->name, "Unknown gamepad %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!knownGamepad)
|
||||
{
|
||||
wchar_t displayName[126];
|
||||
HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
|
||||
ffStrbufSetWS(&device->name, displayName);
|
||||
else
|
||||
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
|
||||
if (HidD_GetProductString(hHidFile, displayName, sizeof(displayName)))
|
||||
{
|
||||
wchar_t manufacturer[126];
|
||||
if (HidD_GetManufacturerString(hHidFile, manufacturer, sizeof(manufacturer)))
|
||||
{
|
||||
ffStrbufSetWS(&device->name, manufacturer);
|
||||
FF_STRBUF_AUTO_DESTROY displayNameStr = ffStrbufCreateWS(displayName);
|
||||
ffStrbufAppendC(&device->name, ' ');
|
||||
ffStrbufAppend(&device->name, &displayNameStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSetWS(&device->name, displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PHIDP_PREPARSED_DATA preparsedData = NULL;
|
||||
if (HidD_GetPreparsedData(hHidFile, &preparsedData))
|
||||
{
|
||||
HIDP_CAPS caps;
|
||||
NTSTATUS capsResult = HidP_GetCaps(preparsedData, &caps);
|
||||
HidD_FreePreparsedData(preparsedData);
|
||||
if (!NT_SUCCESS(capsResult))
|
||||
continue;
|
||||
|
||||
wchar_t serialNumber[127] = L"";
|
||||
if (HidD_GetSerialNumberString(hHidFile, serialNumber, sizeof(serialNumber)))
|
||||
ffStrbufSetWS(&device->serial, serialNumber);
|
||||
|
||||
if (
|
||||
(rdi.hid.dwVendorId == 0x054C && (
|
||||
rdi.hid.dwProductId == 0x05C4 || // PS4 Gen1
|
||||
rdi.hid.dwProductId == 0x09CC // PS4 Gen2
|
||||
)) ||
|
||||
(rdi.hid.dwVendorId == 0x057E && (
|
||||
rdi.hid.dwProductId == 0x2009 // NS Pro
|
||||
))
|
||||
)
|
||||
{
|
||||
// Controller must be connected by other programs
|
||||
FF_AUTO_FREE uint8_t* reportBuffer = malloc(caps.InputReportByteLength);
|
||||
OVERLAPPED overlapped = { };
|
||||
DWORD nBytes;
|
||||
if (ReadFile(hHidFile, reportBuffer, caps.InputReportByteLength, &nBytes, &overlapped) ||
|
||||
(WaitForSingleObject(hHidFile, FF_IO_TERM_RESP_WAIT_MS) == WAIT_OBJECT_0 && GetOverlappedResult(hHidFile, &overlapped, &nBytes, FALSE)))
|
||||
{
|
||||
if (rdi.hid.dwVendorId == 0x054C)
|
||||
{
|
||||
if (nBytes > 31)
|
||||
{
|
||||
uint8_t batteryInfo = reportBuffer[caps.InputReportByteLength == 64 /*USB?*/ ? 30 : 32];
|
||||
device->battery = (uint8_t) ((batteryInfo & 0x0f) * 100 / (batteryInfo & 0x10 /*charging?*/ ? 11 /*BATTERY_MAX_USB*/ : 8 /*BATTERY_MAX*/));
|
||||
if (device->battery > 100) device->battery = 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nBytes > 3 && reportBuffer[0] == 0x30)
|
||||
{
|
||||
uint8_t batteryInfo = reportBuffer[2];
|
||||
device->battery = (uint8_t) (((batteryInfo & 0xE0) >> 4) * 100 / 8);
|
||||
if (device->battery == 0) device->battery = 1;
|
||||
else if (device->battery > 100) device->battery = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
CancelIo(hHidFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+84
-4
@@ -6,6 +6,8 @@ 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_QUALCOMM = "Qualcomm";
|
||||
const char* FF_GPU_VENDOR_NAME_MTK = "MTK";
|
||||
const char* FF_GPU_VENDOR_NAME_VMWARE = "VMware";
|
||||
const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
|
||||
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
|
||||
@@ -33,6 +35,10 @@ const char* ffGetGPUVendorString(unsigned vendorId)
|
||||
return FF_GPU_VENDOR_NAME_INTEL;
|
||||
else if(arrayContains((const unsigned[]) {0x0955, 0x10de, 0x12d2}, vendorId, 3))
|
||||
return FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
else if(arrayContains((const unsigned[]) {0x5143}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
else if(arrayContains((const unsigned[]) {0x14c3}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_MTK;
|
||||
else if(arrayContains((const unsigned[]) {0x15ad}, vendorId, 1))
|
||||
return FF_GPU_VENDOR_NAME_VMWARE;
|
||||
else if(arrayContains((const unsigned[]) {0x1af4}, vendorId, 1))
|
||||
@@ -73,15 +79,17 @@ const char* detectByOpenGL(FFlist* gpus)
|
||||
|
||||
if (!gpu->vendor.length)
|
||||
{
|
||||
if (ffStrbufContainS(&result.renderer, "Apple"))
|
||||
if (ffStrbufContainS(&gpu->name, "Apple"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
else if (ffStrbufContainS(&result.renderer, "Intel"))
|
||||
else if (ffStrbufContainS(&gpu->name, "Intel"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if (ffStrbufContainS(&result.renderer, "AMD") || ffStrbufContainS(&result.renderer, "ATI"))
|
||||
else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if (ffStrbufContainS(&result.renderer, "NVIDIA"))
|
||||
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
}
|
||||
if (ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE))
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result.version);
|
||||
@@ -110,3 +118,75 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
|
||||
|
||||
return "GPU detection failed";
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
|
||||
{
|
||||
if (content->length)
|
||||
{
|
||||
char buffer[32];
|
||||
uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor);
|
||||
char* start = (char*) memmem(content->chars, content->length, buffer, len);
|
||||
char* end = content->chars + content->length;
|
||||
if (start)
|
||||
{
|
||||
start += len;
|
||||
end = memchr(start, '\n', (uint32_t) (end - start));
|
||||
if (!end)
|
||||
end = content->chars + content->length;
|
||||
if (!gpu->vendor.length)
|
||||
ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start);
|
||||
|
||||
start = end; // point to '\n' of vendor
|
||||
end = start + 1; // point to start of devices
|
||||
// find the start of next vendor
|
||||
while (end[0] == '\t' || end[0] == '#')
|
||||
{
|
||||
end = strchr(end, '\n');
|
||||
if (!end)
|
||||
{
|
||||
end = content->chars + content->length;
|
||||
break;
|
||||
}
|
||||
else
|
||||
end++;
|
||||
}
|
||||
|
||||
len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device);
|
||||
start = memmem(start, (size_t) (end - start), buffer, len);
|
||||
if (start)
|
||||
{
|
||||
start += len;
|
||||
end = memchr(start, '\n', (uint32_t) (end - start));
|
||||
if (!end)
|
||||
end = content->chars + content->length;
|
||||
|
||||
char* openingBracket = memchr(start, '[', (uint32_t) (end - start));
|
||||
if (openingBracket)
|
||||
{
|
||||
openingBracket++;
|
||||
char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket));
|
||||
if (closingBracket)
|
||||
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
|
||||
}
|
||||
if (!gpu->name.length)
|
||||
ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpu->name.length)
|
||||
{
|
||||
const char* subclassStr;
|
||||
switch (subclass)
|
||||
{
|
||||
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
|
||||
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
|
||||
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
|
||||
default: subclassStr = ""; break;
|
||||
}
|
||||
|
||||
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -42,3 +42,7 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
|
||||
|
||||
const char* ffGetGPUVendorString(unsigned vendorId);
|
||||
|
||||
#ifndef _WIN32
|
||||
void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
|
||||
#endif
|
||||
|
||||
@@ -38,12 +38,12 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
|
||||
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
|
||||
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
@@ -106,8 +106,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
IOObjectRelease(registryEntry);
|
||||
}
|
||||
|
||||
IOObjectRelease(iterator);
|
||||
|
||||
ffGpuDetectMetal(gpus);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
FFGPUResult* gpu = NULL;
|
||||
FF_LIST_FOR_EACH(FFGPUResult, x, *gpus)
|
||||
{
|
||||
if (x->deviceId == device.registryID || ffStrbufEqualS(&x->name, device.name.UTF8String))
|
||||
if (x->deviceId == device.registryID)
|
||||
{
|
||||
gpu = x;
|
||||
break;
|
||||
@@ -32,9 +32,20 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
|
||||
|
||||
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
if (device.hasUnifiedMemory)
|
||||
{
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
gpu->shared.total = device.recommendedMaxWorkingSetSize;
|
||||
gpu->shared.used = device.currentAllocatedSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
gpu->dedicated.total = device.recommendedMaxWorkingSetSize;
|
||||
gpu->dedicated.used = device.currentAllocatedSize;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return "Metal API is not supported by this macOS version";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "3rdparty/nvml/nvml.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
{
|
||||
// https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h
|
||||
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
ffReadFileBuffer("/usr/share/pciids/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
|
||||
struct pci_conf confs[128];
|
||||
struct pci_match_conf match = {
|
||||
.pc_class = PCIC_DISPLAY,
|
||||
.flags = PCI_GETCONF_MATCH_CLASS,
|
||||
};
|
||||
struct pci_conf_io pcio = {
|
||||
.pat_buf_len = sizeof(match),
|
||||
.num_patterns = 1,
|
||||
.patterns = &match,
|
||||
.match_buf_len = sizeof(confs),
|
||||
.matches = confs,
|
||||
};
|
||||
|
||||
if (ioctl(fd, PCIOCGETCONF, &pcio) < 0)
|
||||
return "ioctl(fd, PCIOCGETCONF, &pc) failed";
|
||||
|
||||
if (pcio.status == PCI_GETCONF_ERROR)
|
||||
return "ioctl(fd, PCIOCGETCONF, &pc) returned error";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
||||
loadPciIds(&pciids);
|
||||
|
||||
for (uint32_t i = 0; i < pcio.num_matches; ++i)
|
||||
{
|
||||
struct pci_conf* pc = &confs[i];
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(pc->pc_vendor));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInitS(&gpu->driver, pc->pd_name);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
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;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = (uint32_t) pc->pc_sel.pc_domain,
|
||||
.bus = pc->pc_sel.pc_bus,
|
||||
.device = pc->pc_sel.pc_dev,
|
||||
.func = pc->pc_sel.pc_func,
|
||||
},
|
||||
}, (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 = &gpu->frequency,
|
||||
}, "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;
|
||||
}
|
||||
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
+118
-303
@@ -1,151 +1,24 @@
|
||||
#include "detection/gpu/gpu.h"
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "detection/vulkan/vulkan.h"
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pci/pci.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
// Fix building on Ubuntu 20.04
|
||||
#ifndef PCI_IORESOURCE_MEM
|
||||
#define PCI_IORESOURCE_MEM 0x00000200
|
||||
#endif
|
||||
#ifndef PCI_IORESOURCE_PREFETCH
|
||||
#define PCI_IORESOURCE_PREFETCH 0x00002000
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#endif
|
||||
|
||||
typedef struct PCIData
|
||||
{
|
||||
struct pci_access* access;
|
||||
FF_LIBRARY_SYMBOL(pci_fill_info)
|
||||
FF_LIBRARY_SYMBOL(pci_read_byte)
|
||||
FF_LIBRARY_SYMBOL(pci_lookup_name)
|
||||
FF_LIBRARY_SYMBOL(pci_get_param)
|
||||
#include <inttypes.h>
|
||||
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
FF_LIBRARY_SYMBOL(pci_get_string_property)
|
||||
#endif
|
||||
} PCIData;
|
||||
|
||||
static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(device->vendor_id));
|
||||
|
||||
if(gpu->vendor.length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(&gpu->vendor, 255);
|
||||
pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id);
|
||||
ffStrbufRecalculateLength(&gpu->vendor);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Intel"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "NVIDIA"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Apple"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
}
|
||||
|
||||
static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
u8 revId = 0;
|
||||
bool revIdSet = false;
|
||||
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
revIdSet = pci->ffpci_fill_info(device, PCI_FILL_CLASS_EXT) & PCI_FILL_CLASS_EXT;
|
||||
if(revIdSet)
|
||||
revId = device->rev_id;
|
||||
#endif
|
||||
|
||||
if(!revIdSet)
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
return;
|
||||
#else
|
||||
revId = pci->ffpci_read_byte(device, PCI_REVISION_ID);
|
||||
#endif
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY query = ffStrbufCreateF("%X, %X,", device->device_id, revId);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query.chars, &gpu->name);
|
||||
|
||||
const char* removeStrings[] = {
|
||||
"AMD ", "ATI ",
|
||||
" (TM)", "(TM)",
|
||||
" Graphics Adapter", " Graphics", " Series", " Edition"
|
||||
};
|
||||
ffStrbufRemoveStrings(&gpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings);
|
||||
}
|
||||
|
||||
static void pciDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
if(ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD))
|
||||
{
|
||||
drmDetectDeviceName(gpu, pci, device);
|
||||
if(gpu->name.length > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFree(&gpu->name, 255);
|
||||
pci->ffpci_lookup_name(pci->access, gpu->name.chars, (int) gpu->name.allocated, PCI_LOOKUP_DEVICE, device->vendor_id, device->device_id);
|
||||
ffStrbufRecalculateLength(&gpu->name);
|
||||
|
||||
uint32_t openingBracket = ffStrbufFirstIndexC(&gpu->name, '[');
|
||||
uint32_t closingBracket = ffStrbufNextIndexC(&gpu->name, openingBracket, ']');
|
||||
if(closingBracket < gpu->name.length)
|
||||
{
|
||||
ffStrbufSubstrBefore(&gpu->name, closingBracket);
|
||||
ffStrbufSubstrAfter(&gpu->name, openingBracket);
|
||||
}
|
||||
}
|
||||
|
||||
static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
pci->ffpci_fill_info(device, PCI_FILL_DRIVER);
|
||||
ffStrbufAppendS(&gpu->driver, pci->ffpci_get_string_property(device, PCI_FILL_DRIVER));
|
||||
#endif
|
||||
|
||||
const char* base = pci->ffpci_get_param(pci->access, "sysfs.path");
|
||||
if(!ffStrSet(base))
|
||||
return;
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s/devices/%04x:%02x:%02x.%d/driver", base, device->domain, device->bus, device->dev, device->func);
|
||||
if (gpu->driver.length == 0)
|
||||
{
|
||||
ffStrbufEnsureFree(&gpu->driver, 1023);
|
||||
ssize_t resultLength = readlink(path.chars, gpu->driver.chars, gpu->driver.allocated - 1); //-1 for null terminator
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->driver.length = (uint32_t) resultLength;
|
||||
gpu->driver.chars[resultLength] = '\0';
|
||||
ffStrbufSubstrAfterLastC(&gpu->driver, '/');
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppendS(&path, "/module/version");
|
||||
ffAppendFileBuffer(path.chars, &gpu->driver);
|
||||
ffStrbufTrimRightSpace(&gpu->driver);
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device)
|
||||
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
|
||||
{
|
||||
const FFlist* tempsResult = ffDetectTemps();
|
||||
|
||||
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
|
||||
{
|
||||
// FIXME: this code doesn't take multiGPUs into count
|
||||
//The kernel exposes the device class multiplied by 256 for some reason
|
||||
if(tempValue->deviceClass == device->device_class * 256)
|
||||
if(tempValue->deviceClass == deviceClass * 256)
|
||||
{
|
||||
gpu->temperature = tempValue->value;
|
||||
return;
|
||||
@@ -153,193 +26,140 @@ FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* devi
|
||||
}
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool pciDetectMemory(FFGPUResult* gpu, const PCIData* pci, struct pci_dev* device)
|
||||
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
gpu->dedicated.used = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
|
||||
uint32_t flags = (uint32_t) pci->ffpci_fill_info(device, PCI_FILL_IO_FLAGS | PCI_FILL_SIZES);
|
||||
if (!(flags & PCI_FILL_IO_FLAGS) || !(flags & PCI_FILL_SIZES))
|
||||
ffStrbufAppendS(pciDir, "/driver");
|
||||
char pathBuf[PATH_MAX];
|
||||
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
|
||||
if(resultLength > 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
return false;
|
||||
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
|
||||
if (slash)
|
||||
{
|
||||
slash++;
|
||||
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
|
||||
}
|
||||
|
||||
ffStrbufAppendS(pciDir, "/module/version");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppend(&gpu->driver, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
gpu->dedicated.total = gpu->shared.total = 0;
|
||||
for (uint32_t i = 0; i < sizeof(device->size) / sizeof(device->size[0]); i++)
|
||||
{
|
||||
if (!(device->flags[i] & PCI_IORESOURCE_MEM)) continue;
|
||||
|
||||
// Assume dedicated memories are prefetchable
|
||||
// At least it's true for my laptop
|
||||
if (device->flags[i] & PCI_IORESOURCE_PREFETCH)
|
||||
gpu->dedicated.total += device->size[i];
|
||||
else
|
||||
gpu->shared.total += device->size[i];
|
||||
}
|
||||
|
||||
if (gpu->dedicated.total == 0 && gpu->shared.total == 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void pciDetectType(FFGPUResult* gpu)
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
{
|
||||
//There is no straightforward way to detect the type of a GPU.
|
||||
//The approach taken here is to look at the memory sizes of the device.
|
||||
//Since integrated GPUs usually use the system ram, they don't have expansive ROMs
|
||||
//and their memory sizes are usually smaller than 1GB.
|
||||
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 // 1GB
|
||||
? FF_GPU_TYPE_DISCRETE
|
||||
: FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
else
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
}
|
||||
ffReadFileBuffer("/usr/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* results, PCIData* pci, struct pci_dev* device)
|
||||
{
|
||||
pci->ffpci_fill_info(device, PCI_FILL_CLASS);
|
||||
ffReadFileBuffer("/usr/share/misc/pci.ids", pciids); // debian?
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
char class[1024];
|
||||
pci->ffpci_lookup_name(pci->access, class, sizeof(class) - 1, PCI_LOOKUP_CLASS, device->device_class);
|
||||
ffReadFileBuffer("/usr/local/share/hwdata/pci.ids", pciids);
|
||||
if (pciids->length > 0) return true;
|
||||
|
||||
if(
|
||||
//https://pci-ids.ucw.cz/read/PD/03
|
||||
strcasecmp("VGA compatible controller", class) != 0 &&
|
||||
strcasecmp("XGA compatible controller", class) != 0 &&
|
||||
strcasecmp("3D controller", class) != 0 &&
|
||||
strcasecmp("Display controller", class) != 0
|
||||
) return;
|
||||
|
||||
pci->ffpci_fill_info(device, PCI_FILL_IDENT);
|
||||
|
||||
FFGPUResult* gpu = ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
pciDetectVendorName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->name);
|
||||
pciDetectDeviceName(gpu, pci, device);
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
pciDetectDriverName(gpu, pci, device);
|
||||
|
||||
#if FF_USE_PCI_MEMORY
|
||||
// Libpci reports at least 2 false results (#495, #497)
|
||||
pciDetectMemory(gpu, pci, device);
|
||||
pciDetectType(gpu);
|
||||
#else
|
||||
gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
#endif
|
||||
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = (uint32_t) device->domain,
|
||||
.bus = device->bus,
|
||||
.device = device->dev,
|
||||
.func = device->func,
|
||||
},
|
||||
}, (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 = &gpu->frequency,
|
||||
}, "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;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if(options->temp && gpu->temperature != gpu->temperature)
|
||||
pciDetectTemp(gpu, device);
|
||||
#endif
|
||||
}
|
||||
|
||||
jmp_buf pciInitJmpBuf;
|
||||
static void __attribute__((__noreturn__))
|
||||
handlePciInitError(FF_MAYBE_UNUSED char *msg, ...)
|
||||
{
|
||||
longjmp(pciInitJmpBuf, 1);
|
||||
}
|
||||
// https://github.com/pciutils/pciutils/blob/bca0412843fa650c749128ade03f35ab3e8fe2b9/lib/init.c#L186
|
||||
static void __attribute__((__noreturn__))
|
||||
handlePciGenericError(char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, msg);
|
||||
fputs("pcilib: ", stderr);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
static void handlePciWarning(FF_MAYBE_UNUSED char *msg, ...)
|
||||
{
|
||||
// noop
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
PCIData pci;
|
||||
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
|
||||
const char* pciDirPath = "/sys/bus/pci/devices/";
|
||||
|
||||
FF_LIBRARY_LOAD(libpci, &instance.config.library.libPCI, "dlopen libpci.so failed", "libpci" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_alloc);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_init);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_scan_bus);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libpci, pci_cleanup);
|
||||
DIR* dirp = opendir(pciDirPath);
|
||||
if(dirp == NULL)
|
||||
return "Failed to open `/sys/bus/pci/devices/`";
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_fill_info);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_lookup_name);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_read_byte);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_param);
|
||||
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&pciDir, pciDirPath);
|
||||
|
||||
#if PCI_LIB_VERSION >= 0x030800
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libpci, pci, pci_get_string_property);
|
||||
#endif
|
||||
const uint32_t pciBaseDirLength = pciDir.length;
|
||||
|
||||
pci.access = ffpci_alloc();
|
||||
pci.access->warning = handlePciWarning;
|
||||
pci.access->error = handlePciInitError;
|
||||
if(setjmp(pciInitJmpBuf) == 0) // https://github.com/pciutils/pciutils/issues/136
|
||||
ffpci_init(pci.access);
|
||||
else
|
||||
return "pcilib: Cannot find any working access method.";
|
||||
pci.access->error = handlePciGenericError; // set back to generic error so we don't mess up error handling in other places
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
||||
loadPciIds(&pciids);
|
||||
|
||||
ffpci_scan_bus(pci.access);
|
||||
|
||||
struct pci_dev* device = pci.access->devices;
|
||||
while(device != NULL)
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
pciHandleDevice(options, gpus, &pci, device);
|
||||
device = device->next;
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
||||
ffStrbufAppendS(&pciDir, entry->d_name);
|
||||
|
||||
const uint32_t pciDevDirLength = pciDir.length;
|
||||
|
||||
ffStrbufAppendS(&pciDir, "/modalias");
|
||||
if (!ffReadFileBuffer(pciDir.chars, &buffer))
|
||||
continue;
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
|
||||
uint32_t vendorId, deviceId;
|
||||
uint8_t classId, subclassId;
|
||||
if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%*8ssd%*8sbc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &classId, &subclassId) != 4)
|
||||
continue;
|
||||
|
||||
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
||||
continue;
|
||||
|
||||
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
|
||||
if (sscanf(entry->d_name, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
|
||||
pciDetectDriver(gpu, &pciDir, &buffer);
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(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 = &gpu->frequency,
|
||||
}, "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;
|
||||
}
|
||||
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
|
||||
#ifdef __linux__
|
||||
if(options->temp && gpu->temperature != gpu->temperature)
|
||||
pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
|
||||
#endif
|
||||
}
|
||||
|
||||
ffpci_cleanup(pci.access);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
@@ -348,10 +168,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_LIBPCI
|
||||
return pciDetectGPUs(options, gpus);
|
||||
#else
|
||||
FF_UNUSED(options, gpus);
|
||||
return "fastfetch is built without libpci support";
|
||||
#endif
|
||||
return pciDetectGPUs(options, gpus);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ struct FFNvmlData {
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetClockInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
|
||||
|
||||
bool inited;
|
||||
} nvmlData;
|
||||
@@ -32,6 +33,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetClockInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
|
||||
|
||||
if (ffnvmlInit_v2() != NVML_SUCCESS)
|
||||
{
|
||||
@@ -79,6 +81,24 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
if (!device) return "Device not found";
|
||||
}
|
||||
|
||||
nvmlBrandType_t brand;
|
||||
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
|
||||
{
|
||||
switch (brand)
|
||||
{
|
||||
case NVML_BRAND_NVIDIA_RTX:
|
||||
case NVML_BRAND_QUADRO_RTX:
|
||||
case NVML_BRAND_GEFORCE:
|
||||
case NVML_BRAND_TITAN:
|
||||
case NVML_BRAND_TESLA:
|
||||
case NVML_BRAND_QUADRO:
|
||||
*result.type = FF_GPU_TYPE_DISCRETE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.temp)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "gpu.h"
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
|
||||
@@ -10,6 +13,7 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
|
||||
return ffStrbufEqual(&gpu->name, name);
|
||||
}
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName)
|
||||
{
|
||||
if (vendor == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
@@ -44,6 +48,7 @@ static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
@@ -72,7 +77,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
|
||||
// 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"
|
||||
uint32_t vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
|
||||
unsigned vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0;
|
||||
swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId);
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
@@ -139,6 +144,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
||||
const char* dllName;
|
||||
|
||||
@@ -168,6 +174,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -68,6 +68,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
ffStrbufInitStatic(&gpu->platformApi, "DXCore");
|
||||
|
||||
ffStrbufInit(&gpu->driver);
|
||||
uint64_t value = 0;
|
||||
@@ -98,6 +99,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
|
||||
ffStrbufSetStatic(&gpu->vendor, vendorStr);
|
||||
|
||||
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
||||
if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && (options->driverSpecific || options->temp))
|
||||
{
|
||||
FFGpuDriverCondition cond = {
|
||||
@@ -117,6 +119,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF
|
||||
.frequency = &gpu->frequency,
|
||||
}, "/usr/lib/wsl/lib/libnvidia-ml.so");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
typedef struct FFHostResult
|
||||
{
|
||||
FFstrbuf productFamily;
|
||||
FFstrbuf productName;
|
||||
FFstrbuf productVersion;
|
||||
FFstrbuf productSku;
|
||||
FFstrbuf sysVendor;
|
||||
FFstrbuf family;
|
||||
FFstrbuf name;
|
||||
FFstrbuf version;
|
||||
FFstrbuf sku;
|
||||
FFstrbuf serial;
|
||||
FFstrbuf uuid;
|
||||
FFstrbuf vendor;
|
||||
} FFHostResult;
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host);
|
||||
|
||||
@@ -5,32 +5,32 @@
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
// http://newandroidbook.com/ddb/
|
||||
ffSettingsGetAndroidProperty("ro.product.device", &host->productFamily);
|
||||
ffSettingsGetAndroidProperty("ro.product.device", &host->family);
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.product.marketname", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.config.devicename", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->productName)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.brand", &host->productName);
|
||||
ffSettingsGetAndroidProperty("ro.product.marketname", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.vendor.product.display", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.config.devicename", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.brand", &host->name);
|
||||
|
||||
if (ffSettingsGetAndroidProperty("ro.product.model", &host->productVersion))
|
||||
if (ffSettingsGetAndroidProperty("ro.product.model", &host->version))
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCase(&host->productVersion, &host->productName))
|
||||
if (ffStrbufStartsWithIgnCase(&host->version, &host->name))
|
||||
{
|
||||
ffStrbufSubstrAfter(&host->productVersion, host->productName.length);
|
||||
ffStrbufTrimLeft(&host->productVersion, ' ');
|
||||
ffStrbufSubstrAfter(&host->version, host->name.length);
|
||||
ffStrbufTrimLeft(&host->version, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->sysVendor);
|
||||
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->vendor);
|
||||
|
||||
if(host->sysVendor.length && !ffStrbufStartsWithIgnCase(&host->productName, &host->sysVendor))
|
||||
if(host->vendor.length && !ffStrbufStartsWithIgnCase(&host->name, &host->vendor))
|
||||
{
|
||||
ffStrbufPrependS(&host->productName, " ");
|
||||
ffStrbufPrepend(&host->productName, &host->sysVendor);
|
||||
ffStrbufPrependS(&host->name, " ");
|
||||
ffStrbufPrepend(&host->name, &host->vendor);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -169,40 +169,48 @@ static const char* getProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
|
||||
const char* getProductNameWithIokit(FFstrbuf* result)
|
||||
{
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceNameMatching("product"), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("product"));
|
||||
if (!registryEntry)
|
||||
return "IOServiceGetMatchingService() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef productName = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("product-name"), kCFAllocatorDefault, kNilOptions);
|
||||
if (!productName)
|
||||
return "IORegistryEntryCreateCFProperty() failed";
|
||||
|
||||
if (ffCfDictGetString(properties, CFSTR("product-name"), result))
|
||||
break;
|
||||
}
|
||||
return ffCfStrGetString(productName, result);
|
||||
}
|
||||
|
||||
const char* getOthersByIokit(FFHostResult* host)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t registryEntry = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("IOPlatformExpertDevice"));
|
||||
if (!registryEntry)
|
||||
return "IOServiceGetMatchingService() failed";
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef serialNumber = IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (serialNumber)
|
||||
ffCfStrGetString(serialNumber, &host->serial);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef uuid = IORegistryEntryCreateCFProperty(registryEntry, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (uuid)
|
||||
ffCfStrGetString(uuid, &host->uuid);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef manufacturer = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
|
||||
if (manufacturer)
|
||||
ffCfStrGetString(manufacturer, &host->vendor);
|
||||
|
||||
IOObjectRelease(registryEntry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
ffStrbufSetStatic(&host->sysVendor, "Apple");
|
||||
|
||||
const char* error = ffSysctlGetString("hw.model", &host->productFamily);
|
||||
const char* error = ffSysctlGetString("hw.model", &host->family);
|
||||
if (error) return error;
|
||||
|
||||
ffStrbufSetStatic(&host->productName, getProductNameWithHwModel(&host->productFamily));
|
||||
if (host->productName.length == 0)
|
||||
getProductNameWithIokit(&host->productName);
|
||||
if (host->productName.length == 0)
|
||||
ffStrbufSet(&host->productName, &host->productFamily);
|
||||
|
||||
ffStrbufSetStatic(&host->name, getProductNameWithHwModel(&host->family));
|
||||
if (host->name.length == 0)
|
||||
getProductNameWithIokit(&host->name);
|
||||
if (host->name.length == 0)
|
||||
ffStrbufSet(&host->name, &host->family);
|
||||
getOthersByIokit(host);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -4,16 +4,20 @@
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.product", &host->productName);
|
||||
ffCleanUpSmbiosValue(&host->productName);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.family", &host->productFamily);
|
||||
ffCleanUpSmbiosValue(&host->productFamily);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.version", &host->productVersion);
|
||||
ffCleanUpSmbiosValue(&host->productVersion);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.sku", &host->productSku);
|
||||
ffCleanUpSmbiosValue(&host->productSku);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.maker", &host->sysVendor);
|
||||
ffCleanUpSmbiosValue(&host->sysVendor);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.product", &host->name);
|
||||
ffCleanUpSmbiosValue(&host->name);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.family", &host->family);
|
||||
ffCleanUpSmbiosValue(&host->family);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.version", &host->version);
|
||||
ffCleanUpSmbiosValue(&host->version);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.sku", &host->sku);
|
||||
ffCleanUpSmbiosValue(&host->sku);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.serial", &host->serial);
|
||||
ffCleanUpSmbiosValue(&host->serial);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.uuid", &host->uuid);
|
||||
ffCleanUpSmbiosValue(&host->uuid);
|
||||
ffSettingsGetFreeBSDKenv("smbios.system.maker", &host->vendor);
|
||||
ffCleanUpSmbiosValue(&host->vendor);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -7,48 +7,76 @@
|
||||
|
||||
static void getHostProductName(FFstrbuf* name)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name);
|
||||
if(name->length > 0)
|
||||
return;
|
||||
if (ffReadFileBuffer("/sys/firmware/devicetree/base/model", name))
|
||||
{
|
||||
ffStrbufTrimRightSpace(name);
|
||||
ffStrbufTrimRight(name, '\0');
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
}
|
||||
|
||||
ffReadFileBuffer("/sys/firmware/devicetree/base/model", name);
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
if (ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name))
|
||||
{
|
||||
ffStrbufTrimRightSpace(name);
|
||||
ffStrbufTrimRight(name, '\0');
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
}
|
||||
|
||||
ffReadFileBuffer("/sys/firmware/devicetree/base/banner-name", name);
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
|
||||
//does a clear before the read
|
||||
ffReadFileBuffer("/tmp/sysinfo/model", name);
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
if (ffReadFileBuffer("/tmp/sysinfo/model", name))
|
||||
{
|
||||
ffStrbufTrimRightSpace(name);
|
||||
ffStrbufTrimRight(name, '\0');
|
||||
if(ffIsSmbiosValueSet(name))
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufClear(name);
|
||||
}
|
||||
|
||||
static void getHostSerialNumber(FFstrbuf* serial)
|
||||
{
|
||||
if (ffReadFileBuffer("/sys/firmware/devicetree/base/serial-number", serial))
|
||||
{
|
||||
ffStrbufTrimRightSpace(serial);
|
||||
ffStrbufTrimRight(serial, '\0');
|
||||
if(ffIsSmbiosValueSet(serial))
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufClear(serial);
|
||||
}
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
|
||||
getHostProductName(&host->productName);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->family);
|
||||
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &host->name))
|
||||
getHostProductName(&host->name);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->version);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->sku);
|
||||
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_serial", "/sys/class/dmi/id/product_serial", &host->serial))
|
||||
getHostSerialNumber(&host->serial);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_uuid", "/sys/class/dmi/id/product_uuid", &host->uuid);
|
||||
if (!ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->vendor))
|
||||
{
|
||||
if (ffStrbufStartsWithS(&host->name, "Apple "))
|
||||
ffStrbufSetStatic(&host->vendor, "Apple Inc.");
|
||||
}
|
||||
|
||||
//KVM/Qemu virtual machine
|
||||
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
|
||||
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
|
||||
if(ffStrbufStartsWithS(&host->name, "Standard PC"))
|
||||
ffStrbufPrependS(&host->name, "KVM/QEMU ");
|
||||
|
||||
if(host->productFamily.length == 0 && host->productName.length == 0)
|
||||
if(host->family.length == 0 && host->name.length == 0)
|
||||
{
|
||||
const char* wslDistroName = getenv("WSL_DISTRO_NAME");
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(wslDistroName != NULL || getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&host->productName, "Windows Subsystem for Linux");
|
||||
ffStrbufAppendS(&host->name, "Windows Subsystem for Linux");
|
||||
if (wslDistroName)
|
||||
ffStrbufAppendF(&host->productName, " - %s", wslDistroName);
|
||||
ffStrbufAppendS(&host->productFamily, "WSL");
|
||||
ffStrbufAppendF(&host->name, " - %s", wslDistroName);
|
||||
ffStrbufAppendS(&host->family, "WSL");
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY wslVer = ffStrbufCreate(); //Wide characters
|
||||
if(!ffProcessAppendStdOut(&wslVer, (char* const[]){
|
||||
@@ -61,7 +89,7 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
ffStrbufSubstrAfterLastC(&wslVer, ' ');
|
||||
for(uint32_t i = 0; i < wslVer.length; ++i) {
|
||||
if(wslVer.chars[i]) //don't append \0
|
||||
ffStrbufAppendC(&host->productVersion, wslVer.chars[i]);
|
||||
ffStrbufAppendC(&host->version, wslVer.chars[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,69 @@
|
||||
#include "host.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
typedef struct FFSmbiosSystemInfo
|
||||
{
|
||||
FFSmbiosHeader Header;
|
||||
|
||||
uint8_t Manufacturer; // string
|
||||
uint8_t ProductName; // string
|
||||
uint8_t Version; // string
|
||||
uint8_t SerialNumber; // string
|
||||
|
||||
// 2.1+
|
||||
struct {
|
||||
uint32_t TimeLow;
|
||||
uint16_t TimeMid;
|
||||
uint16_t TimeHighAndVersion;
|
||||
uint8_t ClockSeqHiAndReserved;
|
||||
uint8_t ClockSeqLow;
|
||||
uint8_t Node[6];
|
||||
} UUID; // varies
|
||||
uint8_t WakeUpType; // enum
|
||||
|
||||
// 2.4+
|
||||
uint8_t SKUNumber; // string
|
||||
uint8_t Family; // string
|
||||
} FFSmbiosSystemInfo;
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
FF_HKEY_AUTO_DESTROY hKey = NULL;
|
||||
const FFSmbiosSystemInfo* data = (const FFSmbiosSystemInfo*) (*ffGetSmbiosHeaderTable())[FF_SMBIOS_TYPE_SYSTEM_INFO];
|
||||
if (!data)
|
||||
return "System information is not found in SMBIOS data";
|
||||
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\BIOS\", &hKey, NULL) failed";
|
||||
const char* strings = (const char*) data + data->Header.Length;
|
||||
|
||||
ffRegReadStrbuf(hKey, L"SystemProductName", &host->productName, NULL);
|
||||
ffCleanUpSmbiosValue(&host->productName);
|
||||
ffRegReadStrbuf(hKey, L"SystemFamily", &host->productFamily, NULL);
|
||||
ffCleanUpSmbiosValue(&host->productFamily);
|
||||
ffRegReadStrbuf(hKey, L"SystemVersion", &host->productVersion, NULL);
|
||||
ffCleanUpSmbiosValue(&host->productVersion);
|
||||
ffRegReadStrbuf(hKey, L"SystemSKU", &host->productSku, NULL);
|
||||
ffCleanUpSmbiosValue(&host->productSku);
|
||||
ffRegReadStrbuf(hKey, L"SystemManufacturer", &host->sysVendor, NULL);
|
||||
ffCleanUpSmbiosValue(&host->sysVendor);
|
||||
ffStrbufSetStatic(&host->vendor, ffSmbiosLocateString(strings, data->Manufacturer));
|
||||
ffCleanUpSmbiosValue(&host->vendor);
|
||||
ffStrbufSetStatic(&host->name, ffSmbiosLocateString(strings, data->ProductName));
|
||||
ffCleanUpSmbiosValue(&host->name);
|
||||
ffStrbufSetStatic(&host->version, ffSmbiosLocateString(strings, data->Version));
|
||||
ffCleanUpSmbiosValue(&host->version);
|
||||
ffStrbufSetStatic(&host->serial, ffSmbiosLocateString(strings, data->SerialNumber));
|
||||
ffCleanUpSmbiosValue(&host->serial);
|
||||
|
||||
static_assert(offsetof(FFSmbiosSystemInfo, UUID) == 0x08, "FFSmbiosSystemInfo.UUID offset is wrong");
|
||||
if (data->Header.Length > offsetof(FFSmbiosSystemInfo, UUID))
|
||||
{
|
||||
ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
data->UUID.TimeLow, data->UUID.TimeMid, data->UUID.TimeHighAndVersion,
|
||||
data->UUID.ClockSeqHiAndReserved, data->UUID.ClockSeqLow,
|
||||
data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]);
|
||||
}
|
||||
|
||||
static_assert(offsetof(FFSmbiosSystemInfo, SKUNumber) == 0x19, "FFSmbiosSystemInfo.SKUNumber offset is wrong");
|
||||
if (data->Header.Length > offsetof(FFSmbiosSystemInfo, SKUNumber))
|
||||
{
|
||||
ffStrbufSetStatic(&host->sku, ffSmbiosLocateString(strings, data->SKUNumber));
|
||||
ffCleanUpSmbiosValue(&host->sku);
|
||||
}
|
||||
|
||||
if (data->Header.Length > offsetof(FFSmbiosSystemInfo, Family))
|
||||
{
|
||||
ffStrbufSetStatic(&host->family, ffSmbiosLocateString(strings, data->Family));
|
||||
ffCleanUpSmbiosValue(&host->family);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "detection/locale/locale.h"
|
||||
|
||||
#include "common/properties.h"
|
||||
#include "common/parsing.h"
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
|
||||
FF_MAYBE_UNUSED
|
||||
static void getLocaleFromEnv(FFstrbuf* locale)
|
||||
{
|
||||
ffStrbufAppendS(locale, getenv("LANG"));
|
||||
if(locale->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(locale, getenv("LC_ALL"));
|
||||
if(locale->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(locale, getenv("LC_MESSAGES"));
|
||||
}
|
||||
|
||||
static void getLocaleFromStdFn(FFstrbuf* locale)
|
||||
{
|
||||
ffStrbufAppendS(locale, setlocale(LC_ALL, NULL));
|
||||
|
||||
#ifdef LC_MESSAGES
|
||||
if(locale->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(locale, setlocale(LC_MESSAGES, NULL));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ffDetectLocale(FFstrbuf* result)
|
||||
{
|
||||
#if !(defined(__APPLE__) || defined(_WIN32))
|
||||
|
||||
//Ubuntu (and deriviates) use a non standard locale file.
|
||||
//Parse it first, because on distributions where it exists, it takes precedence.
|
||||
//Otherwise use the standard etc/locale.conf file.
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_ETC"/default/locale", "LANG =", result);
|
||||
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_ETC"/locale.conf", "LANG =", result);
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
getLocaleFromEnv(result);
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
#endif
|
||||
|
||||
getLocaleFromStdFn(result);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "detection/locale/locale.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
void ffDetectLocale(FFstrbuf* result)
|
||||
{
|
||||
ffStrbufAppendS(result, getenv("LC_MESSAGES"));
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(result, getenv("LANG"));
|
||||
if(result->length > 0)
|
||||
return;
|
||||
|
||||
#ifdef LC_MESSAGES
|
||||
ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL));
|
||||
|
||||
if(result->length > 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
ffStrbufAppendS(result, setlocale(LC_ALL, NULL));
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "detection/locale/locale.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <locale.h>
|
||||
|
||||
void ffDetectLocale(FFstrbuf* result)
|
||||
{
|
||||
wchar_t name[LOCALE_NAME_MAX_LENGTH];
|
||||
int size = GetUserDefaultLocaleName(name, LOCALE_NAME_MAX_LENGTH);
|
||||
if (size > 1) // including '\0'
|
||||
ffStrbufSetNWS(result, (uint32_t)size - 1, name);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/media/media.h"
|
||||
#include "common/thread.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -11,7 +10,6 @@
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include "common/dbus.h"
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
|
||||
static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResult* result)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,9 @@ typedef struct FFMonitorResult
|
||||
uint32_t physicalWidth; // in mm
|
||||
uint32_t physicalHeight; // in mm
|
||||
bool hdrCompatible;
|
||||
uint16_t manufactureYear;
|
||||
uint16_t manufactureWeek;
|
||||
uint32_t serial;
|
||||
} FFMonitorResult;
|
||||
|
||||
const char* ffDetectMonitor(FFlist* results);
|
||||
|
||||
@@ -40,9 +40,13 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
|
||||
if(!displayInfo) continue;
|
||||
|
||||
bool isVirtual = false;
|
||||
if (ffCfDictGetBool(displayInfo, CFSTR("kCGDisplayIsVirtualDevice"), &isVirtual) == NULL && isVirtual)
|
||||
continue;
|
||||
|
||||
uint8_t edidData[128] = {};
|
||||
uint32_t edidLength = 0;
|
||||
if (false || !ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength))
|
||||
if (ffCfDictGetData(displayInfo, CFSTR("IODisplayEDID"), 0, sizeof(edidData), edidData, &edidLength) == NULL)
|
||||
{
|
||||
uint32_t width, height;
|
||||
ffEdidGetPhysicalResolution(edidData, &width, &height);
|
||||
@@ -75,6 +79,14 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
monitor->physicalHeight = (uint32_t) (size.height + 0.5);
|
||||
monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) ||
|
||||
detectHdrSupportWithNSScreen(display);
|
||||
|
||||
int64_t serial, year, week;
|
||||
if (ffCfDictGetInt64(displayInfo, CFSTR("DisplaySerialNumber"), &serial) == NULL)
|
||||
monitor->serial = (uint32_t) (uint64_t) serial;
|
||||
if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayYearManufacture"), &year) == NULL)
|
||||
monitor->manufactureYear = (uint16_t) year;
|
||||
if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayWeekManufacture"), &week) == NULL)
|
||||
monitor->manufactureWeek = (uint16_t) week;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -29,10 +29,10 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
uint32_t drmDirWithDnameLength = drmDir.length;
|
||||
|
||||
ffStrbufAppendS(&drmDir, "/enabled");
|
||||
char enabled = 'd'; // disabled
|
||||
ffReadFileData(drmDir.chars, sizeof(enabled), &enabled);
|
||||
if (enabled != 'e') // enabled
|
||||
ffStrbufAppendS(&drmDir, "/status");
|
||||
char status = 'd'; // disconnected
|
||||
ffReadFileData(drmDir.chars, sizeof(status), &status);
|
||||
if (status != 'c') // connected
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
@@ -59,6 +59,7 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
ffStrbufInit(&display->name);
|
||||
ffEdidGetName(edidData, &display->name);
|
||||
ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight);
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
|
||||
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ const char* ffDetectMonitor(FFlist* results)
|
||||
FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results);
|
||||
display->width = width;
|
||||
display->height = height;
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
|
||||
display->hdrCompatible = ffEdidGetHdrCompatible(edidData, edidLength); // Doesn't work. edidLength is always 128
|
||||
ffStrbufInit(&display->name);
|
||||
ffEdidGetName(edidData, &display->name);
|
||||
|
||||
@@ -23,15 +23,15 @@ typedef struct OpenCLData
|
||||
|
||||
static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
{
|
||||
cl_platform_id platformID;
|
||||
cl_uint numPlatforms;
|
||||
cl_platform_id platformID = NULL;
|
||||
cl_uint numPlatforms = 0;
|
||||
data->ffclGetPlatformIDs(1, &platformID, &numPlatforms);
|
||||
|
||||
if(numPlatforms == 0)
|
||||
return "clGetPlatformIDs returned 0 platforms";
|
||||
|
||||
cl_device_id deviceID;
|
||||
cl_uint numDevices;
|
||||
cl_device_id deviceID = NULL;
|
||||
cl_uint numDevices = 0;
|
||||
data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices);
|
||||
|
||||
if(numDevices == 0)
|
||||
@@ -40,7 +40,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
if(numDevices == 0)
|
||||
return "clGetDeviceIDs returned 0 devices";
|
||||
|
||||
char version[64];
|
||||
char version[64] = "";
|
||||
data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL);
|
||||
if(!ffStrSet(version))
|
||||
return "clGetDeviceInfo returned NULL or empty string";
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "os.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -72,11 +74,11 @@ static bool detectOSCodeName(FFOSResult* os)
|
||||
|
||||
static void parseOSXSoftwareLicense(FFOSResult* os)
|
||||
{
|
||||
FILE* rtf = fopen("/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf", "r");
|
||||
FF_AUTO_CLOSE_FILE FILE* rtf = fopen("/System/Library/CoreServices/Setup Assistant.app/Contents/Resources/en.lproj/OSXSoftwareLicense.rtf", "r");
|
||||
if(rtf == NULL)
|
||||
return;
|
||||
|
||||
char* line = NULL;
|
||||
FF_AUTO_FREE char* line = NULL;
|
||||
size_t len = 0;
|
||||
const char* searchStr = "\\f0\\b SOFTWARE LICENSE AGREEMENT FOR macOS ";
|
||||
while(getline(&line, &len, rtf) != EOF)
|
||||
@@ -89,11 +91,6 @@ static void parseOSXSoftwareLicense(FFOSResult* os)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(line != NULL)
|
||||
free(line);
|
||||
|
||||
fclose(rtf);
|
||||
}
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os)
|
||||
|
||||
@@ -9,14 +9,6 @@
|
||||
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
|
||||
#include <IOKit/storage/nvme/NVMeSMARTLibExternal.h>
|
||||
|
||||
static inline void wrapIoObjectRelease(io_service_t* service)
|
||||
{
|
||||
assert(service);
|
||||
if (*service)
|
||||
IOObjectRelease(*service);
|
||||
}
|
||||
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
|
||||
|
||||
static inline void wrapIoDestroyPlugInInterface(IOCFPlugInInterface*** pluginInf)
|
||||
{
|
||||
assert(pluginInf);
|
||||
@@ -49,11 +41,11 @@ static const char* detectSsdTemp(io_service_t entryPhysical, double* temp)
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
|
||||
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
|
||||
{
|
||||
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
|
||||
|
||||
|
||||
@@ -8,10 +8,8 @@ typedef struct FFPowerAdapterResult
|
||||
FFstrbuf name;
|
||||
FFstrbuf modelName;
|
||||
FFstrbuf manufacturer;
|
||||
FFstrbuf serial;
|
||||
int watts;
|
||||
} FFPowerAdapterResult;
|
||||
|
||||
const char* ffDetectPowerAdapterImpl(FFlist* results);
|
||||
|
||||
#define FF_POWERADAPTER_UNSET -2
|
||||
#define FF_POWERADAPTER_NOT_CONNECTED -1
|
||||
const char* ffDetectPowerAdapter(FFlist* results);
|
||||
|
||||
@@ -2,51 +2,40 @@
|
||||
#include "poweradapter.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
#include <IOKit/ps/IOPSKeys.h>
|
||||
|
||||
const char* ffDetectPowerAdapterImpl(FFlist* results)
|
||||
const char* ffDetectPowerAdapter(FFlist* results)
|
||||
{
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
while((registryEntry = IOIteratorNext(iterator)) != 0)
|
||||
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef details = IOPSCopyExternalPowerAdapterDetails();
|
||||
if (details && CFDictionaryContainsKey(details, CFSTR(kIOPSPowerAdapterWattsKey)))
|
||||
{
|
||||
CFMutableDictionaryRef properties;
|
||||
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
||||
{
|
||||
IOObjectRelease(registryEntry);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFPowerAdapterResult* adapter = ffListAdd(results);
|
||||
|
||||
ffStrbufInit(&adapter->name);
|
||||
ffStrbufInit(&adapter->description);
|
||||
ffStrbufInit(&adapter->manufacturer);
|
||||
ffStrbufInit(&adapter->modelName);
|
||||
adapter->watts = FF_POWERADAPTER_UNSET;
|
||||
ffStrbufInit(&adapter->serial);
|
||||
adapter->watts = 0;
|
||||
|
||||
CFDictionaryRef adapterDict;
|
||||
if(!ffCfDictGetDict(properties, CFSTR("AdapterDetails"), &adapterDict))
|
||||
ffCfDictGetString(details, CFSTR(kIOPSNameKey), &adapter->name);
|
||||
if (ffCfDictGetString(details, CFSTR("Model"), &adapter->modelName) != NULL)
|
||||
{
|
||||
if (ffCfDictGetInt(adapterDict, CFSTR("Watts"), &adapter->watts))
|
||||
{
|
||||
adapter->watts = FF_POWERADAPTER_NOT_CONNECTED;
|
||||
continue;
|
||||
}
|
||||
ffCfDictGetString(adapterDict, CFSTR("Name"), &adapter->name);
|
||||
ffCfDictGetString(adapterDict, CFSTR("Description"), &adapter->description);
|
||||
ffCfDictGetString(adapterDict, CFSTR("Manufacturer"), &adapter->manufacturer);
|
||||
ffCfDictGetString(adapterDict, CFSTR("Model"), &adapter->modelName);
|
||||
int adapterId;
|
||||
if (ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterIDKey), &adapterId) == 0)
|
||||
ffStrbufSetF(&adapter->modelName, "%d", adapterId);
|
||||
}
|
||||
|
||||
CFRelease(properties);
|
||||
IOObjectRelease(registryEntry);
|
||||
ffCfDictGetString(details, CFSTR("Manufacturer"), &adapter->manufacturer);
|
||||
ffCfDictGetString(details, CFSTR("Description"), &adapter->description);
|
||||
if (ffCfDictGetString(details, CFSTR("SerialString"), &adapter->serial) != NULL)
|
||||
{
|
||||
int serialNumber;
|
||||
if (ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterSerialNumberKey), &serialNumber) == 0)
|
||||
ffStrbufSetF(&adapter->serial, "%X", serialNumber);
|
||||
}
|
||||
ffCfDictGetInt(details, CFSTR(kIOPSPowerAdapterWattsKey), &adapter->watts);
|
||||
}
|
||||
|
||||
IOObjectRelease(iterator);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "poweradapter.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFlist* results)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
|
||||
|
||||
//type must exist and be "Mains"
|
||||
ffStrbufAppendS(dir, "/type");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Mains"))
|
||||
return;
|
||||
|
||||
//scope may not exist or must not be "Device" (?)
|
||||
ffStrbufAppendS(dir, "/scope");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
|
||||
return;
|
||||
|
||||
ffStrbufAppendS(dir, "/online");
|
||||
char online = '1';
|
||||
ffReadFileData(dir->chars, sizeof(online), &online);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if (online == '0')
|
||||
return;
|
||||
|
||||
//input_power_limit must exist and be not empty
|
||||
ffStrbufAppendS(dir, "/input_power_limit");
|
||||
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if (!available)
|
||||
return;
|
||||
FFPowerAdapterResult* result = ffListAdd(results);
|
||||
ffStrbufInit(&result->name);
|
||||
ffStrbufInit(&result->description);
|
||||
result->watts = (int) (ffStrbufToDouble(&tmpBuffer) / 1e6 + 0.5);
|
||||
ffStrbufInit(&result->manufacturer);
|
||||
ffStrbufInit(&result->modelName);
|
||||
ffStrbufInit(&result->serial);
|
||||
|
||||
ffStrbufAppendS(dir, "/manufacturer");
|
||||
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
else if (ffStrEquals(id, "macsmc-ac")) // asahi
|
||||
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufAppendS(dir, "/model_name");
|
||||
if (ffReadFileBuffer(dir->chars, &result->modelName))
|
||||
ffStrbufTrimRightSpace(&result->modelName);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufAppendS(dir, "/serial_number");
|
||||
if (ffReadFileBuffer(dir->chars, &result->serial))
|
||||
ffStrbufTrimRightSpace(&result->serial);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
}
|
||||
|
||||
const char* ffDetectPowerAdapter(FFlist* results)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
|
||||
|
||||
uint32_t baseDirLength = baseDir.length;
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
|
||||
if(dirp == NULL)
|
||||
return "opendir(\"/sys/class/power_supply/\") == NULL";
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, ".."))
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&baseDir, entry->d_name);
|
||||
parsePowerAdapter(&baseDir, entry->d_name, results);
|
||||
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user