Skip to main content

Prerequisites

Before you begin, set up your device and configure the DUT for HFP audio gateway functions.

Connect a remote device

To connect a remote device, run the following command from the bluetoothctl menu:
connect <bt_address>
Parameters <bt_address> is the Bluetooth address of the remote device. Example To connect to a paired remote device with <bt_address> 20:19:D8:36:90:40, run the following command:
connect 20:19:D8:36:90:40
Sample output
[Test]# connect 20:19:D8:36:90:40
Attempting to connect to 20:19:D8:36:90:40
[CHG] Device 20:19:D8:36:90:40 Connected: yes
[CHG] Device 20:19:D8:36:90:40 UUIDs: 00001108-0000-1000-8000-00805f9b34fb
[CHG] Device 20:19:D8:36:90:40 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device 20:19:D8:36:90:40 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb
[CHG] Device 20:19:D8:36:90:40 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb
[CHG] Device 20:19:D8:36:90:40 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 20:19:D8:36:90:40 ServicesResolved: yes
[CHG] Device 20:19:D8:36:90:40 Bonded: yes
[CHG] Device 20:19:D8:36:90:40 Paired: yes
[NEW] Endpoint /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1
[NEW] Transport /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1/fd1
Connection successful
[CHG] Transport /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1/fdl State: active
[CHG] Transport /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1/fd1 Volume: 0x0068 (104)
[CHG] Transport /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1/fd1 State: idle

Verify audio gateway functionality

To verify the audio gateway functionality, do the following:
The pactl tool isn’t available by default. Enable and build the tool on your device.
  1. List all cards, verify the available profiles of the BlueZ card, and find its active profile by running the following command:
    pactl list cards
    
    Sample output
    # pactl list cards
    Card #65
       Name: bluez_card.20_19_D8_36_90_40
       Driver: module-bluez5-device.c
       Owner Module: n/a
       Properties:
          device.api = "bluez5"
          device.bus = "bluetooth"
          media.class = "Audio/Device"
          device.name = "bluez_card.20_19_D8_36_90_40"
          device.description = " MyHeadset"
          device.alias = " MyHeadset"
          device.form_factor = "headset"
          device.string = "20:19:D8:36:90:40 "
          api.bluez5.icon = "audio-headset"
          api.bluez5.path = "/org/bluez/hci0/dev_20_19_D8_36_90_40"
          api.bluez5.address = "20:19:D8:36:90:40"
          api.bluez5.device = ""
          api.bluez5.class = "0x240404"
          api.bluez5.connection = "connected"
          device.icon_name = "audio-headset-bluetooth"
          bluez5.profile = "off"
          spa.object.id = "5"
          factory.id = "15"
          client.id = "33"
          object.id = "36"
          object.serial = "65"
       Profiles:
          off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
          a2dp-sink: High Fidelity Playback (A2DP Sink, codec SBC) (sinks: 1, sources: 0, priority: 18, available: yes)
          a2dp-sink-sbc_xq: High Fidelity Playback (A2DP Sink, codec SBC-XQ) (sinks: 1, sources: 0, priority: 17, available: yes)
          headset-head-unit-cvsd: Headset Head Unit (HSP/HFP, codec CVSD) (sinks: 1, sources: 1, priority: 2, available: yes)
          headset-head-unit: Headset Head Unit (HSP/HFP, codec mSBC) (sinks: 1, sources: 1, priority: 3, available: yes)
       Active Profile: a2dp-sink
       Ports:
          headset-input: Handsfree (type: Headset, priority: 0, latency offset: 0 usec, available)
             Properties:
                port.type = "headset"
             Part of profile(s): headset-head-unit-cvsd, headset-head-unit
          headset-output: Headset (type: Headset, priority: 0, latency offset: 0 usec, available)
             Properties:
                port.type = "headset"
             Part of profile(s): a2dp-sink, a2dp-sink-sbc_xq
          headset-hf-output: Handsfree (type: Headset, priority: 0, latency offset: 0 usec, available)
             Properties:
                port.type = "headset"
             Part of profile(s): headset-head-unit-cvsd, headset-head-unit
    
  2. If the active profile is a2dp-sink (Active Profile: a2dp-sink), switch the active profile to headset-head-unit by running the following command:
    pactl set-card-profile bluez_card.20_19_D8_36_90_40 headset-head-unit
    
    This setting ensures that the audio is streamed over SCO when multiple profiles are connected.
  3. Verify that the active profile of the BlueZ card is set to headset-head-unit by running the following command:
    pactl list cards
    
    Sample output
    # pactl list cards
    Card #65
       Name: bluez_card.20_19_D8_36_90_40
       Driver: module-bluez5-device.c
       Owner Module: n/a
       Properties:
          device.api = "bluez5"
          device.bus = "bluetooth"
          media.class = "Audio/Device"
          device.name = "bluez_card.20_19_D8_36_90_40"
          device.description = " MyHeadset"
          device.alias = " MyHeadset"
          device.form_factor = "headset"
          device.string = "20:19:D8:36:90:40 "
          api.bluez5.icon = "audio-headset"
          api.bluez5.path = "/org/bluez/hci0/dev_20_19_D8_36_90_40"
          api.bluez5.address = "20:19:D8:36:90:40"
          api.bluez5.device = ""
          api.bluez5.class = "0x240404"
          api.bluez5.connection = "connected"
          device.icon_name = "audio-headset-bluetooth"
          bluez5.profile = "off"
          spa.object.id = "5"
          factory.id = "15"
          client.id = "33"
          object.id = "36"
          object.serial = "65"
       Profiles:
          off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
          a2dp-sink: High Fidelity Playback (A2DP Sink, codec SBC) (sinks: 1, sources: 0, priority: 18, available: yes)
          a2dp-sink-sbc_xq: High Fidelity Playback (A2DP Sink, codec SBC-XQ) (sinks: 1, sources: 0, priority: 17, available: yes)
          headset-head-unit-cvsd: Headset Head Unit (HSP/HFP, codec CVSD) (sinks: 1, sources: 1, priority: 2, available: yes)
          headset-head-unit: Headset Head Unit (HSP/HFP, codec mSBC) (sinks: 1, sources: 1, priority: 3, available: yes)
       Active Profile: headset-head-unit
    
  4. Create a dummy SCO as follows: a. Run SSH. b. Play a WAV file by running the following command:
    paplay <file.wav> -v
    
    Example To play the AG_playback.wav file, run the following command:
    paplay AG_playback.wav -v
    
    Sample output
    sh-5.1# paplay AG_playback.wav -v
    Opening a playback stream with sample specification 's16le 2ch 44100Hz' and channel map 'front-left,front-right'.
    Connection established.
    Stream successfully created.
    Buffer metrics: maxlength=4194304, tlength=352800, prebuf=349276, minreq=3528
    Using sample spec 's16le 2ch 44100Hz', channel map 'front-left,front-right'.
    Connected to device bluez_output.20:19:D8:36:90:40 (index: 68, suspended: no).
    Stream started. 
    Time: 2.003 sec; Latency: 2042009 usec.
    
  5. Receive microphone data from the remote device by running the following command:
    parec -v --rate=<rate> --format=<format> --channels=<channel_number> --file-format=<file_format audio_filepath> --device=<device_name>
    
    Parameters
