When bluetooth transport has both both sink and source, pulseaudio would
synchronize writing out frames with reading frames from peer to make fair
schedule of reads and writes. Pulseaudio allows two blocks of data to be sent to
peer before synchronizing writes with reads just in case that peer implements
similar write schedule.
It could happen that first blocks are still missed by peer, which would cause
pulseaudio writes to stall waiting for first frames from peer.
Fix this by allowing more data frames out until data from peer is actually
received.
Closes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1424
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/777>
Check whether a Bluetooth profile is supported both by the remote device
and the local host before creating a card profile for it.
This is useful when some of the media profiles have not been registered
with bluetoothd because ex., oFono is not running and the headset
backend is not available.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/638>
With USB Alternate Setting 3 size of HCI payload is 72 bytes which is already
larger than mSBC frame size. Largest known size of HCI payload is with USB
Alternate Setting 5 (144 bytes), make it the default SCO socket MTU.
Reserve additional space in bluetooth encoder buffer to cover this case.
Since mSBC encoder and decoder will now work with larger packet sizes, drop
assertions about MTU larger than mSBC frame size.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/617>
Whenever a device disconnects the device is not removed from BlueZ, only
the profiles that had an active connection are disconnected. Since we
were providing this battery level based on AT commands received through
HSP/HFP these services should be responsible for deregistering it again.
Deregister the interface to signal BlueZ (And UPower in return) that the
battery level won't be accurate/updated anymore.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/482>
The Volume property on org.bluez.MediaTransport1 is required to utilize
Absolute Volume, but it will only become availabe if the peer device
supports the feature. This happens asynchronously somewhere after the
transport itself has been acquired, after which the callbacks are
attached and software volume is reset.
To prevent race conditions availability of the property is also checked
on startup through a "Get" call.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/239>
Write the current volume to the `Volume` DBus property to keep the
volume on the remote in sync. Without this the remote device shows the
wrong volume, and any attempts to change it will cause an unexpected
jump when the local volume has also been adjusted.
Thanks to prior investments to improve volume synchronization, setting
up callbacks and sending initial volume to the peer for HFP/HSP
implementing this feature is as easy as unconditionally assigning a
valid function to `set_source_volume`. `source_setup_volume_callback`
is already responsible for attaching a `SOURCE_VOLUME_CHANGED` hook and
sending initial (restored) volume to the peer (signifying support for
Absolute Volume - if not derived from the presence of FEATURE_CATEGORY_2
on the profile yet).
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/239>
Like the previous commit this handles `Volume` property changes but
applies them to an A2DP sink instead of source stream. As mentioned in
the AVRCP spec v1.6.2 §5.8 the rendering device (A2DP sink) is
responsible for performing volume attenuation meaning PulseAudio should
pass through audio as-is without performing any attenuation in SW.
Setting a valid pointer to `set_sink_volume` and returning `true` from
`should_attenuate_volume` attaches a hardware callback to `pa_sink` such
that no volume attenuation is performed anymore.
In addition to receiving volume change notifications it is also possible
to control remote volume by writing a new value to the DBus property.
This is especially useful when playing back to in-ear audio devices
which usually lack physical buttons to adjust the final volume on the
sink.
While software volume (used before this patch) is generally fine it is
annoying to crank it up all the way to 100% when a previous connection
to a different device left saved volume on the peer at a low volume.
Providing this bidirectional synchronization is most natural to users
who wish to use physical controls on their headphones, are used to this
from their smartphone, or aforementioned volume mismatches where both PA
as source and the peer as sink/rendering device are performing
attenutation.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/239>
HFP Audio Connection SCO configuration is negotiated symmetrically in both
directions, and USB HCI SCO packet framing is also symmetric in both directions.
This means that packet size will be the same for reads and writes over HFP SCO
socket.
HFP profile specification states that valid speech data shall exist on the
Synchronous Connection in both directions after the Audio Connection is
established.
This guarantees that an incoming packet will arrive shortly after SCO connection
is established. Use it's size to fix write MTU in case kernel value is wrong.
Discussion here https://lore.kernel.org/patchwork/patch/1303411/
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/507>
Setting these callbacks adds the HW_{VOLUME,MUTE}_CTRL flag even when
PulseAudio is solely responsible for performing attenuation whilst only
keeping the peer posted on changes. For this case the hardware callback
is not registered at all but instead a hook is attached to catch
PA_CORE_HOOK_{SINK,SOURCE}_VOLUME_CHANGED. Only when the peer performs
attenuation (the peer is in HeadSet/HandsFree role) are the callbacks
used, without touching PA software volume at all. A future change could
potentially use software volume to compensate for the extremely coarse
16 steps of volume control in HSP and HFP, and to allow volume over
100%.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/519>
Originally written for A2DP this rework of that patch enables late-bound
hardware volume control on HFP and HSP. As per the specification the
headphones (where gain control for both speaker and microphone could
happen in hardware on the peer) are supposed to send initial values for
these before the SCO connection is created; these `AT+VG[MS]` commands
are also used to determine support for it. PA uses this information in
`add_{sink,source}` to attach hardware volume callbacks, _if_ it is
supported. Otherwise PA performs the attenuation in software.
Unfortunately headphones like the WH-1000XM3's connect to A2DP
initially and only send `AT+VGS` (microphone hardware gain is not
supported) _during_ SCO connection when the user switches to the HFP
profile afterwards; the callbacks set up dynamically in
`rfcomm_io_callback` are written after the sink and source have been
created (`add_{sink,source}`), leaving them without hardware volume
callbacks and with software volume when adjusted on the PA side. (The
headphones can still send volume updates resulting in abrupt changes if
software and peer volume differ. Furthermore the same attenuation is
applied twice - once in PA software, once on the peer).
To solve this problem we simply check whether the callbacks have been
attached whenever the peer sends a volume change, and if not attach the
callbacks to the sink/source and reset software volume.
Fixes: d510ddc7f ("bluetooth: Perform software attenuation until HF/HS reports gain control")
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/528>
HF/HS hardware attenuation is optional on HFP: the peer indicates
support with the AT+BRSF command, when bit 4 is set. That does not
explicitly mandate speaker or microphone gain control; either is
dynamically detected as soon as `AT+VG[MS]=` is received. Otherwise
software attenuation is performed.
It is also optional on HSP but nothing is mentioned about feature
detection, assume it is the same as HFP: perform software attenuation
until the HF/HS peer sends an `AT+VG[MS]=` command.
When PA is a HS/HF (and the peer the AG) we attenuate both channels in
software and unconditionally keep the peer up to date with
`AT+VGM/AT+VGS` commands.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/521>
Generalize the distinction between local and peer-attenuated volumes
into a function, paving the way for future changes where this needs to
be checked in more places and when A2DP Absolute Volume support is
added.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/521>
Sink and source naming is more generic when dealing with audio that is
directional in the sense that it either goes to or comes from the other
device, but not necessarily a microphone or speaker. A concrete example
is the swapped meaning when the current device is in the HeadSet
profile. The incoming audio can come from any source, not necessarily a
microphone. Likewise, audio captured by the microphone of the headset is
not necessarily played back by a speaker on the AG, it is merely acting
as a sink for the data: further handling is irrelevant to the naming.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/521>
For the upcoming A2DP AVRCP Absolute Volume feature the code in BlueZ5
has to be generic to be reusable. Move this conversion so that it
becomes possible to implement A2DP volume - which uses different values
- on top without duplicating existing callback functionality.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/521>
When HFP HF support is enabled in native backend, peer HFP HF profile connection
is preferred over same peer HSP HS profile connection if peer supports both
profiles.
Enforce the preference by rejecting HSP HS profile connections from such peer.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/491>
Native backend implements HFP AG but not HFP HF yet, therefore headset=auto
functionality is still needed if HFP HF is required.
To make headset=auto work again, drop both HFP AG and HSP AG roles while
performing handover from native backend when oFono is detected running.
While at it, restore profile description to Headset Head Unit (HSP/HFP)
to note that HFP may be still provided via oFono backend.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/491>
When all headsets supported both HSP and HFP, life was good and we
only needed to implement HSP in the native backend. Unfortunately
some headsets have started supporting HFP only. Unfortuantely, we
can't simply switch to HFP only because that might break older HSP
only headsets meaning we need to support both HSP and HFP separately.
This patch separates them from a joint profile to being two separate
ones. The older one retains the headset_head_unit name, meaning any
saved parameters will still select this (keeping us backward
compatible). It also introduces a new headset_handsfree.
For headsets that support both HSP and HFP, the two profiles will
become separately visible and selectable. This will only matter once
we start adding features to HFP that HSP can't support (like wideband
audio).
Signed-off-by: <James.Bottomley@HansenPartnership.com>
---
v6:
- merge profile switching fixes patch from Rodrigo Araujo
v5:
- rename option to enable_native_hfp_hf
- don't call profile_done for HFP_HF unless it was initialised
v3:
- Update for PA 11.0
v2:
- fold in review feedback
- add global disable option for not registering HFP
v3:
- change parameter to enable_profile_hfp
- update device_supports_profile to be aware of hfp/hsp exclusivity
- change parameter to enable_profile_hfp_hf
bluetooth: separate HSP and HFP (to me merged with this patch)
Hi.
First, just to say that your patches are going great. Finally I can use
the microphone of my HFP only headset (a version of a Bluedio T2+).
So far, I've only encontered one problem: the auto_switch option of
module_bluetooth_policy stops working. Dug through the code and I think
you missed a few spots were you have to hangle the new headset_handsfree
profile in module_bluetooth_policy.c
Applying the following after applying your v5 patches fixed the issue
for me, now when I start making a VOIP call the profile switches to
headset_handsfree and the mic works automatically, and when the call
finishes it reverts back to a2dp.
Thanks and best regards.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/491>
The PA_BLUETOOTH_PROFILE names should mirror the PA_BLUETOOTH_UUID
names using profile_function instead of randomly made up names. Fix
this with the transformation:
PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT -> PA_BLUETOOTH_PROFILE_HSP_HS
PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY -> PA_BLUETOOTH_PROFILE_HFP_AG
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
v4: update for PA 11.0
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/491>
Bluetooth thread may ask encoder to reduce bitrate if writing is not keeping up
with inputs or writing to bluetooth socket takes too much time.
Assuming conditions leading to reduced bitrate are intermittent, allow periodic
attempts to increase encoder bitrate, by default at most twice per second.
Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/481>