{ pkgs, inputs, ... }: # All MediaTek MT7927 / MT6639 (Filogic 380) WiFi 7 + Bluetooth support for this # host in one place: the upstream flake module, the hardware enablement, and the # workarounds needed to actually make it function on nixos-unstable. # # Workaround background: on current nixos-unstable, `boot.extraModulePackages` # modules placed in `extra/` are NOT indexed by `depmod` (modules.dep / # modules.alias contain zero `extra/` entries). As a result `modprobe`/udev # resolve mt7925e / btusb to the stock in-tree drivers, which do not support the # MediaTek MT7927 (14c3:7927). We therefore force the patched out-of-tree modules # to load by explicit path, blacklist the in-tree collisions so udev cannot bind # them first, and fix the BT firmware path the driver expects. let # The upstream mt7927 flake installs the BT firmware under # `mediatek/mt6639/`, but the patched btmtk driver requests it from # `mediatek/mt7927/`. Provide it at the expected path. mt7927BtFirmwareFix = pkgs.runCommand "mt7927-bt-firmware-fix" { } '' src="${inputs.mt7927.packages.${pkgs.system}.firmware}/lib/firmware/mediatek/mt6639/BT_RAM_CODE_MT6639_2_1_hdr.bin" install -Dm644 "$src" \ "$out/lib/firmware/mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin" ''; in { imports = [ inputs.mt7927.nixosModules.default ]; hardware.mediatek-mt7927 = { enable = true; enableWifi = true; enableBluetooth = true; disableAspm = true; # Highly recommended to fix upload speeds }; hardware.firmware = [ mt7927BtFirmwareFix ]; boot.blacklistedKernelModules = [ # Whole mt76 stack (patched extra/ copy replaces it entirely). "mt76" "mt76_connac_lib" "mt792x_lib" "mt7921_common" "mt7921e" "mt7925_common" "mt7925e" # Patched bluetooth. "btusb" "btmtk" ]; systemd.services.mt7927-force = { description = "Force-load patched MediaTek MT7927 (Filogic 380) kernel modules"; wantedBy = [ "multi-user.target" ]; before = [ "network.target" "NetworkManager.service" ]; path = [ pkgs.kmod ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' KVER="$(uname -r)" EXTRA="/run/booted-system/kernel-modules/lib/modules/$KVER/extra" # Load in-tree core dependencies (these ARE indexed, so modprobe works). modprobe mac80211 cfg80211 rfkill led-class bluetooth || true # Defensive: drop any in-tree mt76 modules that may have been pulled in # (e.g. via boot.kernelModules) so the patched copies can bind instead. rmmod mt7925e mt7921e mt7925_common mt7921_common mt792x_lib mt76_connac_lib mt76 2>/dev/null || true insmod_x() { local mod="$1" local name name="''${mod##*/}"; name="''${name%.ko}" if lsmod | grep -q "^$name "; then echo "mt7927-force: $name already loaded, skipping" else echo "mt7927-force: insmod $mod" insmod "$mod" || echo "mt7927-force: FAILED to insmod $mod" fi } # Patched mt76 stack (full replacement, dependency order). insmod_x "$EXTRA/mt76/mt76.ko" insmod_x "$EXTRA/mt76/mt76-connac-lib.ko" insmod_x "$EXTRA/mt76/mt792x-lib.ko" insmod_x "$EXTRA/mt76/mt7921/mt7921-common.ko" insmod_x "$EXTRA/mt76/mt7925/mt7925-common.ko" insmod_x "$EXTRA/mt76/mt7921/mt7921e.ko" insmod_x "$EXTRA/mt76/mt7925/mt7925e.ko" # Patched bluetooth. The patched btmtk/btusb need symbols from the # in-tree bluetooth core (bluetooth.ko) and the btrtl/btintel/btbcm # helpers, so load those first (they are indexed and modprobe-able). for m in bluetooth btrtl btintel btbcm rfkill ecdh_generic ecc crc16; do if modprobe "$m" 2>/dev/null; then echo "mt7927-force: modprobe $m ok" else echo "mt7927-force: modprobe $m FAILED (continuing)" fi done insmod_x "$EXTRA/bluetooth/btmtk.ko" insmod_x "$EXTRA/bluetooth/btusb.ko" ''; }; }