Incorrect bluetooth device type and icon

Greetings to my dear Manjaro users.

This issues has been bothering me for quite a while, but I never had enough courage to resolve it once and for all until now.

The system recognizes my Bluetooth bookshelf speakers as a headset, so it is represented by headset icons, wrong description, and it even introduces dummy microphone to the system. And it’s not Linux or Manjaro’s fault! That is all because device class of the speakers is incorrectly set to “headset” on the firmware level (Class=0x240404 instead of something like 0x200400), and there is no way to update the firmware. But I want my system to see and treat the device as actual speakers, and not… headset

So, trying to change device class by editing config file /var/lib/bluetooth/[bluetooth_adapter_address]/[paired_device_address]/info is pointless, because it requires restarting bluetooth.service and upon next device re-connection it gets overridden by its firmware data. I tried to mess around with bluez-tools and bluez-utils, but seems they can’t help either, and neither can help Google or chatGPT prompting.

But I still think there must be a way to deal with it on the OS level somewhere somehow.

So can anybody point me to the right direction, please?

I’m on Gnome 47+ and 6.6.63-1-MANJARO, if it’s relevant.

You should look at creating an udev rule to customize the behaviour

See → udev - ArchWiki

Especially pay attention to the external resources at the bottom of the page.

1 Like

If I understand this correctly, I need to create a udev rule to run some script on device connection. Well, as I said I tried to change /var/lib/bluetooth/[bluetooth_adapter_address]/[paired_device_address]/info but it didn’t work. Is there another config file in the system I am not aware of?

Bluetooth main.conf is ignored – no way to apply settings – Arch Linux Forums

to set the device class for your bluetooth device, first open btmon in a second terminal and on the main terminal try

bluetoothctl mgmt.class 4 20

You will see in btmon that 4 20 gives you the necessary device class for Audio device / Loudspeaker. You can try with different numbers and see the results. I couldn’t find a way to change the major service class the device advertises itself as.

none of this works every time… Especially settings the class, and I absolutely have no idea why it is so unreliable, but this is way beyond my comprehension.

Or install bluez-deprecated-tools and use hciconfig

askubuntu.com - how-to-change-bluetooth-device-class

First, find your interface name:

hciconfig

It should give you the name of the interface, e.g., hci0.

Given that display your interface class:

hciconfig hci0 class

That should display your device class.

Finally, with super user privilege:

sudo hciconfig hci0 class 000408

should set up new class of your device.

Unfortunately, both methods only change the class of my computer Bluetooth controller, and not of the paired device.

And man, bluetoothctl mgmt has some weird interface. When you think you’ve connected to the desired device to apply changes to, it actually applies changes to your controller. No wonder, since device’s firmware cannot be modified this way, but it’s nonetheless misleading.

If the speakers work for playing audio, but are shown as a headset rather than speakers in audio GUI controls (or pactl list sinks ) Audio device can be renamed in PulseAudio or PipeWire

PulseAudio/Examples - Renaming Devices - ArchWiki

stackexchange.com - rename devices in pipewire

I’m excited! Wireplumber seems to be close enough to the solution.
At least it is aware of underlying bluetooth device properties like classes.

However, I created ~/.config/wireplumber/51-device-rename.conf
with the following content:

monitor.bluez.rules = [
  {
    matches = [
      {
        ## Matches all sources.
        device.name = "bluez_card.0C_AE_BD_03_37_0C"
      }
    ]
    actions = {
      update-props = {
        # Common node & audio adapter properties may also be set here
        api.bluez5.class = "0x200414",
        device.description = "EDIFIER R1042BT Test",
        device.alias = "EDIFIER R1042BT Test"
      }
    }
  }
]

Then I did systemctl --user restart wireplumber.service
But the output of the wpctl inspect did not change:

$ wpctl inspect 91                                                                                                                   
id 91, type PipeWire:Interface:Device
    api.bluez5.address = "0C:AE:BD:03:37:0C"
    api.bluez5.class = "0x240404"
    api.bluez5.connection = "connected"
    api.bluez5.device = ""
    api.bluez5.icon = "audio-headset"
    api.bluez5.id = "17"
    api.bluez5.path = "/org/bluez/hci0/dev_0C_AE_BD_03_37_0C"
    bluez5.profile = "off"
  * client.id = "40"
    device.alias = "EDIFIER R1042BT"
  * device.api = "bluez5"
    device.bus = "bluetooth"
  * device.description = "EDIFIER R1042BT"
    device.form-factor = "headset"
    device.icon-name = "audio-headset-bluetooth"
  * device.name = "bluez_card.0C_AE_BD_03_37_0C"
    device.string = "0C:AE:BD:03:37:0C"
  * factory.id = "15"
  * media.class = "Audio/Device"
  * object.serial = "166"

I assume that some properties cannot be changed for a reason, but I know for a fact alias is modifiable. It didn’t change though.

What am I doing wrong?