Commit graph

4526 commits

Author SHA1 Message Date
Pauli Virtanen
84bfbd92a1 bluez5: bap: prefer high-reliability qos for 44.1/48 kHz
On some device combinations (MT7925 / Sony LinkBuds S) the low-latency
48 kHz QoS crackle.

It's probably better to default to high-reliability for those, until we
have proper quality vs. latency configuration in place.
2026-02-03 19:10:25 +02:00
Wim Taymans
2c0988ab4c bluez-dbus: fix adapter memcpy length
sizeof(adapter) is larger than the big_entry->adapter and so the code
would copy too much. Instead only copy the strlen of the parsed
adapter, which we checked above to be smaller than the available size.

This doesn't copy the 0 byte because the memory is assumed to be 0
filled already by the calloc.

If the address is exactly the HCI_DEV_NAME_LEN, it will result in a non-0
terminated string, which may or may not be a problem...
2026-02-03 10:16:22 +01:00
Wim Taymans
3c80f0fb3e filter-graph: add gain option to sofa
So that we can apply the gain to the IR. This is more efficient than
doing a volume after the convolution.

See #5098
2026-02-02 16:28:54 +01:00
Alexander Sarmanow
f34a87fe38 bluez5: bap: add support for per adapter broadcast config
By setting the hci handle (e.g. hci0) of the desired adapter, the BIG
config will only applied on that adapter. In case no "adapter" entry in
the config is given, it will be applied on all adapters.

Signed-off-by: Alexander Sarmanow <a.sarmanow@televic.com>
2026-02-02 11:15:41 +00:00
Frédéric Danis
1a478c7147 bluez5: Fix stack smashing crash in remote_endpoint_update_props()
Commit 2942bae034 introduced parsing of
"SupportedFeatures" which uses a third DBusMessageIter pointer.

*** stack smashing detected ***: terminated
==389050==
==389050== Process terminating with default action of signal 6 (SIGABRT)
==389050==    at 0x4F57B2C: __pthread_kill_implementation (pthread_kill.c:44)
==389050==    by 0x4F57B2C: __pthread_kill_internal (pthread_kill.c:78)
==389050==    by 0x4F57B2C: pthread_kill@@GLIBC_2.34 (pthread_kill.c:89)
==389050==    by 0x4EFE27D: raise (raise.c:26)
==389050==    by 0x4EE18FE: abort (abort.c:79)
==389050==    by 0x4EE27B5: __libc_message_impl.cold (libc_fatal.c:134)
==389050==    by 0x4FEFC48: __fortify_fail (fortify_fail.c:24)
==389050==    by 0x4FF0ED3: __stack_chk_fail (stack_chk_fail.c:24)
==389050==    by 0xBC1D1A1: remote_endpoint_update_props (bluez5-dbus.c:3137)
==389050==    by 0xB53609F: ???
==389050==    by 0x1DF: ???
==389050==    by 0x61C17BF: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==389050==    by 0x1DF: ???
==389050==    by 0xC5ED113: ???
2026-01-30 18:02:38 +01:00
Wim Taymans
47dd57faa7 filter-graph: handle other SOFA errors as errno 2026-01-29 16:50:52 +01:00
Mengshi Wu
bc53b6b343 bluez5: Remove unused bt_features variable in sco_create_socket. 2026-01-25 17:26:15 +00:00
Mengshi Wu
254620676f bluez5: Use named constants for Bluetooth codec IDs
Replace magic numbers (0x02, 0x05) with named constants BT_CODEC_CVSD
and BT_CODEC_MSBC for better code readability. Also remove redundant
zero initialization of num_caps field since the buffer is already
memset to zero.
2026-01-25 17:26:15 +00:00
Mengshi Wu
78f16bc04b bluez5: Remove hw-offload feature flag check and associated quirks
The sco_offload_btcodec() function now returns void and only skips
offload setup when using the default datapath, simplifying the logic
and removing the need for explicit feature flag checks.
2026-01-25 17:26:15 +00:00
Mengshi Wu
2b5d21da5b bluez5: simplify SCO datapath parsing with spa_atou32 2026-01-25 17:26:15 +00:00
Mengshi Wu
2d6a7d2186 bluez5: fix format string in sco_offload_btcodec log message 2026-01-25 17:26:15 +00:00
Mengshi Wu
db7c74a042 bluez5/backend-native: Add HFP/HSP hardware offload datapath configuration
Add support for configuring the SCO hardware offload data path for
HFP/HSP profiles using the Bluetooth SIG-specified procedure. This
enables vendor-specific SCO offload integrations.

