1. 17 Nov, 2021 1 commit
    • Igor Kovalenko's avatar
      bluetooth: Fix device->adapter dependency while releasing discovery · 1a3ffd4c
      Igor Kovalenko authored and PulseAudio Marge Bot's avatar PulseAudio Marge Bot committed
      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>
      1a3ffd4c
  2. 06 Oct, 2021 3 commits
  3. 30 Jul, 2021 1 commit
  4. 28 Jul, 2021 2 commits
  5. 17 May, 2021 3 commits
    • Marijn Suijten's avatar
      bluetooth: Delay A2DP Absolute Volume setup until property is available · 25426bc0
      Marijn Suijten authored and PulseAudio Marge Bot's avatar PulseAudio Marge Bot committed
      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>
      25426bc0
    • Marijn Suijten's avatar
      bluetooth: Report a2dp_source volume changes to the source device · c6b77153
      Marijn Suijten authored and PulseAudio Marge Bot's avatar PulseAudio Marge Bot committed
      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>
      c6b77153
    • Marijn Suijten's avatar
      bluetooth: Update source software volume on AVRCP SetAbsoluteVolume · 710a35cd
      Marijn Suijten authored and PulseAudio Marge Bot's avatar PulseAudio Marge Bot committed
      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>
      710a35cd
  6. 05 Apr, 2021 2 commits
    • James Bottomley's avatar
      bluetooth: add wideband audio codec negotiation to HFP · 4444ecad
      James Bottomley authored and PulseAudio Marge Bot's avatar PulseAudio Marge Bot committed
      
      
      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's avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
      Part-of: <!507>
      4444ecad
    • James Bottomley's avatar
      bluetooth: add support for mSBC codec · f22cfa8f
      James Bottomley authored and PulseAudio Marge Bot's avatar PulseAudio Marge Bot committed
      
      
      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's avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
      Part-of: <!507>
      f22cfa8f
  7. 03 Apr, 2021 1 commit
    • Igor Kovalenko's avatar
      bluetooth: prioritize native backend HFP HF connection · 1f204a13
      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>
      1f204a13
  8. 17 Mar, 2021 1 commit
    • Marijn Suijten's avatar
      bluetooth: Set up hardware gain control if init volume is received late · 8db4dff2
      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>
      8db4dff2
  9. 16 Mar, 2021 2 commits
    • Marijn Suijten's avatar
      bluetooth: Perform software attenuation until HF/HS reports gain control · d510ddc7
      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>
      d510ddc7
    • Marijn Suijten's avatar
      bluetooth: Move attenuation decision to shared function · 9c847b16
      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>
      9c847b16
  10. 23 Feb, 2021 2 commits
    • Igor Kovalenko's avatar
      bluetooth: prefer headset HFP HF connection with native backend · 815dd2d6
      Igor Kovalenko authored and Igor Kovalenko's avatar Igor Kovalenko committed
      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>
      815dd2d6
    • James Bottomley's avatar
      bluetooth: separate HSP and HFP · 66ed99a1
      James Bottomley authored and Igor Kovalenko's avatar Igor Kovalenko committed
      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>
      66ed99a1
  11. 01 Feb, 2021 1 commit
  12. 22 Jan, 2021 1 commit
    • Sanchayan Maity's avatar
      bluetooth: ldac: Use format as FLOAT32LE · c6862152
      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>
      c6862152
  13. 21 Jan, 2021 2 commits
  14. 19 Jan, 2021 10 commits
    • Sanchayan Maity's avatar
      bluetooth: Register an endpoint according to encode or decode support · ed44fa18
      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>
      ed44fa18
    • Sanchayan Maity's avatar
      bluetooth: Prevent registration of an unavailable codec at runtime · 8289bdb7
      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>
      8289bdb7
    • Sanchayan Maity's avatar
      bluetooth: Introduce a can_be_supported API for A2DP codecs · d6149364
      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>
      d6149364
    • Sanchayan Maity's avatar
      bluetooth: Add support for getting current active codec · 60441697
      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>
      60441697
    • Sanchayan Maity's avatar
      bluetooth: Add support for getting list of negotiated codecs · 2fea838e
      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>
      2fea838e
    • Sanchayan Maity's avatar
      bluetooth: Add aptX support via GStreamer · 33779648
      Sanchayan Maity authored
      Part-of: <!440>
      33779648
    • Sanchayan Maity's avatar
      bluetooth: Add LDAC support via GStreamer · ef4762a4
      Sanchayan Maity authored
      Part-of: <!440>
      ef4762a4
    • Sanchayan Maity's avatar
      bluetooth: Add a generic GStreamer codec module · a407e9aa
      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>
      a407e9aa
    • Sanchayan Maity's avatar
      bluetooth: Support A2DP codec switching via messaging API · 3447335d
      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>
      3447335d
    • Sanchayan Maity's avatar
      bluez5-util: Add support for using RegisterApplication D-Bus API · 5284b450
      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>
      5284b450
  15. 19 Mar, 2020 1 commit
  16. 24 Jul, 2019 1 commit
    • pali's avatar
      bluetooth: Fix usage of RTP structures in SBC codec · 9e70d052
      pali authored and Tanu Kaskinen's avatar Tanu Kaskinen committed
      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.
      9e70d052
  17. 12 Apr, 2019 2 commits
    • pali's avatar
      bluetooth: Set correct endianity of audio samples for SBC codec · 1b6e5b85
      pali authored and Tanu Kaskinen's avatar Tanu Kaskinen committed
      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
      1b6e5b85
    • pali's avatar
      bluetooth: Modular API for A2DP codecs · 106aa914
      pali authored and Tanu Kaskinen's avatar Tanu Kaskinen committed
      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.
      106aa914
  18. 27 Jul, 2018 1 commit
  19. 21 Jun, 2018 1 commit
  20. 05 Sep, 2017 1 commit
    • Colin Leroy's avatar
      cli-command: don't exit on "module already loaded" errors · f0dfddea
      Colin Leroy authored and Tanu Kaskinen's avatar Tanu Kaskinen committed
      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.
      f0dfddea
  21. 28 Mar, 2017 1 commit
    • Tanu Kaskinen's avatar
      bluez5-util: fix profile waiting logic · cb78d6f5
      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
      cb78d6f5