OptionsParameterDescriptionExample
--rate<rate>The specific sample rate to play the audio file.16000
--format<format>The specific sample format to play the audio file.s16le
--channels<channel_number>The specific number of channels to play the audio file.1
--file-format<file_format audio_filepath>The file format to play the audio file from a directory.wav /data/rec1.wav
--device<device_name>The device name of the source or sink to play the audio file.bluez_input.20:19:D8:36:90:40
To identify the device name from a list of sources, run the following command in SSH:
pactl list sources short
Sample output
sh-5.1# pactl list sources short
51      alsa_output.platform-sound.HiFi__Speaker__sink.monitor  PipeWire        s16le 2ch 48000Hz       SUSPENDED
52      alsa_input.platform-sound.HiFi__Mic1__source    PipeWire        s16le 2ch 48000Hz       SUSPENDED
65      bluez_input.20:19:D8:36:90:40   PipeWire        float32le 1ch 48000Hz   SUSPENDED
68      bluez_output.20:19:D8:36:90:40.monitor  PipeWire        float32le 2ch 48000Hz   SUSPENDED
Example To receive microphone data from a remote device for the example values listed in the table, run the following command:
parec -v --rate=16000 --format=s16le --channels=1 --file-format=wav /data/rec1.wav --device=bluez_input.20:19:D8:36:90:40
Sample output
sh-5.1# parec -v --rate=16000 --format=s16le --channels=1 --file-format=wav /data/rec1.wav --device=bluez_input.20:19:D8:36:90:40
Opening a recording stream with sample specification 's16le 1ch 16000Hz' and channel map 'mono'.
Connection established.
Stream successfully created.
Buffer metrics: maxlength=4194304, fragsize=64000
Using sample spec 's16le 1ch 16000Hz', channel map 'mono'.
Connected to device bluez_input.20:19:D8:36:90:40 (index: 65, suspended: no).
  1. Play the recorded microphone data and verify if the audio is clear.

Disconnect a remote device

To disconnect a remote device, run the following command from the bluetoothctl menu:
disconnect <bt_address>
Parameters <bt_address> is the Bluetooth address of the remote device. Example To disconnect a paired remote device with <bt_address> 20:19:D8:36:90:40, run the following command:
disconnect 20:19:D8:36:90:40
Sample output
[MyHeadset]# disconnect 20:19:D8:36:90:40
Attempting to disconnect from 20:19:D8:36:90:40
[DEL] Transport /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1/fd2
[DEL] Endpoint /org/bluez/hci0/dev_20_19_D8_36_90_40/sep1
[CHG] Device 20:19:D8:36:90:40 ServicesResolved: no
Successful disconnected
[CHG] Device 20:19:D8:36:90:40 Connected: no