Remove 'handsfree' as an audio option, permanently, completely, at the lowest level possible

image

In the image above we can see ‘handsfree’ as an option.

Ideally, I want to completely delete this at the lowest possible level - as if support for this profile were completely removed from my computer.

With the audio devices I use, this ‘handsfree’ mode is nothing more than a ‘low quality audio’ mode which enables itself constantly. I do not want it. My computer should operate as if this profile has never existed.

My full config is available here GitHub - WillsterJohnson/nix-config: My nix config, I’m running an AMD laptop from https://frame.work (16 inch model).

What do I need to do to completely nuke this worthless (to me at least) option from my OS?

2 Likes

here might be some hints: WirePlumber - ArchWiki
let us know if it works!

Give this a shot:

services.pipewire.wireplumber.extraConfig = {
  willsters-rage-at-handsfree-knows-no-rational-bounds = {
    "monitor.bluez.properties" = {
      "override.bluez5.roles" = [ "a2dp_sink" "a2dp_source" "bap_sink" "bap_source" "hsp_hs" "hsp_ag" "hfp_ag" ];
    };
  };
};
5 Likes

seems like that disables the device entirely rather than just the one profile. I did go through the given wpctl commands with both headset and handsfree profiles selected but the unique node.name is the same in both cases.

I’ll keep digging, maybe the solution is in there somewhere.

you got it, there might not even be irrational bounds all things considered.

damn thing has followed me across three distros, two laptops, four headsets/earbuds, and five years. never have found a way out.

I gave that snippet a shot; add to config, rebuild, restart my laptop, but it didn’t work. I figured maybe removing everything but a2dp sink & source might work as the profile I do want defaults to a2dp, but no luck.

‘handsfree’ remains and refuses to budge.


My full config for services.pipewire below. maybe I’ve screwed up something obvious, I’m far, far from an expert at this lol

  services.pipewire = {
    enable = true;
    # audio.enable = true;
    alsa.enable = true;
    # alsa.support32Bit = true;
    pulse.enable = true;
    jack.enable = true;
    wireplumber = {
      extraConfig = {
        willsters-rage-at-handsfree-knows-no-rational-bounds = {
          "monitor.bluez.properties" = {
            "override.bluez5.roles" = ["a2dp_sink" "a2dp_source"];
          };
        };
        # some of this is from another thread I found, didn't work.
        # I'm sure I'll clean this up eventually
        "override.monitor.bluez.properties" = {
          "bluez5.enable-msbc" = false;
          "bluez5.enable-soc" = false;
          "bluez5.hfphsp-backend" = "none";
          "bluez5.roles" = [
            "a2dp_sink"
            "a2dp_source"
          ];
        };
      };
    };
  };

Well, you asked for it. Maybe there’s a patch you could write for Pipewire that changes the behavior if the type matches.

You can add this with an overlay:

nixpkgs.overlays = pkgs.lib.singleton (final: prev: {
  pipewire = prev.pipewire.overrideAttrs (prevAttrs: {
    patches = prevAttrs.patches or [] ++ [
      ./stop-with-the-handsfree-crap-i-swear-to-deity.damnit.patch
    ];
  });
})

If that’s not low level enough for you, you may be able to patch your kernel. This looks like the right place to look.

boot.kernelPatches = [
 ./pipewire-wasnt-good-enough-lets-recompile-linux.diff
];

Hardware modifications are unfortunately outside the scope of most Nix configurations. However, you could also write to Logitech and ask them to compile their firmware with Nix. Failing that, fetchurl on the headset firmware binary and a stdenv.mkDerivation call might be able to solve the problem for you too after some analysis with Ghidra.

I look forward to seeing what you decide. :wink:

5 Likes