Commit graph

146 commits

Author SHA1 Message Date
Wim Taymans
13b8c23767 Don't use SPA_AUDIO_MAX_CHANNELS directly
Make a MAX_CHANNELS define and use that one in code. This makes it
easier to change the constant later.
2025-10-21 09:43:06 +02:00
Pauli Virtanen
7fd05e7eaa bluez5: drop old SCO fragment data when sink starts
Any pending SCO fragment data should be cleared when sink starts, so
that we don't send out any old data.
2025-06-21 16:13:57 +03:00
Pauli Virtanen
5b4e9dc33e bluez5: replace sco-sink with media-sink
Change media-sink to use sco-io for HFP codecs.

Move SCO fragmentation to sco-io side.

Replace sco-sink with media-sink.

sco-sink is mostly copypaste from media-sink, and only differed in the
fragmentation detail, which can as well be handled on sco-io side.
2025-06-21 16:08:30 +03:00
Pauli Virtanen
26b09b0ee3 bluez5: temporarily remove BAP nodes when another device is switching
Unicast BAP codec switch requires CIG reconfiguration, which cannot be
done if there is an acquired transport.

When doing BAP codec switch, disable nodes of other devices sharing the
same CIG.

To avoid problems with node start/stop, just remove and re-add them.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
8795298f69 bluez5: implement BAP ucast reconfiguration
Use SelectProperties() DBus API to reconfigure BAP unicast setup.

Add support to spa_bt_ensure_codec() to select whether to configure as
sink/source/duplex.
2025-06-13 22:16:03 +00:00
Pauli Virtanen
6e0970c14b bluez5: simplify codec switch code
Simplify codec switching code: determine what switch to perform
immediately in spa_bt_device_ensure_media_codec().

The previous code doing "fallback" switching to various codecs is not
useful, as A2DP generally disconnects on the first failure and all
remote endpoints disappear.

Add iteration over multiple endpoints, for reconfiguring both source and
sink directions at the same time.  This is in preparation of supporting
BAP reconfiguration (for A2DP there's usually only one direction
connected at a time).
2025-06-13 22:16:03 +00:00
Pauli Virtanen
83f6d719b1 bluez5: remove HFP codec id from transports
Make HFP codec id backend/codec internal detail. Remove
spa_bt_transport::codec field which is now unused.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
3f9fb8d664 bluez5: bluez5-device: reduce special casing of HFP codec related things
Get most information items out from media_codec properties, avoid
referring to HFP codec ids.
2025-06-13 17:51:16 +00:00
Pauli Virtanen
62bec49c27 bluez5: add spa_bt_get_hfp_codec() / spa_bt_get_media_codecs()
These are for HFP backends to get media codecs.
2025-06-13 17:51:16 +00:00
Sam James
2cec77e7df *: unify config.h handling
config.h needs to be consistently included before any standard headers
if we ever want to set feature test macros (like _GNU_SOURCE or whatever)
inside. It can lead to hard-to-debug issues without that.

It can also be problematic just for our own HAVE_* that it may define
if it's not consistently made available before our own headers. Just
always include it first, before everything.

We already did this in many files, just not consistently.
2025-05-30 10:24:13 +00:00
Sam James
b943c31fd8
*: don't include standard C headers inside of extern "C"
Including C headers inside of `extern "C"` breaks use from C++. Hoist
the includes of standard C headers above the block so we don't try
to mangle the stdlib.

I initially tried to scope this with a targeted change but it's too
hard to do correctly that way. This way, we avoid whack-a-mole.

Firefox is working around this in their e21461b7b8b39cc31ba53c47d4f6f310c673ff2f
commit.

Bug: https://bugzilla.mozilla.org/1953080
2025-05-30 09:48:28 +01:00
Pauli Virtanen
897748759e bluez5: update timestamping code to match kernel & bluez
Update code to match the final version landed in mainline Linux 6.15
2025-05-17 10:51:37 +00:00
Pauli Virtanen
270eda63a9 bluez5: different icon for A2DP & HFP output routes
Set different icons for A2DP & HFP output routes, so that they look
different (in Gnome).

Don't call the non-HFP output route as "headset" or "handsfree" in this
case, to be less ambiguous about microphone availability.

