diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 52994bb..0000000 --- a/docs/README.md +++ /dev/null @@ -1,383 +0,0 @@ -# Deepcool - -An unofficial Linux kernel module Provides early boot support and sysfs -interface for monitoring and controlling device display modes for Deepcool -Digital USB HID devices (CPU coolers, AIOs, cases). The module runs directly in -kernel space, providing early boot support and standard Linux interfaces for -controlling Deepcool Digital USB HID devices. - -## Motive - -[deepcool-digital-linux]: https://github.com/Nortank12/deepcool-digital-linux - -This project exists solely because I hoped to replace the userspace daemon with -a kernel module that is always loaded. Simply put, I don't need it to be an -userspace daemon, and I am under the impression that using the Linux kernel APIs -directly will yield be better performance, or at least less overhead. - -[deepcool-digital-linux] is an userspace daemon that does a little more than -this project, and is a more suitable replacement if you are not looking to taint -your kernel with out-of-tree modules. Not that a "tainted kernel" is inherently -bad, though. There are different usecases. See below for a better comparison -between **Deepcool** (this module) and **deepcool-digital-linux**, the userspace -daemon. - -## Features - -The primary feature of Deepcool is that it supports early boot, or in other -words, its functionality fully available _as soon as you reach the kernel_. Rest -of the functionality is almost identical with little caveats. - -- **Real-time Monitoring**: CPU temperature, usage, power, frequency -- **Display Modes**: Auto-cycling, CPU temp, CPU usage, CPU power, and more -- **Sysfs Interface**: Standard Linux interface for configuration -- **Automatic Device Detection**: Supports most Deepcool Digital product series -- **Multiple Device Series Support**: - - AK Series (AK400 DIGITAL, AK500 DIGITAL, AK620 DIGITAL) - - AK400 PRO, AK620 PRO - - LS Series - - AG Series - - LQ Series - - LD Series - - LP Series - - CH Series (Gen1, Gen2, CH510) - -> [!INFO] -> **For device support, please refer to the -> [device support matrix](#device-support-matrix) below** - -If you believe there is anything missing that belongs in a kernel module, please -feel free to let me know. I'd be happy to discuss. - -## Usage - -To use Deepcool, you must load it in your kernel. The installation steps may -differ based on your distro, but most distros should be supported out of the -box. - -### Requirements - -- Linux kernel 5.10 or later -- Kernel headers for your running kernel -- Build essentials (gcc, make) -- Root/sudo access for installation - -#### Kernel Configuration - -The following kernel options must be enabled: - -```plaintext -CONFIG_HID=y or m -CONFIG_HIDRAW=y or m -CONFIG_USB_HID=y or m -CONFIG_THERMAL=y -CONFIG_CPU_FREQ=y -CONFIG_CPUFREQ_STATS=y -CONFIG_SYSFS=y -``` - -Most of those features are enabled on most kernels, but is best to check before -you build. `zcat` can be used to check the configuration for your current kernel -configuration: - -```sh -$ zcat /proc/config.gz | grep CONFIG_HID -# => CONFIG_HIDRAW=y -``` - -For Intel RAPL power monitoring: - -```plaintext -CONFIG_POWERCAP=y -CONFIG_INTEL_RAPL=y or m -``` - -### Building - -Once you confirm that you meet the requirements, you may build the kernel -module. To build, navigate to the cloned directory and run `make`. - -```bash -$ make -#=> The module will be built as `deepcool.ko`. -``` - -## Installation - -### Manual Installation - -[DKMS framework]: https://wiki.archlinux.org/title/Dynamic_Kernel_Module_Support - -The Makefile provides a task to install Deepcool for Linux distributions using -the [DKMS framework]. NixOS should refer to the section below. - -```bash -# Build the module -make - -# Install to system -sudo make dkms-install - -# Load the module -sudo modprobe deepcool -``` - -## Automatic Loading on Boot - -Create a module configuration file: - -```bash -sudo tee /etc/modules-load.d/deepcool_digital.conf < mode - -# Available modes: -# - auto (cycle between supported metrics) -# - cpu_temp (CPU temperature) -# - cpu_usage (CPU usage percentage) -# - cpu_power (CPU power consumption) -# - cpu_freq (CPU frequency) -# - cpu_fan (CPU fan speed, if supported) -# - gpu_temp (GPU temperature, if supported) -# - gpu_usage (GPU usage, if supported) -# - gpu_power (GPU power, if supported) -``` - -**`update_interval`** - Update interval in milliseconds (100-2000) - -```bash -# View current interval -cat update_interval - -# Set to 500ms -echo 500 > update_interval -``` - -**`fahrenheit`** - Temperature unit (0=Celsius, 1=Fahrenheit) - -```bash -# Use Fahrenheit -echo 1 > fahrenheit - -# Use Celsius -echo 0 > fahrenheit -``` - -**`alarm`** - Temperature alarm (0=off, 1=on) - -```bash -# Enable alarm -echo 1 > alarm - -# Disable alarm -echo 0 > alarm -``` - -#### Sensor Attributes (Read-Only) - -**`cpu_temp`** - CPU temperature (°C or °F based on fahrenheit setting) - -```bash -cat cpu_temp -``` - -**`cpu_usage`** - CPU usage percentage (0-100) - -```bash -cat cpu_usage -``` - -**`cpu_power`** - CPU power consumption (Watts) - -```bash -cat cpu_power -``` - -**`cpu_freq`** - CPU frequency (MHz) - -```bash -cat cpu_freq -``` - -### Examples - -#### Set CPU temperature display with Fahrenheit - -```bash -echo "cpu_temp" > /sys/bus/hid/drivers/deepcool_digital/0003:3633:0007.XXXX/mode -echo 1 > fahrenheit -echo 1 > alarm -``` - -#### Auto-cycle between metrics at 1-second intervals - -```bash -echo "auto" > /sys/bus/hid/drivers/deepcool_digital/0003:3633:0007.XXXX/mode -echo 1000 > /sys/bus/hid/drivers/deepcool_digital/0003:3633:0007.XXXX/update_interval -``` - -#### Monitor CPU power consumption - -```bash -echo "cpu_power" > /sys/bus/hid/drivers/deepcool_digital/0003:3633:0007.XXXX/mode -``` - -#### Create a simple monitoring script - -```bash -#!/usr/bin/env bash -DEVICE="/sys/bus/hid/drivers/deepcool_digital/0003:3633:0007.XXXX" - -while true; do - echo "CPU Temp: $(cat $DEVICE/cpu_temp)°C" - echo "CPU Usage: $(cat $DEVICE/cpu_usage)%" - echo "CPU Power: $(cat $DEVICE/cpu_power)W" - echo "CPU Freq: $(cat $DEVICE/cpu_freq)MHz" - echo "---" - sleep 1 -done -``` - -## Device Support Matrix - - - -| Device Series | Auto Mode | Alarm | Fahrenheit | Secondary Display | Rotation | -| ------------- | --------- | ------ | ---------- | ----------------- | -------- | -| AK Series | ✓ | ✓ | ✓ | ✗ | ✗ | -| AK400 PRO | ✓ | HW | ✓ | ✗ | ✗ | -| AK620 PRO | ✓ | HW | ✓ | ✗ | ✗ | -| LS Series | ✓ | ✓ | ✓ | ✗ | ✗ | -| AG Series | ✓ | ✓ | ✗ | ✗ | ✗ | -| LP Series | ✓ | ✗ | ✓ | ✓ | ✓ | -| LQ Series | ✓ | ✓ | ✓ | ✗ | ✗ | -| CH Series | ✓ | varies | varies | varies | ✗ | - - - -**Legend:** - -| Supported | Not Supported | Hardware-Controlled (Fixed thresholds) | -| :-------: | :-----------: | :------------------------------------: | -| ✓ | ✗ | HW | - -## How It Works - -### Initialization - -1. Module loads and registers HID driver -2. Kernel calls `probe()` when device is detected -3. Driver identifies device series and capabilities -4. Sysfs attributes are created -5. Work queue is scheduled for periodic updates - -### Runtime Operation - -``` -Timer fires (every update_interval ms) - ↓ -Work queue handler executes - ↓ -Read CPU sensors: - * Temperature from thermal subsystem - * Usage from kernel CPU statistics - * Frequency from CPUFreq - * Power from Intel RAPL - ↓ -Build device-specific packet - ↓ -Send HID output report over USB - ↓ -Display updates - ↓ -Reschedule work queue -``` - -### User Interaction - -``` -User writes to sysfs attribute - ↓ -Kernel calls store() handler - ↓ -Validate input - ↓ -Update device configuration - ↓ -Next work cycle uses new configuration -``` - -## Contributing - -Contributions are always welcome! When submitting patches, please try to follow -the several recommendations: - -- Tabs and 8 character indentations are heretical. A cardinal sin. Please don't - use those. -- Testing on your own hardware is recommended, but not a hard-requirement -- If there is device-specific behaviour (or non-behaviour), please document it! -- Include dmesg output for new devices - -Refer to [BUILD.md](./BUILD.md) for additional notes on working with and -building Deepcool. - -## License - -GPL-2.0-only - -## Attributions - -[Nortank12]: https://github.com/Nortank12 -[zenpower]: https://github.com/ocerman/zenpower - -There are a few projects that I would like to give credit to. Namely I'd like to -thank the [deepcool-digital-linux] project for the inspiration and the device -data. This project would be incredibly annoying to do without the efforts of -[Nortank12]. Please make sure to give them some love! - -I'd like to extend my thanks to the [zenpower] project that provided insight -into developing Linux kernel modules, and the DKMS installation tasks. Thank you -:) - -## See Also - -- [deepcool-digital-linux]: an userspace daemon providing similar functionality, - with better GPU support. -- Linux HID documentation: `Documentation/hid/` in kernel source -- Sysfs documentation: `Documentation/filesystems/sysfs.txt` diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 934192c..0000000 --- a/flake.lock +++ /dev/null @@ -1,27 +0,0 @@ -{ - "nodes": { - "nixpkgs": { - "locked": { - "lastModified": 1759381078, - "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 7fb4142..0000000 --- a/flake.nix +++ /dev/null @@ -1,96 +0,0 @@ -{ - inputs.nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; - - outputs = { - self, - nixpkgs, - }: let - system = "x86_64-linux"; - pkgs = nixpkgs.legacyPackages.${system}; - lib = nixpkgs.lib; - in { - packages."${system}" = let - inherit (pkgs.linuxPackages_latest) kernel; - kmod = pkgs.callPackage ./nix/kmod.nix {inherit kernel;}; - in { - inherit kernel kmod; - }; - - nixosConfigurations."gamma" = let - inherit (lib) nixosSystem; - inherit (lib.modules) mkDefault; - in - nixosSystem { - system = null; - modules = [ - ({modulesPath, ...}: { - imports = [(modulesPath + "/profiles/qemu-guest.nix")]; - networking.hostName = "gamma"; - - boot = { - growPartition = false; - kernelParams = ["console=ttyAMA0,115200n8" "console=tty0"]; - consoleLogLevel = mkDefault 7; # ground control to kernel - }; - - # Empty password - # root can login without a password - users.extraUsers.root.initialHashedPassword = ""; - - # Nixpkgs options - nixpkgs.pkgs = pkgs; # discard everything else, follow flake `pkgs` - - # Packages - environment.systemPackages = [pkgs.microfetch]; - - # Bootable - fileSystems."/boot" = { - device = "/dev/vda1"; - fsType = "vfat"; - }; - - fileSystems."/" = { - device = "/dev/vda2"; - fsType = "ext4"; - }; - - boot.loader.grub = { - efiSupport = true; - efiInstallAsRemovable = true; - device = "nodev"; - }; - - # Kernel fun - boot = { - # Use kernel package defined in flake.nix - kernelPackages = pkgs.linuxPackagesFor self.packages.${system}.kernel; # exposed kernel - - # Get test module from flake outputs - extraModulePackages = [self.packages.${system}.kmod]; - - # Load module from package. - # Alternatively, `$ modprobe test` would work too - kernelModules = ["deepcool"]; - }; - - # Make it smaller - documentation = { - doc.enable = false; - man.enable = false; - nixos.enable = false; - info.enable = false; - }; - - # Get out. - programs = { - bash.completion.enable = false; - command-not-found.enable = false; - }; - - # Shut up. - system.stateVersion = "25.11"; - }) - ]; - }; - }; -} diff --git a/nix/kmod.nix b/nix/kmod.nix deleted file mode 100644 index 0d4dabb..0000000 --- a/nix/kmod.nix +++ /dev/null @@ -1,76 +0,0 @@ -{ - lib, - stdenv, - linuxPackages_latest, - kernel ? linuxPackages_latest.kernel, - ... -}: let - pname = "deepcool"; - version = "0.1.0"; -in - stdenv.mkDerivation { - inherit pname version; - - src = let - fs = lib.fileset; - sp = ../.; - in - fs.toSource { - root = sp; - fileset = fs.unions [ - (sp + /deepcool.c) - (sp + /Makefile) - ]; - }; - - enableParallelBuilding = true; - nativeBuildInputs = kernel.moduleBuildDependencies; - hardeningDisable = ["pic" "format"]; - - env = { - KVERSION = kernel.modDirVersion; - INSTALL_MOD_PATH = builtins.placeholder "out"; - }; - - buildPhase = '' - runHook preBuild - echo "Kernel version: $KVERSION" - make -C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build \ - M=$(pwd) \ - modules - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - echo "Module Installation Path: $INSTALL_MOD_PATH" - make -C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build \ - M=$(pwd) \ - modules_install - runHook postInstall - ''; - - postInstall = '' - if [ -d $out/lib/modules/${kernel.modDirVersion}/extra ]; then - mkdir -p $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/hid - find $out/lib/modules/${kernel.modDirVersion}/extra -name "*.ko*" \ - -exec mv {} $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/hid/ \; - rmdir $out/lib/modules/${kernel.modDirVersion}/extra 2>/dev/null || true - fi - ''; - - passthru = { - inherit kernel; - kernelVersion = kernel.modDirVersion; - moduleName = "deepcool_digital"; - modulePath = "kernel/drivers/hid/deepcool_digital.ko"; - }; - - meta = { - description = "Linux kernel module for Deepcool Digital USB HID devices"; - license = lib.licenses.gpl2Plus; - maintainers = []; - platforms = lib.platforms.linux; - broken = lib.versionOlder kernel.version "5.10"; - }; - }