- 17 Nov, 2021 1 commit
-
-
Change d7f95170 added a dependency on device adapter pointer being valid while checking if bluetooth profile is supported by device. When adapter object is released, each device holding pointer to adapter being released is notified to reset that to NULL. Since adapter objects are released first when discovery object is unreferenced, each device will have adapter pointer reset before the time device objects are released. Fix observed crash by examining device adapter pointer. If it is NULL report that device does not support any bluetooth profile instead of looking at UUIDs supported by adapter. Part-of: <!646>
-
- 06 Oct, 2021 3 commits
-
-
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: <!638>
-
Part-of: <!638>
-
The remote device list of UUIDs reflects which profiles are supported by the remote device alone. We currently rely solely on this list to decide if a certain card profile is supported, and thus should be created and get connected. This used to be accurate when the Bluetooth modules were first written, but now BlueZ is more dynamic and local profile support can be added or removed during runtime. The adapter's list of UUIDs is an accurate representation of the profiles supported by the local host at a certain moment. This commit combines the list of UUIDs supported by remote device and the list of UUIDs supported by the local host to determined whether a Bluetooth profile is actually supported or not, and whether it should be expected to get connected during device connection. Part-of: <!638>
-
- 30 Jul, 2021 1 commit
-
-
Try to register profile support again after RegisterProfile fails, when BlueZ indicates no one else is implementing the profiles we are interested in. Ideally this would rely on a list of UUIDs supported by the profile manager instead of the adapter, but BlueZ has no such API. Part-of: <pulseaudio/pulseaudio!593>
-
- 28 Jul, 2021 2 commits
-
-
Marijn Suijten authored
HF indicator 2 (see [assigned-numbers], Hands-Free Profile) is able to report battery percentage at 1% intervals (in range [0, 100]), contrary to the `+XAPL` `+IPHONEACCEV` extension which only supports 10% increments. This does not guarantee increased granularity however, as peers may still be limited to imprecise battery measurements internally or round to coarser percentages. Supporting both additionally broadens the range of devices for which PA can report its battery level. [assigned-numbers]: https://www.bluetooth.com/specifications/assigned-numbers/ Part-of: <pulseaudio/pulseaudio!482>
-
Marijn Suijten authored
The previous commit parses both battery level and dock status (if only for printing to logs). Make sure bit `2` is set in the `+XAPL=` reply to signify support for reading this, too. Part-of: <!482>
-
- 17 May, 2021 3 commits
-
-
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: <!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: <!239>
-
The A2DP spec mandates that the audio rendering device - the device receiving audio, in our case a `pa_source` - is responsible for performing attenuation: AVRCP v1.6.2, §5.8: The SetAbsoluteVolume command is used to set an absolute volume to be used by the rendering device. BlueZ models this call as a change of the `Volume` property on the `org.bluez.MediaTransport1` interface. Supporting Absolute Volume is optional but BlueZ unconditionally reports feature category 2 in its profile, mandating support. Hence remote devices (ie. a phone) playing back audio to a machine running PulseAudio assume volume is to be changed through SetAbsoluteVolume, without performing any local attenuation. Future changes will implement this feature the other way around: setting an initial value for the `Volume` property as well as propagating `pa_source` volume changes back to the peer. Part-of: <!239>
-
- 05 Apr, 2021 2 commits
-
-
The HFP protocol supports the ability to negotiate codecs if that is supported by both AG and HF. This patch adds advertising of codec negotiation support and the ability to negotiate a codec change. The only currently supported extra codec (as of HF 1.7.1) is mSBC. mSBC requires that the transmission be done over an eSCO link with Transparent Data. The linux kernel ensures the former, but we have to manually set the socket to transparent data. Signed-off-by:
James Bottomley <James.Bottomley@HansenPartnership.com> Part-of: <!507>
-
Adding processing support for the mSBC codec is somewhat problematic, because, although it is a SBC codec, the a2dp handling can't simply be reused because the codec is used on an eSCO link with transparent data, meaning the transmission unit has to be 48 bytes (fragmenting the codec packets) and reassembly and boundary detection is required to be done by the implementation. Therefore we have to implement separate render and push routines for msbc that do this fragmentation. Fragmentation is done by emulating circular buffers. The receive (push) buffer is easy, since the mSBC packet size is 60, simply have a buffer of this size in the sbc_info area where the fragments are reassembled. Once we have a full 60 bytes, decode and restart from zero. The send (render) buffer is more problematic, since the transmit must be done from contiguous memory. This means that the buffer must be the lowest common multiple of the transmission unit and the packet size. This value is 240 since 240/48 == 5 and 240/60 == 4. So the buffer pointers are reset at 240 which is a whole number of both rendered packets and eSCO transmission units. Signed-off-by:
James Bottomley <James.Bottomley@HansenPartnership.com> Part-of: <!507>
-
- 03 Apr, 2021 1 commit
-
-
Igor Kovalenko authored
Bluez prepends newly registered profile to a list of supported profiles, and new peer profile connections are attempted in reverse order of profile registration. Currently native backend would register HFP AG profile before HSP AG profile. When peer supports both HFP HF and HSP HS profiles, this registration order causes extra HSP HS connection attempt before native backend would reject it to make sure peer is reconnected with HFP HF profile. Reorder HSP AG profile registration before HFP AG to make sure peer supporting both profiles connects with HFP HF profile first. Part-of: <!534>
-
- 17 Mar, 2021 1 commit
-
-
Marijn Suijten authored
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: d510ddc7 ("bluetooth: Perform software attenuation until HF/HS reports gain control") Part-of: <!528>
-
- 16 Mar, 2021 2 commits
-
-
Marijn Suijten authored
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: <!521>
-
Marijn Suijten authored
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: <!521>
-
- 23 Feb, 2021 2 commits
-
-
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: <!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: <!491>
-
- 01 Feb, 2021 1 commit
-
-
Part-of: <!476>
-
- 22 Jan, 2021 1 commit
-
-
Sanchayan Maity authored
LDAC encoder already supports S16, S24, S32 and F32LE. Using FLOAT32LE for the sample format would avoid the additional call for conversion to pa_sconv_s32le_from_float32ne. perf tool shows this as being the function called frequently after encode. So, just avoid this by using sample format as F32LE. Part-of: <!486>
-
- 21 Jan, 2021 2 commits
-
-
Marijn Suijten authored
Part-of: <!479>
-
Marijn Suijten authored
As suggested in [1]: This way it is possible for a codec to have both the encoding and decoding part optional, instead of getting both or nothing (where PA theoretically supports both). In addition this cleans up code that was previously checking the existence of a function pointer, or nothing at all (switch_codec). [1]: !440 (comment 768146) Part-of: <!479>
-
- 19 Jan, 2021 10 commits
-
-
Sanchayan Maity authored
As we now support codecs other than SBC, we might have codec which does not have an encode or a decode capability. Specifically, in the case of LDAC there isn't a known decoder implementation available. For such a case, we should not register the corresponding endpoint. In case of LDAC, as decoding cannot be supported, we should not register a sink endpoint or vice versa in the other scenario. To do this, we check if encode_buffer or decode_buffer entry for a codec has been set in pa_a2dp_codec and accordingly prevent or allow it's registration. Part-of: <!440>
-
Sanchayan Maity authored
When it comes to codecs provided via GStreamer, we register all codecs if GStreamer option is enabled for bluez5 via meson. However, the GStreamer plugin required for the codec might not be present on the system. This results in the codec being available for registration with the bluez stack or selection by the user, but, trying to use the said codec then fails. To prevent the above, we now use the can_be_supported codec API to check if the codec is usable and if not, we do not register the said codec and also prevent users from switching to it. Part-of: <!440>
-
Sanchayan Maity authored
This API internally checks if a requested codec can be supported on the system. This is especially required for codecs supported via GStreamer where the availability of a plugin decides if the said codec can be supported. This will be used to prevent registration of a codec which the remote endpoint device might be able to support, but, PulseAudio can't as the codec is not available on the system due to the absence of a plugin. We can also prevent listing or switching to an unavailable codec. Note that the codec negotiation happens with the bluez stack even before a device is connected. Because of this, we need to make sure that gst_init is called before checking for the availability of a plugin. Since module-bluez5-device gets loaded only after a connection to the device has been established, doing the gst_init in that or one of the bluetooth modules is not feasible. Part-of: <!440>
-
Sanchayan Maity authored
For example, using the following on the command line will return the current codec for a bluetooth device pacmd send-message /card/bluez_card.4C_BC_98_80_01_9B/bluez get-codec where 4C_BC_98_80_01_9B is the bluetooth device. Part-of: <!440>
-
Sanchayan Maity authored
For example, using the following on the command line will return the list of possible codecs for a bluetooth device pacmd send-message /card/bluez_card.4C_BC_98_80_01_9B/bluez list-codecs where 4C_BC_98_80_01_9B is the bluetooth device. Part-of: <!440>
-
Sanchayan Maity authored
Part-of: <!440>
-
Sanchayan Maity authored
Part-of: <!440>
-
Sanchayan Maity authored
This adds a generic gstreamer codec module based on which other bluetooth codecs viz. aptX, aptX-HD, LDAC and AAC can be supported. The GStreamer codec plugins used here themselves depend on the native codec implementation. aptX/aptX-HD -> libopenaptx LDAC -> libldac AAC -> Fraunhofer FDK AAC Part-of: <!440>
-
Sanchayan Maity authored
This uses the messaging API to initiate a codec switch. While a particular codec might be applicable only for a particular profile, for eg. aptX can only be applicable for A2DP sink or source and not for let's say HSP, the codec switching logic has not been tied to the logic for switching profiles. Codec can be switched by running the following on the command line. pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec{"ldac_hq"} pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"ldac_mq"} pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"ldac_sq"} pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"aptx_hd"} pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"aptx"} pacmd send-message /card/bluez_card.XX_XX_XX_XX_XX_XX/bluez switch-codec {"sbc"} Codec name passed above is matched against pa_a2dp_codec->name. Note that the match is case sensitive. XX_XX_XX_XX_XX_XX needs to be substituted with the actual bluetooth device id. Part-of: <!440>
-
Sanchayan Maity authored
A2DP codec switching needs new version of bluez as older version does not provide needed org.freedesktop.DBus.ObjectManager and RegisterApplication DBus APIs. As a preparation for the next step of adding codecs and then codec switching, add support for using the new API. Getting list of supported codecs by remote device is supported only by new version of bluez daemon. If the RegisterApplication API fails, we fallback to the older RegisterEndpoint API and only register the SBC codec. For more information, see https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/media-api.txt This changeset has been taken from Pali Rohár's A2DP codec patch series but separated out to only include the D-Bus specific changes. Part-of: <!440>
-
- 19 Mar, 2020 1 commit
-
-
pali authored
Support for multiple codecs needs to use a new Bluez API which pulseaudio does not implement yet. So register explicitly only SBC codec which is provided by pulseaudio A2DP codec API.
-
- 24 Jul, 2019 1 commit
-
-
Rename struct rtp_payload to rtp_sbc_payload as it is specific for SBC codec payload. Add proper checks for endianity in rtp.h header and use uint8_t type where appropriated. Field frame_count is only 4 bit number, so add checks to prevent overflow. And because is_fragmented field is not parsed by decoder there is no support for decoding fragmented SBC frames. So throw an error in this case.
-
- 12 Apr, 2019 2 commits
-
-
Pulseaudio SBC codec defines that audio samples are in PA_SAMPLE_S16LE format which is little endian. But libsbc library expects audio samples by default in host endianity which is big endian on big endian system. So SBC support on big endian system is broken. To fix this problem tell libsbc library that audio samples are in little endian to match PA_SIMPLE_S16LE sample format. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=91359
-
This patch introduce new modular API for bluetooth A2DP codecs. Its benefits are: * bluez5-util and module-bluez5-device does not contain any codec specific code, they are codec independent. * For adding new A2DP codec it is needed just to adjust one table in a2dp-codec-util.c file. All codec specific functions are in separate codec file. * Support for backchannel (microphone voice). Some A2DP codecs (like FastStream or aptX Low Latency) are bi-directional and can be used for both music playback and audio call. * Support for more configurations per codec. This allows to implement low quality mode of some codec together with high quality. Current SBC codec implementation was moved from bluez5-util and module-bluez5-device to its own file and converted to this new A2DP API.
-
- 27 Jul, 2018 1 commit
-
-
There is no need to mention a module argument is valid only when using BlueZ 5 now that we don't support BlueZ 4 anymore.
-
- 21 Jun, 2018 1 commit
-
-
BlueZ 4 is no longer supported by BlueZ community for a long long time, also by moving to BlueZ 5 it should make it even more clearer that BlueZ 4 is no longer an option.
-
- 05 Sep, 2017 1 commit
-
-
Some modules may only be loaded once, and trying to load them twice from default.pa makes PulseAudio startup fail. While that could be considered a user error, it's nicer to not be so strict. It's not necessarily easy to figure what went wrong, if for example the user plays with RAOP and adds module-raop-discover to default.pa, which first works fine, but suddenly stops working when the user at some point enables RAOP support in paprefs. Enabling RAOP in paprefs makes module-gconf load the module too, so the module gets loaded twice. This patch adds a way to differentiate module load errors, and make cli-command ignore the error when the module is already loaded.
-
- 28 Mar, 2017 1 commit
-
-
Tanu Kaskinen authored
There were two bugs in the old logic. The first one: If a device has two profiles, the old code would start the wait timer when the first profile connects, but when the second profile connects, the timer would not get stopped and the CONNECTION_CHANGED hook would not get fired, because the code for that was inside an if block that only gets executed when the first profile connects. As a result, module-bluez5-device loading would always be delayed until the wait timeout expires. The second bug: A crash was observed in device_start_waiting_for_profiles(). That function is called whenever the connected profile count changes from 0 to 1. The function also has an assertion that checks that the timer is not running when the function is called. That assertion crashed in the following scenario with a headset that supports HSP and A2DP: 1. First HSP gets connected. The timer is started. 2. Then HSP gets disconnected for some reason. The timer is still running. 3. Then A2DP gets connected. device_start_waiting_for_profiles() is called, because the connected profile count changed from 0 to 1 again. The timer is already running, so the assertion fails. First I thought I'd remove the assertion from device_start_waiting_for_profiles() and just restart the timer on the second call, but then I figured that when the device returns to the "everything disconnected" state in step 2, it would be better to stop the timer. The purpose of the timer is to delay the notification of the device becoming connected, but if the device becomes disconnected during the waiting period, the notification doesn't make sense any more, and therefore the timer doesn't make sense either. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=100237
-