Changes:
- Add `bluez5.hw-offload-datapath` configuration property (default: 0)
- Implement `sco_offload_btcodec()` to set BT_CODEC socket option
- Add `SPA_BT_FEATURE_HW_OFFLOAD` quirk feature flag
- Apply offload configuration when creating SCO sockets if quirk enabled
- Document new property in pipewire-props.7.md

The datapath ID is configurable via device parameters and only applied
when the hardware offload feature flag is set in quirks, allowing
platform-specific SCO offload implementations.
2026-01-25 17:26:15 +00:00
Arun Raghavan
04793138b5 alsa-card-profiles: Add config for a couple of JBL gaming headsets
Similar to the existing SteelSeries and Logitech ones, but the order of
the playback endpoints is reversed, and only mono input is supported.
2026-01-22 15:35:05 +00:00
Wim Taymans
f82f4945b9 filter-graph: improve min/max checks for control
Clamp the control values to their min/max.

Remove the default_control array, we can just restore the default with
the port_set_control_value(). Do this when no value has been set on the
port when we set up the graph. The avantage is that we calculate the
default, min and max correctly when they depend on the graph rate.

Fixes #5088
2026-01-21 18:35:36 +01:00
Wim Taymans
7f2cce1021 filter-graph: add a null plugin
It discards all input.
2026-01-21 16:26:16 +01:00
Wim Taymans
a97c4d10af filter-graph: allow 0 input and output ports
There is no reason to fail when there is no input or output port.
We can simply run the graph with what there is. Even if there is no
input or output at all, running one instance of the plugins is
possible.

Add a busy builtin plugin that has no ports and keeps the CPU IDLE or
busy for the give percent.
2026-01-21 16:26:16 +01:00
Wim Taymans
ba3e564e34 filter-graph: notify about default numner of in/out
The filter graph has, after parsing, a default number of input and
output ports. This is based on the description or the first/last element
input and output ports. Pass this information in the properties when
we emit the info.

Don't use the number of configured input/output ports as the default
number of channels in filter-chain because this is only determined after
activating the graph. Instead, use the default input/output channels.

The result is that when you load filter-chain without any channel
layout, it will default to the number of input/outputs of the graph
instead of 0. This allows for the node to be visible in the pulseaudio
API.

Fixes #5084
2026-01-21 16:26:16 +01:00
Wim Taymans
b4b057196d resample: add bool to force inter resampler
Don't rely on the out_rate vs n_phases to decide on when to use the
inter resampler because the out_rate can change when we activate the
adaptive resampler.

Instead use a boolean that we can set at the start.
2026-01-16 11:03:43 +01:00
Wim Taymans
06e4772864 channelmix: add some more channelmix positions
Implement downmix of some top and rear channels as well.
2026-01-15 16:43:43 +01:00
Wim Taymans
9fdbe98330 resample: limit the amount of phases
If we have in and out rates with a very small GCD, we might end up with
a lot of phases. Limit the number of phases to 1024 and switch to
interpolating mode. 1024 phases is enough to accurately interpolate
from.

Together with the MAX_TAPS limit we will never create a filter
size that overflows 32 bits.

Fixes #5073
2026-01-15 12:05:07 +01:00
Wim Taymans
13131706aa spa: use the right AVX2 flags
Our AVX optimizations are really AVX2 so rename the files and functions
and use the right HAVE_AVX2 and cpu flags to compile and select the
right functions.

Fixes #5072
2026-01-13 12:03:09 +01:00
Pauli Virtanen
c1f7963c2a bluez5: fix crash due to debug_mono
Enabling bluez5.debug-iso-mono was in non-ISO branch and crashes. Fix
that.
2026-01-12 19:57:56 +02:00
Pauli Virtanen
f21c44751e bluez5: iso-io: resync if controller packet completion is out of sync
Add heuristic to resync streams if controller packet completion times
for different streams differ by too much.  This likely indicates
controller has lost sync between the streams, and we have to reset
playback.

There's no way to do this properly. The ISO-over-HCI transport is badly
specified in Bluetooth Core Specification.  Many controllers have broken
implementation of the current send timestamp read command, so packets
have no identifiers which ISO interval they belong to.

Controllers try to reconstruct the right interval based on
manufacturer-specific heuristics probably based on packet arrival times.
Kernel + USB introduce timing jitter, and playback sometimes desyncs and
packet from some streams are persistently sent some multiple of the SDU
interval off from the intended timing.

