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.
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.
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.
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.
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.
Update volume state on device set volume notifications.
When one device sends volume notification, CAP specifies volume on other
devices shall be synchronized too.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Add options to control advertised delays supported.
Smaller delay needs smaller node.latency be used, so use 40ms as a
reasonable minimum preferred delay.
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.
The current implementation only send the +CIEV:<call>,<active> event
if there's an active modem in ModemManager. This may lead to headset
disconnection as in (1) if the profile is by another application than
telephony one, e.g. a conference application/website.
This commit improves dummy call status update by adding a new
"bluez5.disable-dummy-call" props param in bluez5 device, allowing
external application like WirePlumber to set it dynamically.
(1) https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1744
Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/merge_requests/2606
Parse TMAP / GMAP features from MediaEndpoint:SupportedFeatures and pass
them onto the codec in SelectProperties, so it can determine which
mandatory features the device supports.
Add configuration option for specifying which TMAP / GMAP feature bits
we advertise to remote side.
Although some of these could be determined automatically, for production
systems it's better to have explicit option to specify which ones should
be advertised as this may depend on HW capabilities.
The "+BIND: <a>,<state>" reply to AT+BIND? should be sent for every
supported indicator.
"AT+BIEV= <assigned number>,<value>" should only be provided for
enabled indicators. The AG shall respond with an ERROR response code
if it receives updates for disabled or unknown HF indicators or values
that are out of bounds.
This allows to pass PTs tests:
- HFP/AG/HFI/BV-02-C
AG receives an updated HF Indicator value
- HFP/AG/HFI/BI-03-C
AG receives invalid updated HF Indicator values
When releasing multiple transports, call Release() simultaneously
instead of serializing the calls.
This operations still needs to be blocking currently, as all releases
have to finish before we do other state-modifying ops.
This works around broken firmware on Creative Zen Hybrid Pro with BAP,
whose Disable command misbehaves when shutting down sink + source CIS
otherwise. It's also anyway better to shut down everything at once.
Some devices refuse to enable microphone if Streaming Context metadata
is just Unspecified.
Set some reasonable values for the stream context we create along TMAP,
and try follow CAP rules for selecting the PAC.
With BAP codec configuration selection goes via multiple functions,
which will need to maintain some private state.
Adjust media_codec to allow for that.
Use it for get_qos().
Based on HFP specs, the audio connection is independent of the active
call status, which should be managed by the ModemManager part of the
plugin.
But when using HFP AG without modem attached, e.g. during zoom meeting,
the connection will be closed after a while unless call status has been
forced to active,
cf. https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1744.
Currently and for HFP AG PTS tests requesting to get an audio connection
in 3 seconds after a call activates, this prevent to start audio
connection before starting a call.
This commit prevents to force the call status during audio (dis)connection
if a modem is available.
Get the ModemManager interfaces when the ModemManager starts after native
HFP has started.
Also add log topic to be able to select log level for modemmanager plugin
part.
Flush errqueue for iso-io also from the media-source handler, to avoid
dropping packet tx reports.
This applies to bidirectional streams. The sink/source handlers poll on
different fd, one being dup'd, and epoll does not trigger them in any
specific interleaved order.
`libusb_free_device_list()` should be passed `true` as its second
argument to unreference every single device in the list.
Fixes: 5e0b63b1495591 ("bluez5: backend-native: use quirks + usb adapter caps for checking msbc")
`dbus_connection_register_object_path()` does not take ownership of the
path passed to it, so currently the callers `telephony_{ag,call}_register()`
leak a copy of the path string. Fix that by not making an unnecessary copy.
Fixes: b28399ac578357 ("bluez5: add telephony D-Bus service implementation")
SPA_POD_CHOICE_ENUM_Int must always take at least 2 values as first one
is default. (Just 1 value no longer works on current master, and it's
anyway incorrect.)
Replace with just SPA_POD_Int, as there's just one choice.
In the unknown form-factor case (which I saw on a set of headphones
here, Creative Zen Hybrid Pro), let's avoid an apocryphal acronym in
favour of a term that might be more familiar to the user.