Also set device.icon-name for the device too.
2025-05-05 07:45:24 +00:00
Sanchayan Maity
8120493edb bluez5-dbus: Track ASHA HiSyncId & Side information in transport
ASHA devices with the same HiSyncId are a pair and this
will be used later on to set them up together with a
combine sink like device set for BAP. Side information
is required for channel information when setting up the
combine sink.
2025-05-05 07:43:34 +00:00
Pauli Virtanen
0d61cc1b1d bluez5: use kernel-provided RX timestamps
Use kernel-provided packet reception timestamps to get less jitter in
packet timings. Mostly matters for ISO/SCO which have regular schedule.

A2DP (L2CAP) doesn't currently do RX timestamps in kernel, but we can as
well use the same mechanism for it.
2025-04-21 10:22:50 +00:00
Wim Taymans
722776cf65 Remove some hardcoded channel number values
Mostly related to the number of channels.
2025-04-04 15:46:03 +02:00
Pauli Virtanen
34ac0d8256 bluez5: support BAP hardware volume
Support BAP HW volume now that it's implemented in BlueZ, with the
volume range 0-255 per spec.
2025-01-25 15:37:52 +00:00
Sanchayan Maity
13c026417b bluez5: Implement support for ASHA
ASHA is a Bluetooth specification for hearing aids.

For a high level overview of the ASHA Specification for BlueZ.
https://asymptotic.notion.site/ASHA-Spec-for-Bluez-61a46027fd46458d8235e14d6bedb2ce

The original specification in Android.
https://source.android.com/docs/core/connect/bluetooth/asha

Corresponding support in BlueZ.
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/profiles/audio/asha.c

This only implements handling of one side of a ASHA device
pair. Stereo support/handling of both "left" & "right" side
will follow later requiring work on clock synchronization
between the pair.
2025-01-09 14:51:50 +00:00
Pauli Virtanen
2bf48487cb bluez5: handle A2DP inverted ClearConfiguration/SetConfiguration order
When in A2DP sink role and remote end switches codec, BlueZ nowadays
appears sometimes emit first SetConfiguration (creating new transport),
and then ClearConfiguration (removing old transport).

Handle this case: emit profiles_changed event always when transports
come/go.

Redefine profiles_changed() to take bitmask of profiles whose connection
status changed, so we don't need to emit two remove+add events.
2024-12-06 16:36:14 +02:00
Pauli Virtanen
2847d90b4b bluez5: report latency to rendering when in A2DP sink role
Now that BlueZ supports delay reporting in A2DP sink role, implement
that.

Report value that gives the total latency between packet reception and
audio rendering.

Also make Latency parameter in media-source to be not just a dummy
value.
2024-12-01 20:14:36 +02:00
Pauli Virtanen
8504e58120 bluez5: reduce quirks logspam
There's no need to log quirks every time they are used, it's enough to
log them once when a device connects.
2024-11-04 21:41:24 +02:00
Pauli Virtanen
c9acdd2f1f bluez5: backend-native: update HFP SDP records
Advertise SWB since we implement it.  Update HFP version to 1.9
accordingly.
2024-10-31 08:18:45 +00:00
Vlad Pruteanu
786c2445e9 bluez5: Parse 'broadcasting' state
A new 'broadcasting' state is to be added in BlueZ. It is
functionally similar to 'pending', but for the Broadcast scenario.

Until now, on Broadcast sink side, the transports associated with a
scanned source would automatically be switched to pending. PipeWire
then acquired any transport that was pending.

This is to be changed, transports will now remain in 'idle' state
until the user calls transport.select on them from bluetoothctl.
This changes the state to 'broadcasting'. PipeWire will then acquire
these selected transports.

This way, the user can select to which sink he wishes to sync.
2024-08-01 10:36:58 +00:00
Pauli Virtanen
b94d6e53a1 bluez5: use initial SCO RX wait workaround only for USB controllers
Kernel-provided MTU does not work for USB controllers and the correct
packet size to send can be known currently only from RX. So we are
waiting for RX to get it.

The known problem is USB-specific, we shouldn't need the workaround for
other transport types.

Don't wait for POLLIN for non-USB controllers on connect, but ready
things on POLLOUT as usual.

For non-USB controllers, pick some sensible packet sizes to use
initially, before we switch to same size as for RX.
2024-05-18 13:53:45 +03:00
Pauli Virtanen
5ae0dfb239 bluez5: bap: determine SDU interval from codec frame duration
BlueZ API as BAP Server gives us the ISO interval, instead of the SDU
interval, in the MediaTransport.QoS.Interval property.  They are not
necessarily the same. What we need is the SDU interval.

The SDU interval is the interval between packets the encoder outputs, so
it is determined by the codec configuration, and for LC3 is equal to the
frame duration.