Try to determine this from packet completion latencies.  This is
somewhat manufacturer specific, tested on Intel & Realtek, hopefully
works on others too.
2026-01-11 17:55:26 +02:00
Pauli Virtanen
0003d7a2d0 bluez5: iso-io: add debug option for forcing same data in all streams
When debugging desync issues, it's useful to force same data be sent on
all ISO streams. Add option for that.
2026-01-11 17:55:26 +02:00
Pauli Virtanen
d0309b4e1e bluez5: deal with missing TX timestamps
There are known controller firmware bugs that cause packet completion
reports, mainly for ISO packets, to be missing.

To avoid getting stuck e.g. in ISO queue flushing, we should consider a
packet completed if sufficient time has passed even if controller (and
kernel) don't report it completed. Take 1 s as conservative timeout, the
expected values are some ms.

These firmware bugs also cause kernel to stop sending packets if too
many are left uncompleted, but we cannot detect that.
2026-01-11 17:55:26 +02:00
Pauli Virtanen
c96e58af01 bluez5: handle BAP device set volume change notifications
Update volume state on device set volume notifications.

When one device sends volume notification, CAP specifies volume on other
devices shall be synchronized too.
2026-01-06 16:14:22 +00:00
Pauli Virtanen
260e8261d5 bluez5: add bluez5.autoswitch-routes option to indicate loopback nodes
When session manager emits loopback nodes for profile autoswitch, we
need to indicate them in the Routes.

Otherwise, the port information in Pulseaudio API doesn't account for
them, and some apps (eg GNOME) misbehave, as the loopback node sometimes
doesn't have valid ports.
2026-01-05 20:43:13 +02:00
Pauli Virtanen
e91a79dab7 spa: alsa: actually set the channel map when use-chmap=true
When using channel maps, the active map should be set using
snd_pcm_set_chmap(). This has to be called when stream is in prepared
state.

Track which of the maps the selected format has set, and set it in
do_prepare().
2026-01-05 15:37:05 +00:00
Pauli Virtanen
f754741d58 bluez5: handle BAP volume change events
Handle volume changes initiated by remote also for the BAP profiles.
2026-01-05 15:35:17 +00:00
Pauli Virtanen
8a7c71694d bluez5: handle BAP initial HW volumes
Setup initial HW volumes for BAP profiles similarly as done for A2DP.
As Client, retain the remote volumes as initial values, and as Server
use our own default volumes.

Also as A2DP Source, use the remote HW volume as initial value, if
available.

In the Client / A2DP Source modes session manager usually restores its
own volumes overriding what we set here.
2026-01-05 15:35:17 +00:00
Pauli Virtanen
11389d101a bluez5: iso-io: more accurate resync after overrun
Take active rate correction properly into account when dropping data on
overrun resync.

Drop data only for the currently processed stream, after data has been
consumed from it. Make sure the rate correction factor is updated after
this for the next cycle of the stream.

Also fix buffer fill level calculation: the fill level interpolation
should use node rate corr, not clock rate diff, since the calculations
are done in system clock domain. Fix same issue in fractional delay
calculation, and take no resampler prefill into account.

Later, we maybe need some more resampler APIs to avoid such details
leaking in.

Previously, stream could have its old rate correction locked in, and its
fill level would then end up off the target on the next cycle.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
b535534611 bluez5: media-source: do buffering on connection start also with PLC
Also when we are capable of PLC, it's better to buffer audio at start,
to get a buffer level close to the target initially.

Delay ISO overrun handling one cycle after buffering is complete, so
that any resamplers are filled at that point.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
1d7e89e069 bluez5: media-source: improve handling of underrun with PLC
When PLC data was produced due to underrun and decode buffer has reached
target level, drop received audio if we already did PLC for that packet.
It's better to lose some packets than having to resync latency.

When about to underrun when PLC is active, update rate matching before
filling up buffer, so that rate slows down and we do not get stuck in a
continuous underrun where PLC fills data and we drop received packets.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
de34ce606f bluez5: media-source: fix off-by-one cycle in rate matching
The rate matching filter assumes buffer level for cycle j+1 is

    buffer(j+1) = buffer(j) + recv(j) - corr(j+1) * duration

but what we are actually doing is instead

    buffer(j+1) = buffer(j) + recv(j) - corr(j-1) * duration

because the correction factor that is computed is not used for the next
cycle, but the one following that. Although the filter is still stable
in theory the extra lag causes oscillations to be damped less.

Fix by using the computed correction factor for the next cycle, as
there's no reason why we'd like to have more lag in rate matching.