Add codec method get_interval() that returns the correct interval, and
use it in iso-io.
2024-04-01 19:13:01 +03:00
Pauli Virtanen
65f594c6a1 bluez5: further HFP cleanups
Fix naming issues.
2024-01-25 08:43:45 +00:00
Pauli Virtanen
45ff965f33 bluez5: support LC3-SWB in SCO sink/source
Add support for LC3-SWB encoding/decoding.

Tested on Pixel Buds Pro.
2024-01-25 08:43:45 +00:00
Pauli Virtanen
fe412784a4 bluez5: support LC3-SWB in HFP RFCOMM & add codec id for it
HFP 1.9 adds LC3 as a possible codec in addition to CVSD & mSBC.
E.g. Pixel Buds Pro latest firmware supports it.

Add the RFCOMM side and codec selection for it.
2024-01-25 08:43:45 +00:00
Pauli Virtanen
7f2dd3531c bluez5: use only one input route
Don't have separate input route for A2DP and HFP, as it is generally not
necessary.

When in A2DP mode when there's also HFP possible, emit the input route
in SPA_PARAM_Route, even though there is no corresponding input node
emitted.

The host may then emit a loopback microphone node, and switch profiles
according to its status. Having the input route available at all times
allows to retain changes to volume settings made when there is no real
input node.
2023-12-09 14:05:50 +02:00
Frédéric Danis
442a208382 Bluez5: backend-native: HSP AG release SCO link on AT+CKPD=200
Bluetooth PTS test HSP/AG/ACR/BV-01-I request AG to release the SCO link
upon reception of AT+CKPD=200 reception
2023-11-29 15:43:22 +00:00
Pauli Virtanen
186b730c9c bluez5: fix device supported codec checks
Make supported codec checks to use profiles, not "is-a-sink" flag, to
determine which codecs can be used.

Fixes bluez5-device checking only source profiles, even when the local
device is only a sink.
2023-09-13 15:51:50 +00:00
Silviu Florian Barbulescu
8660066af6 Add suport for braodcast sink 2023-08-24 16:31:03 +00:00
Silviu Florian Barbulescu
b07bb4e106 Check if the adapter supports bap broadcast before registering the broadcast endpoint. 2023-08-24 16:31:03 +00:00
Silviu Florian Barbulescu
ef3fac401d bluez5: Add LE Audio BAP broadcast source support
Once Pipewire is started it will try to register a BAP broadcast source media endpoint on UUID 00001852-0000-1000-8000-00805f9b34fb if the media codec that supports BAP and the adapter indicates LE Audio is supported.
When the endpoint is detected (over DBus) by Pipewire and it has a broadcast sink UUID, a new device will be created with the address 00:00:00:00:00:00. This device will be our simulated remote device. This is done because a broadcast source emitting device does not need any connection to start transmitting the audio. This device is set as connected.
When the SetConfiguration DBus method is called and the spa_bt_transport structure with the profile BAP broadcast source is created we switch the device from the one read from DBus to the one created by us. This is done because in BlueZ, when the transport is created, at the Device property, BlueZ sets the adapter as the device that the transport is connected to. Here the device will have the newly created SPA_BT_PROFILE_BAP_BROADCAST_SINK profile connected.
Added code that allows to create a node in the graph for a device connected to the SPA_BT_PROFILE_BAP_BROADCAST_SINK profile.
2023-08-24 16:31:03 +00:00
Pauli Virtanen
04951ac15f bluez5: make set transport volume calls async
The transport set volume call may take a long time or never complete, so
make them async to not block main loop.

Also reduce log level to info for the failed volume setting, as this is
something the user can do nothing about.
2023-04-30 18:44:33 +03:00
Pauli Virtanen
420f7cb48e bluez5: select BAP audio locations in SelectProperties
Do BAP audio location selection properly in SelectProperties, now that
BlueZ provides the supported locations there. Remove a previous
workaround.

The audio location in SelectProperties determines the audio channel
allocation, which determines the channel positions.
2023-04-25 21:44:38 +03:00
Pauli Virtanen
d642569394 bluez5: parse device set information via dbus
Parse device set information from DBus, and link devices to each other
according to it.  Add signal for notifying about device set changes.
2023-04-10 07:00:44 +00:00
Pauli Virtanen
eca13ec230 bluez5: iso-io: get BAP interval from dbus, not getsockopt
For ISO server sockets, the QOS struct from getsockopt contains values
with different meaning from ISO client socket. Get the values via DBus
instead, which is right in both cases.
2023-04-10 07:00:44 +00:00
Pauli Virtanen
6e94487057 bluez5: set BAP channel location from transport if unset
If BAP codec configuration is mono channel with unspecified location,
set the channel position from transport location.

This in principle should be set in SelectProperties, but currently BlueZ
doesn't tell us that yet there, so we hack it up later on.
2023-04-10 07:00:44 +00:00
Pauli Virtanen
cec050ac25 bluez5: add spa_bt_iso_io that does the low-level part for ISO
Add factored out helper for ISO socket I/O.

ISO sockets need synchronization of writes and audio position for
different stream fds in the same isochronous group, and it's easier to
separate out the part that coordinates it.
2023-04-03 16:35:22 +00:00
Pauli Virtanen
13a9964a71 bluez5: don't try to acquire if we are getting errors
If transport goes into error state too often, fail instead of trying to
acquire it again.

This avoids getting into a tight acquire->fail->reacquire loop.
2023-03-18 15:39:56 +02:00
Pauli Virtanen
dfd30f37dc bluez5: parse BAP transport CIG/CIS properties 2023-03-17 16:56:31 +00:00
Pauli Virtanen
63118b130e bluez5: make A2DP/BAP transport acquire/release async
Change A2DP/BAP transport acquire and release to be async.

Since BlueZ acquiring ISO sockets blocks until all sockets in same CIG
are acquired, BAP transports must be acquired asynchronously.
2023-03-17 16:56:31 +00:00
Pauli Virtanen
1d5c693d33 bluez5: change sink/source run state follow transport state
Allow asynchronous changes in transport state in the sinks/sources.

Also allow transport acquire to be actually synchronous, in this case it
must set transport state during acquire call.

Separate driver start/stop from transport start/stop.
2023-03-17 16:56:31 +00:00
Pauli Virtanen
b9d7ecb5b2 bluez5: handle BAP presentation delay and transport latency
For BAP server audio sink, set buffering target so that we try to match
the target presentation delay.  Also adjust requested node latency to be
smaller than the delay.

Also fix BAP transport presentation delay value parsing, and parse also
the other BAP transport properties. Of these, transport latency value
needs to be taken into account in the total sink latency.
2023-02-19 22:44:23 +02:00
Barnabás Pőcze
934ab3036e treewide: use SPDX tags to specify copyright information
SPDX tags make the licensing information easy to understand and clear,
and they are machine parseable.

See https://spdx.dev for more information.
2023-02-16 10:54:48 +00:00
Pauli Virtanen
fb43a71543 bluez5: SupportedUUIDs is an adapter-specific property
The DBus adapter objects has both .Adapter1 and .Media1 interfaces.

Change handling of this so that we wait for both properties to appear.
2023-01-27 19:25:16 +02:00
Pauli Virtanen
7b54a891b4 bluez5: separate object manager for A2DP and BAP
BlueZ fails registering object managers containing A2DP endpoints if
controller is in LE-only mode.

Make the A2DP and BAP object managers separate, so that failure to
register one does not prevent registering the other.

Also rename some functions to indicate which ones deal with the legacy
BlueZ API.
2023-01-27 19:25:16 +02:00
Pauli Virtanen
d94832942e bluez5: allow codecs to share endpoints
AVDTP in principle allows 62 endpoints, but in practice it appears some
devices (Samsung Galaxy Buds2 Pro, Redmi Buds 3 Lite, probably others)
fail to connect A2DP when the number is somewhere above 24.  A2DP
connection works when initiated from the Central, but not when the
device itself does it, so these devices are not fully broken.  We should
reduce the number of registered A2DP endpoints to avoid running into
problems with such broken devices.

Some of our source codecs are the same actual codec with the same
configuration, and don't need separate source endpoints.

Allow codecs to not have a registered endpoint (fill_caps == NULL), and
tolerate codecs with the same endpoint name.  In codec switch, keep
track separately which of the codecs with the same endpoint name the
local endpoint is currently associated with.
2022-10-26 18:59:26 +03:00
Frédéric Danis
28b4fbecfb bluez5: Manage BAP linked transports
Multiple transport from the same device may share the same stream (CIS)
and group (CIG) but for different direction, e.g. a speaker and a
microphone. In this case they are linked.
In this case:
- On acquire, if another transport has already been acquired, the new
  transport should not call Acquire or TryAcquire but re-use values from
  the previously acquired transport,
- on release, the closing of transport fd and call to Release should be
  done only for the last transport.
2022-09-15 11:17:20 +00:00