This then changes c(j-1) -> c(j) in the assumptions, which turns out to
fix the situation. Fix the filter derivation to match.  The filter
coefficients stay as they were, and they are actually exactly correct
also for short averaging times.

In practice, it is observed that ISO RX with quantum 4096 converges to
stable rate, whereas previously the matching retained small
oscillations.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
c4812af436 bluez5: decode-buffer: fix buffer level after recovery
The buffer level number includes the current quantum, so it should not
be subtracted. We do this after recovery from glitch, and this throws
rate matching off.

The level after recovery should also include the resampler delay.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
11faea9dbc bluez5: media-source: don't break audio if BAP presentation delay too small
As BAP server, when we can't satisfy BAP presentation delay, just accept
a bigger latency and emit a warning, instead of having broken audio.
Also make sure it works if quantum is forced to a larger value than our
wanted node.latency.

Take other latencies into account when selecting the wanted node.latency
for BAP Server.

Fix up port.params usage vs. user flag, which is not used here.

Reset decode buffer rate matching if we need to PLC due to underrun so
it doesn't get stuck at playback at increased rate if target is too
small.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
ac3ac3382b bluez5: iso-io: delay streaming start until all acquires are complete
For better start synchronization, we should wait until all ISO nodes
that are going to be started finish creating ISO io.

Add a separate ready flag for startup that is set when all Acquire
requests are complete.
2026-01-05 15:34:06 +00:00
Pauli Virtanen
8b36e2d9b7 bluez5: support specifying preferred delays as BAP Server
Add options to control advertised delays supported.

Smaller delay needs smaller node.latency be used, so use 40ms as a
reasonable minimum preferred delay.
2026-01-05 15:34:06 +00:00
Wim Taymans
ae9361bb34 support: return NULL instead of FALSE 2026-01-03 22:54:25 +01:00
Wim Taymans
4a2710c779 dbus: handle errors better
Make sure we don't crash when running out of fds and the loop functions
start to return NULL sources.
2026-01-03 11:24:08 +01:00
Frédéric Danis
e15e50c5ee spa: bluez: backend-native: Prevent HSP/HFP connection in both directions
The HSP and HFP profiles expect that a device function only as an audio
gateway or as an headset, which is the normal behavior for a headset,
a hands-free car unit or a phone.

In case of a desktop, it can perform both functionalities, but there's
no interest to get them at the same time as the bidirectional audio
is already supported.
2025-12-19 07:12:46 +00:00
Frédéric Danis
f468529084 spa: bluez: backend-native: Fix audio connection policy for HSP/HFP 2025-12-19 07:12:46 +00:00
Arun Raghavan
e2262617aa spa: alsa: Fix off-by-one check in ELD channel position parsing 2025-12-17 11:08:44 -08:00
Jonas Holmberg
12b2e5d67c audiotestsrc: Operate as follower too
Don't start the timer but fill buffers when following another driver.
2025-12-16 13:15:00 +01:00
Arun Raghavan
ee42b18226 spa: alsa: Guard against mismatched LPCM channel count in ELD parsing
With wonky EDID states, we want to make sure we don't overflow the
available positions.
2025-12-15 12:47:49 -08:00
Frédéric Danis
d89d1668dc spa: bluez: backend-native: Add support for AT+BLDN for PTS tests
This allows to fake Last Dial Number call by calling the first memory.

This allows to pass PTS tests HFP/AG/OCL/BV-01-C and HFP/AG/OCL/BV-02-C.
2025-12-15 08:56:03 +00:00
Frédéric Danis
9a48bbaa36 spa: bluez: modemmanager: Add support for memory dialing for PTS tests
This add a new property to to allow to fake memory dialing for PTS tests
HFP/AG/OCM/BV-01-C and HFP/AG/OCM/BV-02-C.
2025-12-15 08:56:03 +00:00
Mason Remaley
c7ebc66e64 Adds explanation to reduce chance of regressing the fix 2025-12-15 08:20:24 +00:00
Mason Remaley
a6f8e209ac These two functions were marked as static, but referened by the SSE41 implementation in a separate file
I'm not 100% sure if this was breaking SSE41 builds on the official build system (I'm building Pipewire
with a different process), but I suspect it was, because you can't combine these into a single translation
unit to sidestep it without including multiple copies of resample-native-impl.h which isn't desirable.
2025-12-15 08:20:24 +00:00
Wim Taymans
8153efc6ed audioconvert: refactor some code
We sync the filter graph in two places, make a function so that both
places do the same thing.

Make node_reset clear the setup flag so that we don't have to do that
twice.
2025-12-09 21:01:11 +01:00